diff options
Diffstat (limited to 'drivers')
228 files changed, 10834 insertions, 6848 deletions
diff --git a/drivers/Makefile b/drivers/Makefile index 920c975bb6d4..26ca9031ea49 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -58,7 +58,7 @@ obj-$(CONFIG_GAMEPORT) += input/gameport/ | |||
58 | obj-$(CONFIG_INPUT) += input/ | 58 | obj-$(CONFIG_INPUT) += input/ |
59 | obj-$(CONFIG_I2O) += message/ | 59 | obj-$(CONFIG_I2O) += message/ |
60 | obj-$(CONFIG_RTC_LIB) += rtc/ | 60 | obj-$(CONFIG_RTC_LIB) += rtc/ |
61 | obj-$(CONFIG_I2C) += i2c/ | 61 | obj-y += i2c/ |
62 | obj-$(CONFIG_W1) += w1/ | 62 | obj-$(CONFIG_W1) += w1/ |
63 | obj-$(CONFIG_HWMON) += hwmon/ | 63 | obj-$(CONFIG_HWMON) += hwmon/ |
64 | obj-$(CONFIG_PHONE) += telephony/ | 64 | obj-$(CONFIG_PHONE) += telephony/ |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 2f2e7964226d..c4efc0c17f8f 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
@@ -433,49 +433,6 @@ static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file) | |||
433 | PDE(inode)->data); | 433 | PDE(inode)->data); |
434 | } | 434 | } |
435 | 435 | ||
436 | static ssize_t | ||
437 | acpi_processor_write_performance(struct file *file, | ||
438 | const char __user * buffer, | ||
439 | size_t count, loff_t * data) | ||
440 | { | ||
441 | int result = 0; | ||
442 | struct seq_file *m = file->private_data; | ||
443 | struct acpi_processor *pr = m->private; | ||
444 | struct acpi_processor_performance *perf; | ||
445 | char state_string[12] = { '\0' }; | ||
446 | unsigned int new_state = 0; | ||
447 | struct cpufreq_policy policy; | ||
448 | |||
449 | |||
450 | if (!pr || (count > sizeof(state_string) - 1)) | ||
451 | return -EINVAL; | ||
452 | |||
453 | perf = pr->performance; | ||
454 | if (!perf) | ||
455 | return -EINVAL; | ||
456 | |||
457 | if (copy_from_user(state_string, buffer, count)) | ||
458 | return -EFAULT; | ||
459 | |||
460 | state_string[count] = '\0'; | ||
461 | new_state = simple_strtoul(state_string, NULL, 0); | ||
462 | |||
463 | if (new_state >= perf->state_count) | ||
464 | return -EINVAL; | ||
465 | |||
466 | cpufreq_get_policy(&policy, pr->id); | ||
467 | |||
468 | policy.cpu = pr->id; | ||
469 | policy.min = perf->states[new_state].core_frequency * 1000; | ||
470 | policy.max = perf->states[new_state].core_frequency * 1000; | ||
471 | |||
472 | result = cpufreq_set_policy(&policy); | ||
473 | if (result) | ||
474 | return result; | ||
475 | |||
476 | return count; | ||
477 | } | ||
478 | |||
479 | static void acpi_cpufreq_add_file(struct acpi_processor *pr) | 436 | static void acpi_cpufreq_add_file(struct acpi_processor *pr) |
480 | { | 437 | { |
481 | struct proc_dir_entry *entry = NULL; | 438 | struct proc_dir_entry *entry = NULL; |
@@ -487,10 +444,9 @@ static void acpi_cpufreq_add_file(struct acpi_processor *pr) | |||
487 | 444 | ||
488 | /* add file 'performance' [R/W] */ | 445 | /* add file 'performance' [R/W] */ |
489 | entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE, | 446 | entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE, |
490 | S_IFREG | S_IRUGO | S_IWUSR, | 447 | S_IFREG | S_IRUGO, |
491 | acpi_device_dir(device)); | 448 | acpi_device_dir(device)); |
492 | if (entry){ | 449 | if (entry){ |
493 | acpi_processor_perf_fops.write = acpi_processor_write_performance; | ||
494 | entry->proc_fops = &acpi_processor_perf_fops; | 450 | entry->proc_fops = &acpi_processor_perf_fops; |
495 | entry->data = acpi_driver_data(device); | 451 | entry->data = acpi_driver_data(device); |
496 | entry->owner = THIS_MODULE; | 452 | entry->owner = THIS_MODULE; |
diff --git a/drivers/atm/adummy.c b/drivers/atm/adummy.c index 8d60c4eb54fe..2ebd07f2ef81 100644 --- a/drivers/atm/adummy.c +++ b/drivers/atm/adummy.c | |||
@@ -6,7 +6,6 @@ | |||
6 | #include <linux/version.h> | 6 | #include <linux/version.h> |
7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
8 | #include <linux/skbuff.h> | 8 | #include <linux/skbuff.h> |
9 | #include <linux/pci.h> | ||
10 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
11 | #include <linux/types.h> | 10 | #include <linux/types.h> |
12 | #include <linux/string.h> | 11 | #include <linux/string.h> |
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 18dba8e78da7..92428e55b0c2 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -226,12 +226,10 @@ static int device_probe_drivers(void *data) | |||
226 | * | 226 | * |
227 | * Walk the list of drivers that the bus has and call | 227 | * Walk the list of drivers that the bus has and call |
228 | * driver_probe_device() for each pair. If a compatible | 228 | * driver_probe_device() for each pair. If a compatible |
229 | * pair is found, break out and return. If the bus specifies | 229 | * pair is found, break out and return. |
230 | * multithreaded probing, walking the list of drivers is done | ||
231 | * on a probing thread. | ||
232 | * | 230 | * |
233 | * Returns 1 if the device was bound to a driver; | 231 | * Returns 1 if the device was bound to a driver; |
234 | * 0 if no matching device was found or multithreaded probing is done; | 232 | * 0 if no matching device was found; |
235 | * -ENODEV if the device is not registered. | 233 | * -ENODEV if the device is not registered. |
236 | * | 234 | * |
237 | * When called for a USB interface, @dev->parent->sem must be held. | 235 | * When called for a USB interface, @dev->parent->sem must be held. |
@@ -239,7 +237,6 @@ static int device_probe_drivers(void *data) | |||
239 | int device_attach(struct device * dev) | 237 | int device_attach(struct device * dev) |
240 | { | 238 | { |
241 | int ret = 0; | 239 | int ret = 0; |
242 | struct task_struct *probe_task = ERR_PTR(-ENOMEM); | ||
243 | 240 | ||
244 | down(&dev->sem); | 241 | down(&dev->sem); |
245 | if (dev->driver) { | 242 | if (dev->driver) { |
@@ -251,12 +248,7 @@ int device_attach(struct device * dev) | |||
251 | ret = 0; | 248 | ret = 0; |
252 | } | 249 | } |
253 | } else { | 250 | } else { |
254 | if (dev->bus->multithread_probe) | 251 | ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); |
255 | probe_task = kthread_run(device_probe_drivers, dev, | ||
256 | "probe-%s", dev->bus_id); | ||
257 | if(IS_ERR(probe_task)) | ||
258 | ret = bus_for_each_drv(dev->bus, NULL, dev, | ||
259 | __device_attach); | ||
260 | } | 252 | } |
261 | up(&dev->sem); | 253 | up(&dev->sem); |
262 | return ret; | 254 | return ret; |
@@ -383,33 +375,6 @@ void driver_detach(struct device_driver * drv) | |||
383 | } | 375 | } |
384 | } | 376 | } |
385 | 377 | ||
386 | #ifdef CONFIG_PCI_MULTITHREAD_PROBE | ||
387 | static int __init wait_for_probes(void) | ||
388 | { | ||
389 | DEFINE_WAIT(wait); | ||
390 | |||
391 | printk(KERN_INFO "%s: waiting for %d threads\n", __FUNCTION__, | ||
392 | atomic_read(&probe_count)); | ||
393 | if (!atomic_read(&probe_count)) | ||
394 | return 0; | ||
395 | while (atomic_read(&probe_count)) { | ||
396 | prepare_to_wait(&probe_waitqueue, &wait, TASK_UNINTERRUPTIBLE); | ||
397 | if (atomic_read(&probe_count)) | ||
398 | schedule(); | ||
399 | } | ||
400 | finish_wait(&probe_waitqueue, &wait); | ||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | core_initcall_sync(wait_for_probes); | ||
405 | postcore_initcall_sync(wait_for_probes); | ||
406 | arch_initcall_sync(wait_for_probes); | ||
407 | subsys_initcall_sync(wait_for_probes); | ||
408 | fs_initcall_sync(wait_for_probes); | ||
409 | device_initcall_sync(wait_for_probes); | ||
410 | late_initcall_sync(wait_for_probes); | ||
411 | #endif | ||
412 | |||
413 | EXPORT_SYMBOL_GPL(device_bind_driver); | 378 | EXPORT_SYMBOL_GPL(device_bind_driver); |
414 | EXPORT_SYMBOL_GPL(device_release_driver); | 379 | EXPORT_SYMBOL_GPL(device_release_driver); |
415 | EXPORT_SYMBOL_GPL(device_attach); | 380 | EXPORT_SYMBOL_GPL(device_attach); |
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index 5b684fddcc03..4941ddb78939 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c | |||
@@ -145,6 +145,7 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge) | |||
145 | void *addr = agp_generic_alloc_page(agp_bridge); | 145 | void *addr = agp_generic_alloc_page(agp_bridge); |
146 | u32 temp; | 146 | u32 temp; |
147 | 147 | ||
148 | global_flush_tlb(); | ||
148 | if (!addr) | 149 | if (!addr) |
149 | return NULL; | 150 | return NULL; |
150 | 151 | ||
@@ -160,6 +161,7 @@ static void ali_destroy_page(void * addr) | |||
160 | if (addr) { | 161 | if (addr) { |
161 | global_cache_flush(); /* is this really needed? --hch */ | 162 | global_cache_flush(); /* is this really needed? --hch */ |
162 | agp_generic_destroy_page(addr); | 163 | agp_generic_destroy_page(addr); |
164 | global_flush_tlb(); | ||
163 | } | 165 | } |
164 | } | 166 | } |
165 | 167 | ||
diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c index b0acf41c0db9..aa8f3a39a704 100644 --- a/drivers/char/agp/alpha-agp.c +++ b/drivers/char/agp/alpha-agp.c | |||
@@ -173,7 +173,7 @@ alpha_core_agp_setup(void) | |||
173 | /* | 173 | /* |
174 | * Build a fake pci_dev struct | 174 | * Build a fake pci_dev struct |
175 | */ | 175 | */ |
176 | pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); | 176 | pdev = alloc_pci_dev(); |
177 | if (!pdev) | 177 | if (!pdev) |
178 | return -ENOMEM; | 178 | return -ENOMEM; |
179 | pdev->vendor = 0xffff; | 179 | pdev->vendor = 0xffff; |
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index f902d71947ba..45aeb917ec63 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c | |||
@@ -51,28 +51,6 @@ int agp_memory_reserved; | |||
51 | */ | 51 | */ |
52 | EXPORT_SYMBOL_GPL(agp_memory_reserved); | 52 | EXPORT_SYMBOL_GPL(agp_memory_reserved); |
53 | 53 | ||
54 | #if defined(CONFIG_X86) | ||
55 | int map_page_into_agp(struct page *page) | ||
56 | { | ||
57 | int i; | ||
58 | i = change_page_attr(page, 1, PAGE_KERNEL_NOCACHE); | ||
59 | /* Caller's responsibility to call global_flush_tlb() for | ||
60 | * performance reasons */ | ||
61 | return i; | ||
62 | } | ||
63 | EXPORT_SYMBOL_GPL(map_page_into_agp); | ||
64 | |||
65 | int unmap_page_from_agp(struct page *page) | ||
66 | { | ||
67 | int i; | ||
68 | i = change_page_attr(page, 1, PAGE_KERNEL); | ||
69 | /* Caller's responsibility to call global_flush_tlb() for | ||
70 | * performance reasons */ | ||
71 | return i; | ||
72 | } | ||
73 | EXPORT_SYMBOL_GPL(unmap_page_from_agp); | ||
74 | #endif | ||
75 | |||
76 | /* | 54 | /* |
77 | * Generic routines for handling agp_memory structures - | 55 | * Generic routines for handling agp_memory structures - |
78 | * They use the basic page allocation routines to do the brunt of the work. | 56 | * They use the basic page allocation routines to do the brunt of the work. |
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 55392a45a14b..9c69f2e761f5 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
@@ -186,8 +186,9 @@ static void *i8xx_alloc_pages(void) | |||
186 | return NULL; | 186 | return NULL; |
187 | 187 | ||
188 | if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) { | 188 | if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) { |
189 | change_page_attr(page, 4, PAGE_KERNEL); | ||
189 | global_flush_tlb(); | 190 | global_flush_tlb(); |
190 | __free_page(page); | 191 | __free_pages(page, 2); |
191 | return NULL; | 192 | return NULL; |
192 | } | 193 | } |
193 | global_flush_tlb(); | 194 | global_flush_tlb(); |
@@ -209,7 +210,7 @@ static void i8xx_destroy_pages(void *addr) | |||
209 | global_flush_tlb(); | 210 | global_flush_tlb(); |
210 | put_page(page); | 211 | put_page(page); |
211 | unlock_page(page); | 212 | unlock_page(page); |
212 | free_pages((unsigned long)addr, 2); | 213 | __free_pages(page, 2); |
213 | atomic_dec(&agp_bridge->current_memory_agp); | 214 | atomic_dec(&agp_bridge->current_memory_agp); |
214 | } | 215 | } |
215 | 216 | ||
@@ -315,9 +316,6 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) | |||
315 | struct agp_memory *new; | 316 | struct agp_memory *new; |
316 | void *addr; | 317 | void *addr; |
317 | 318 | ||
318 | if (pg_count != 1 && pg_count != 4) | ||
319 | return NULL; | ||
320 | |||
321 | switch (pg_count) { | 319 | switch (pg_count) { |
322 | case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge); | 320 | case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge); |
323 | global_flush_tlb(); | 321 | global_flush_tlb(); |
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 0c9dab557c94..6cd7373dcdf4 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c | |||
@@ -320,11 +320,11 @@ static int __devinit agp_nvidia_probe(struct pci_dev *pdev, | |||
320 | u8 cap_ptr; | 320 | u8 cap_ptr; |
321 | 321 | ||
322 | nvidia_private.dev_1 = | 322 | nvidia_private.dev_1 = |
323 | pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1)); | 323 | pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1)); |
324 | nvidia_private.dev_2 = | 324 | nvidia_private.dev_2 = |
325 | pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2)); | 325 | pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2)); |
326 | nvidia_private.dev_3 = | 326 | nvidia_private.dev_3 = |
327 | pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0)); | 327 | pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0)); |
328 | 328 | ||
329 | if (!nvidia_private.dev_1 || !nvidia_private.dev_2 || !nvidia_private.dev_3) { | 329 | if (!nvidia_private.dev_1 || !nvidia_private.dev_2 || !nvidia_private.dev_3) { |
330 | printk(KERN_INFO PFX "Detected an NVIDIA nForce/nForce2 " | 330 | printk(KERN_INFO PFX "Detected an NVIDIA nForce/nForce2 " |
@@ -443,6 +443,9 @@ static int __init agp_nvidia_init(void) | |||
443 | static void __exit agp_nvidia_cleanup(void) | 443 | static void __exit agp_nvidia_cleanup(void) |
444 | { | 444 | { |
445 | pci_unregister_driver(&agp_nvidia_pci_driver); | 445 | pci_unregister_driver(&agp_nvidia_pci_driver); |
446 | pci_dev_put(nvidia_private.dev_1); | ||
447 | pci_dev_put(nvidia_private.dev_2); | ||
448 | pci_dev_put(nvidia_private.dev_3); | ||
446 | } | 449 | } |
447 | 450 | ||
448 | module_init(agp_nvidia_init); | 451 | module_init(agp_nvidia_init); |
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index 3d83b461ccad..f4562cc22343 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c | |||
@@ -329,7 +329,7 @@ parisc_agp_setup(void __iomem *ioc_hpa, void __iomem *lba_hpa) | |||
329 | struct agp_bridge_data *bridge; | 329 | struct agp_bridge_data *bridge; |
330 | int error = 0; | 330 | int error = 0; |
331 | 331 | ||
332 | fake_bridge_dev = kmalloc(sizeof (struct pci_dev), GFP_KERNEL); | 332 | fake_bridge_dev = alloc_pci_dev(); |
333 | if (!fake_bridge_dev) { | 333 | if (!fake_bridge_dev) { |
334 | error = -ENOMEM; | 334 | error = -ENOMEM; |
335 | goto fail; | 335 | goto fail; |
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c index ee8f50edde1b..cda608c42bea 100644 --- a/drivers/char/agp/sgi-agp.c +++ b/drivers/char/agp/sgi-agp.c | |||
@@ -47,9 +47,8 @@ static void *sgi_tioca_alloc_page(struct agp_bridge_data *bridge) | |||
47 | 47 | ||
48 | nid = info->ca_closest_node; | 48 | nid = info->ca_closest_node; |
49 | page = alloc_pages_node(nid, GFP_KERNEL, 0); | 49 | page = alloc_pages_node(nid, GFP_KERNEL, 0); |
50 | if (page == NULL) { | 50 | if (!page) |
51 | return 0; | 51 | return NULL; |
52 | } | ||
53 | 52 | ||
54 | get_page(page); | 53 | get_page(page); |
55 | SetPageLocked(page); | 54 | SetPageLocked(page); |
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index 125f4282d955..eb1a1c738190 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c | |||
@@ -143,96 +143,6 @@ static struct agp_bridge_driver sis_driver = { | |||
143 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 143 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
144 | }; | 144 | }; |
145 | 145 | ||
146 | static struct agp_device_ids sis_agp_device_ids[] __devinitdata = | ||
147 | { | ||
148 | { | ||
149 | .device_id = PCI_DEVICE_ID_SI_5591_AGP, | ||
150 | .chipset_name = "5591", | ||
151 | }, | ||
152 | { | ||
153 | .device_id = PCI_DEVICE_ID_SI_530, | ||
154 | .chipset_name = "530", | ||
155 | }, | ||
156 | { | ||
157 | .device_id = PCI_DEVICE_ID_SI_540, | ||
158 | .chipset_name = "540", | ||
159 | }, | ||
160 | { | ||
161 | .device_id = PCI_DEVICE_ID_SI_550, | ||
162 | .chipset_name = "550", | ||
163 | }, | ||
164 | { | ||
165 | .device_id = PCI_DEVICE_ID_SI_620, | ||
166 | .chipset_name = "620", | ||
167 | }, | ||
168 | { | ||
169 | .device_id = PCI_DEVICE_ID_SI_630, | ||
170 | .chipset_name = "630", | ||
171 | }, | ||
172 | { | ||
173 | .device_id = PCI_DEVICE_ID_SI_635, | ||
174 | .chipset_name = "635", | ||
175 | }, | ||
176 | { | ||
177 | .device_id = PCI_DEVICE_ID_SI_645, | ||
178 | .chipset_name = "645", | ||
179 | }, | ||
180 | { | ||
181 | .device_id = PCI_DEVICE_ID_SI_646, | ||
182 | .chipset_name = "646", | ||
183 | }, | ||
184 | { | ||
185 | .device_id = PCI_DEVICE_ID_SI_648, | ||
186 | .chipset_name = "648", | ||
187 | }, | ||
188 | { | ||
189 | .device_id = PCI_DEVICE_ID_SI_650, | ||
190 | .chipset_name = "650", | ||
191 | }, | ||
192 | { | ||
193 | .device_id = PCI_DEVICE_ID_SI_651, | ||
194 | .chipset_name = "651", | ||
195 | }, | ||
196 | { | ||
197 | .device_id = PCI_DEVICE_ID_SI_655, | ||
198 | .chipset_name = "655", | ||
199 | }, | ||
200 | { | ||
201 | .device_id = PCI_DEVICE_ID_SI_661, | ||
202 | .chipset_name = "661", | ||
203 | }, | ||
204 | { | ||
205 | .device_id = PCI_DEVICE_ID_SI_730, | ||
206 | .chipset_name = "730", | ||
207 | }, | ||
208 | { | ||
209 | .device_id = PCI_DEVICE_ID_SI_735, | ||
210 | .chipset_name = "735", | ||
211 | }, | ||
212 | { | ||
213 | .device_id = PCI_DEVICE_ID_SI_740, | ||
214 | .chipset_name = "740", | ||
215 | }, | ||
216 | { | ||
217 | .device_id = PCI_DEVICE_ID_SI_741, | ||
218 | .chipset_name = "741", | ||
219 | }, | ||
220 | { | ||
221 | .device_id = PCI_DEVICE_ID_SI_745, | ||
222 | .chipset_name = "745", | ||
223 | }, | ||
224 | { | ||
225 | .device_id = PCI_DEVICE_ID_SI_746, | ||
226 | .chipset_name = "746", | ||
227 | }, | ||
228 | { | ||
229 | .device_id = PCI_DEVICE_ID_SI_760, | ||
230 | .chipset_name = "760", | ||
231 | }, | ||
232 | { }, /* dummy final entry, always present */ | ||
233 | }; | ||
234 | |||
235 | |||
236 | // chipsets that require the 'delay hack' | 146 | // chipsets that require the 'delay hack' |
237 | static int sis_broken_chipsets[] __devinitdata = { | 147 | static int sis_broken_chipsets[] __devinitdata = { |
238 | PCI_DEVICE_ID_SI_648, | 148 | PCI_DEVICE_ID_SI_648, |
@@ -269,29 +179,15 @@ static void __devinit sis_get_driver(struct agp_bridge_data *bridge) | |||
269 | static int __devinit agp_sis_probe(struct pci_dev *pdev, | 179 | static int __devinit agp_sis_probe(struct pci_dev *pdev, |
270 | const struct pci_device_id *ent) | 180 | const struct pci_device_id *ent) |
271 | { | 181 | { |
272 | struct agp_device_ids *devs = sis_agp_device_ids; | ||
273 | struct agp_bridge_data *bridge; | 182 | struct agp_bridge_data *bridge; |
274 | u8 cap_ptr; | 183 | u8 cap_ptr; |
275 | int j; | ||
276 | 184 | ||
277 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); | 185 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); |
278 | if (!cap_ptr) | 186 | if (!cap_ptr) |
279 | return -ENODEV; | 187 | return -ENODEV; |
280 | 188 | ||
281 | /* probe for known chipsets */ | ||
282 | for (j = 0; devs[j].chipset_name; j++) { | ||
283 | if (pdev->device == devs[j].device_id) { | ||
284 | printk(KERN_INFO PFX "Detected SiS %s chipset\n", | ||
285 | devs[j].chipset_name); | ||
286 | goto found; | ||
287 | } | ||
288 | } | ||
289 | |||
290 | printk(KERN_ERR PFX "Unsupported SiS chipset (device id: %04x)\n", | ||
291 | pdev->device); | ||
292 | return -ENODEV; | ||
293 | 189 | ||
294 | found: | 190 | printk(KERN_INFO PFX "Detected SiS chipset - id:%i\n", pdev->device); |
295 | bridge = agp_alloc_bridge(); | 191 | bridge = agp_alloc_bridge(); |
296 | if (!bridge) | 192 | if (!bridge) |
297 | return -ENOMEM; | 193 | return -ENOMEM; |
@@ -320,12 +216,172 @@ static void __devexit agp_sis_remove(struct pci_dev *pdev) | |||
320 | 216 | ||
321 | static struct pci_device_id agp_sis_pci_table[] = { | 217 | static struct pci_device_id agp_sis_pci_table[] = { |
322 | { | 218 | { |
323 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | 219 | .class = (PCI_CLASS_BRIDGE_HOST << 8), |
324 | .class_mask = ~0, | 220 | .class_mask = ~0, |
325 | .vendor = PCI_VENDOR_ID_SI, | 221 | .vendor = PCI_VENDOR_ID_SI, |
326 | .device = PCI_ANY_ID, | 222 | .device = PCI_DEVICE_ID_SI_5591_AGP, |
327 | .subvendor = PCI_ANY_ID, | 223 | .subvendor = PCI_ANY_ID, |
328 | .subdevice = PCI_ANY_ID, | 224 | .subdevice = PCI_ANY_ID, |
225 | }, | ||
226 | { | ||
227 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
228 | .class_mask = ~0, | ||
229 | .vendor = PCI_VENDOR_ID_SI, | ||
230 | .device = PCI_DEVICE_ID_SI_530, | ||
231 | .subvendor = PCI_ANY_ID, | ||
232 | .subdevice = PCI_ANY_ID, | ||
233 | }, | ||
234 | { | ||
235 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
236 | .class_mask = ~0, | ||
237 | .vendor = PCI_VENDOR_ID_SI, | ||
238 | .device = PCI_DEVICE_ID_SI_540, | ||
239 | .subvendor = PCI_ANY_ID, | ||
240 | .subdevice = PCI_ANY_ID, | ||
241 | }, | ||
242 | { | ||
243 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
244 | .class_mask = ~0, | ||
245 | .vendor = PCI_VENDOR_ID_SI, | ||
246 | .device = PCI_DEVICE_ID_SI_550, | ||
247 | .subvendor = PCI_ANY_ID, | ||
248 | .subdevice = PCI_ANY_ID, | ||
249 | }, | ||
250 | { | ||
251 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
252 | .class_mask = ~0, | ||
253 | .vendor = PCI_VENDOR_ID_SI, | ||
254 | .device = PCI_DEVICE_ID_SI_620, | ||
255 | .subvendor = PCI_ANY_ID, | ||
256 | .subdevice = PCI_ANY_ID, | ||
257 | }, | ||
258 | { | ||
259 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
260 | .class_mask = ~0, | ||
261 | .vendor = PCI_VENDOR_ID_SI, | ||
262 | .device = PCI_DEVICE_ID_SI_630, | ||
263 | .subvendor = PCI_ANY_ID, | ||
264 | .subdevice = PCI_ANY_ID, | ||
265 | }, | ||
266 | { | ||
267 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
268 | .class_mask = ~0, | ||
269 | .vendor = PCI_VENDOR_ID_SI, | ||
270 | .device = PCI_DEVICE_ID_SI_635, | ||
271 | .subvendor = PCI_ANY_ID, | ||
272 | .subdevice = PCI_ANY_ID, | ||
273 | }, | ||
274 | { | ||
275 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
276 | .class_mask = ~0, | ||
277 | .vendor = PCI_VENDOR_ID_SI, | ||
278 | .device = PCI_DEVICE_ID_SI_645, | ||
279 | .subvendor = PCI_ANY_ID, | ||
280 | .subdevice = PCI_ANY_ID, | ||
281 | }, | ||
282 | { | ||
283 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
284 | .class_mask = ~0, | ||
285 | .vendor = PCI_VENDOR_ID_SI, | ||
286 | .device = PCI_DEVICE_ID_SI_646, | ||
287 | .subvendor = PCI_ANY_ID, | ||
288 | .subdevice = PCI_ANY_ID, | ||
289 | }, | ||
290 | { | ||
291 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
292 | .class_mask = ~0, | ||
293 | .vendor = PCI_VENDOR_ID_SI, | ||
294 | .device = PCI_DEVICE_ID_SI_648, | ||
295 | .subvendor = PCI_ANY_ID, | ||
296 | .subdevice = PCI_ANY_ID, | ||
297 | }, | ||
298 | { | ||
299 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
300 | .class_mask = ~0, | ||
301 | .vendor = PCI_VENDOR_ID_SI, | ||
302 | .device = PCI_DEVICE_ID_SI_650, | ||
303 | .subvendor = PCI_ANY_ID, | ||
304 | .subdevice = PCI_ANY_ID, | ||
305 | }, | ||
306 | { | ||
307 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
308 | .class_mask = ~0, | ||
309 | .vendor = PCI_VENDOR_ID_SI, | ||
310 | .device = PCI_DEVICE_ID_SI_651, | ||
311 | .subvendor = PCI_ANY_ID, | ||
312 | .subdevice = PCI_ANY_ID, | ||
313 | }, | ||
314 | { | ||
315 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
316 | .class_mask = ~0, | ||
317 | .vendor = PCI_VENDOR_ID_SI, | ||
318 | .device = PCI_DEVICE_ID_SI_655, | ||
319 | .subvendor = PCI_ANY_ID, | ||
320 | .subdevice = PCI_ANY_ID, | ||
321 | }, | ||
322 | { | ||
323 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
324 | .class_mask = ~0, | ||
325 | .vendor = PCI_VENDOR_ID_SI, | ||
326 | .device = PCI_DEVICE_ID_SI_661, | ||
327 | .subvendor = PCI_ANY_ID, | ||
328 | .subdevice = PCI_ANY_ID, | ||
329 | }, | ||
330 | { | ||
331 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
332 | .class_mask = ~0, | ||
333 | .vendor = PCI_VENDOR_ID_SI, | ||
334 | .device = PCI_DEVICE_ID_SI_730, | ||
335 | .subvendor = PCI_ANY_ID, | ||
336 | .subdevice = PCI_ANY_ID, | ||
337 | }, | ||
338 | { | ||
339 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
340 | .class_mask = ~0, | ||
341 | .vendor = PCI_VENDOR_ID_SI, | ||
342 | .device = PCI_DEVICE_ID_SI_735, | ||
343 | .subvendor = PCI_ANY_ID, | ||
344 | .subdevice = PCI_ANY_ID, | ||
345 | }, | ||
346 | { | ||
347 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
348 | .class_mask = ~0, | ||
349 | .vendor = PCI_VENDOR_ID_SI, | ||
350 | .device = PCI_DEVICE_ID_SI_740, | ||
351 | .subvendor = PCI_ANY_ID, | ||
352 | .subdevice = PCI_ANY_ID, | ||
353 | }, | ||
354 | { | ||
355 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
356 | .class_mask = ~0, | ||
357 | .vendor = PCI_VENDOR_ID_SI, | ||
358 | .device = PCI_DEVICE_ID_SI_741, | ||
359 | .subvendor = PCI_ANY_ID, | ||
360 | .subdevice = PCI_ANY_ID, | ||
361 | }, | ||
362 | { | ||
363 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
364 | .class_mask = ~0, | ||
365 | .vendor = PCI_VENDOR_ID_SI, | ||
366 | .device = PCI_DEVICE_ID_SI_745, | ||
367 | .subvendor = PCI_ANY_ID, | ||
368 | .subdevice = PCI_ANY_ID, | ||
369 | }, | ||
370 | { | ||
371 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
372 | .class_mask = ~0, | ||
373 | .vendor = PCI_VENDOR_ID_SI, | ||
374 | .device = PCI_DEVICE_ID_SI_746, | ||
375 | .subvendor = PCI_ANY_ID, | ||
376 | .subdevice = PCI_ANY_ID, | ||
377 | }, | ||
378 | { | ||
379 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
380 | .class_mask = ~0, | ||
381 | .vendor = PCI_VENDOR_ID_SI, | ||
382 | .device = PCI_DEVICE_ID_SI_760, | ||
383 | .subvendor = PCI_ANY_ID, | ||
384 | .subdevice = PCI_ANY_ID, | ||
329 | }, | 385 | }, |
330 | { } | 386 | { } |
331 | }; | 387 | }; |
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 55212a3811fd..551ef25063ef 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c | |||
@@ -455,15 +455,6 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, | |||
455 | u32 temp, temp2; | 455 | u32 temp, temp2; |
456 | u8 cap_ptr = 0; | 456 | u8 cap_ptr = 0; |
457 | 457 | ||
458 | /* Everything is on func 1 here so we are hardcoding function one */ | ||
459 | bridge_dev = pci_find_slot((unsigned int)pdev->bus->number, | ||
460 | PCI_DEVFN(0, 1)); | ||
461 | if (!bridge_dev) { | ||
462 | printk(KERN_INFO PFX "Detected a Serverworks chipset " | ||
463 | "but could not find the secondary device.\n"); | ||
464 | return -ENODEV; | ||
465 | } | ||
466 | |||
467 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); | 458 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); |
468 | 459 | ||
469 | switch (pdev->device) { | 460 | switch (pdev->device) { |
@@ -483,6 +474,15 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, | |||
483 | return -ENODEV; | 474 | return -ENODEV; |
484 | } | 475 | } |
485 | 476 | ||
477 | /* Everything is on func 1 here so we are hardcoding function one */ | ||
478 | bridge_dev = pci_get_bus_and_slot((unsigned int)pdev->bus->number, | ||
479 | PCI_DEVFN(0, 1)); | ||
480 | if (!bridge_dev) { | ||
481 | printk(KERN_INFO PFX "Detected a Serverworks chipset " | ||
482 | "but could not find the secondary device.\n"); | ||
483 | return -ENODEV; | ||
484 | } | ||
485 | |||
486 | serverworks_private.svrwrks_dev = bridge_dev; | 486 | serverworks_private.svrwrks_dev = bridge_dev; |
487 | serverworks_private.gart_addr_ofs = 0x10; | 487 | serverworks_private.gart_addr_ofs = 0x10; |
488 | 488 | ||
@@ -515,7 +515,7 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, | |||
515 | 515 | ||
516 | bridge->driver = &sworks_driver; | 516 | bridge->driver = &sworks_driver; |
517 | bridge->dev_private_data = &serverworks_private, | 517 | bridge->dev_private_data = &serverworks_private, |
518 | bridge->dev = pdev; | 518 | bridge->dev = pci_dev_get(pdev); |
519 | 519 | ||
520 | pci_set_drvdata(pdev, bridge); | 520 | pci_set_drvdata(pdev, bridge); |
521 | return agp_add_bridge(bridge); | 521 | return agp_add_bridge(bridge); |
@@ -525,8 +525,11 @@ static void __devexit agp_serverworks_remove(struct pci_dev *pdev) | |||
525 | { | 525 | { |
526 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 526 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
527 | 527 | ||
528 | pci_dev_put(bridge->dev); | ||
528 | agp_remove_bridge(bridge); | 529 | agp_remove_bridge(bridge); |
529 | agp_put_bridge(bridge); | 530 | agp_put_bridge(bridge); |
531 | pci_dev_put(serverworks_private.svrwrks_dev); | ||
532 | serverworks_private.svrwrks_dev = NULL; | ||
530 | } | 533 | } |
531 | 534 | ||
532 | static struct pci_device_id agp_serverworks_pci_table[] = { | 535 | static struct pci_device_id agp_serverworks_pci_table[] = { |
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c index 9ebf84d18655..ec435cb25c4f 100644 --- a/drivers/char/hw_random/via-rng.c +++ b/drivers/char/hw_random/via-rng.c | |||
@@ -26,7 +26,6 @@ | |||
26 | 26 | ||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
29 | #include <linux/pci.h> | ||
30 | #include <linux/hw_random.h> | 29 | #include <linux/hw_random.h> |
31 | #include <asm/io.h> | 30 | #include <asm/io.h> |
32 | #include <asm/msr.h> | 31 | #include <asm/msr.h> |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 157b1d09ab55..13808f6083a0 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/timer.h> | 42 | #include <linux/timer.h> |
43 | #include <linux/time.h> | 43 | #include <linux/time.h> |
44 | #include <linux/interrupt.h> | 44 | #include <linux/interrupt.h> |
45 | #include <linux/pci.h> | ||
46 | #include <linux/tty.h> | 45 | #include <linux/tty.h> |
47 | #include <linux/tty_flip.h> | 46 | #include <linux/tty_flip.h> |
48 | #include <linux/serial.h> | 47 | #include <linux/serial.h> |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index bb9a43c6cf3d..9f273f032b0f 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -19,7 +19,6 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/pci.h> | ||
23 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
24 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
25 | #include <linux/sched.h> | 24 | #include <linux/sched.h> |
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index 1e4a8d751a71..2f7ba7a514fe 100644 --- a/drivers/char/watchdog/sc1200wdt.c +++ b/drivers/char/watchdog/sc1200wdt.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/init.h> | 38 | #include <linux/init.h> |
39 | #include <linux/pnp.h> | 39 | #include <linux/pnp.h> |
40 | #include <linux/fs.h> | 40 | #include <linux/fs.h> |
41 | #include <linux/pci.h> | ||
42 | 41 | ||
43 | #include <asm/semaphore.h> | 42 | #include <asm/semaphore.h> |
44 | #include <asm/io.h> | 43 | #include <asm/io.h> |
diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c index fc0e0347f9d2..d4fd0fa2f176 100644 --- a/drivers/char/watchdog/scx200_wdt.c +++ b/drivers/char/watchdog/scx200_wdt.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/notifier.h> | 25 | #include <linux/notifier.h> |
26 | #include <linux/reboot.h> | 26 | #include <linux/reboot.h> |
27 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
28 | #include <linux/pci.h> | 28 | #include <linux/ioport.h> |
29 | #include <linux/scx200.h> | 29 | #include <linux/scx200.h> |
30 | 30 | ||
31 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index d155e81b5c97..993fa7b89253 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig | |||
@@ -9,6 +9,9 @@ config CPU_FREQ | |||
9 | clock speed, you need to either enable a dynamic cpufreq governor | 9 | clock speed, you need to either enable a dynamic cpufreq governor |
10 | (see below) after boot, or use a userspace tool. | 10 | (see below) after boot, or use a userspace tool. |
11 | 11 | ||
12 | To compile this driver as a module, choose M here: the | ||
13 | module will be called cpufreq. | ||
14 | |||
12 | For details, take a look at <file:Documentation/cpu-freq>. | 15 | For details, take a look at <file:Documentation/cpu-freq>. |
13 | 16 | ||
14 | If in doubt, say N. | 17 | If in doubt, say N. |
@@ -16,7 +19,7 @@ config CPU_FREQ | |||
16 | if CPU_FREQ | 19 | if CPU_FREQ |
17 | 20 | ||
18 | config CPU_FREQ_TABLE | 21 | config CPU_FREQ_TABLE |
19 | tristate | 22 | tristate |
20 | 23 | ||
21 | config CPU_FREQ_DEBUG | 24 | config CPU_FREQ_DEBUG |
22 | bool "Enable CPUfreq debugging" | 25 | bool "Enable CPUfreq debugging" |
@@ -32,19 +35,26 @@ config CPU_FREQ_DEBUG | |||
32 | 4 to activate CPUfreq governor debugging | 35 | 4 to activate CPUfreq governor debugging |
33 | 36 | ||
34 | config CPU_FREQ_STAT | 37 | config CPU_FREQ_STAT |
35 | tristate "CPU frequency translation statistics" | 38 | tristate "CPU frequency translation statistics" |
36 | select CPU_FREQ_TABLE | 39 | select CPU_FREQ_TABLE |
37 | default y | 40 | default y |
38 | help | 41 | help |
39 | This driver exports CPU frequency statistics information through sysfs | 42 | This driver exports CPU frequency statistics information through sysfs |
40 | file system | 43 | file system. |
44 | |||
45 | To compile this driver as a module, choose M here: the | ||
46 | module will be called cpufreq_stats. | ||
47 | |||
48 | If in doubt, say N. | ||
41 | 49 | ||
42 | config CPU_FREQ_STAT_DETAILS | 50 | config CPU_FREQ_STAT_DETAILS |
43 | bool "CPU frequency translation statistics details" | 51 | bool "CPU frequency translation statistics details" |
44 | depends on CPU_FREQ_STAT | 52 | depends on CPU_FREQ_STAT |
45 | help | 53 | help |
46 | This will show detail CPU frequency translation table in sysfs file | 54 | This will show detail CPU frequency translation table in sysfs file |
47 | system | 55 | system. |
56 | |||
57 | If in doubt, say N. | ||
48 | 58 | ||
49 | # Note that it is not currently possible to set the other governors (such as ondemand) | 59 | # Note that it is not currently possible to set the other governors (such as ondemand) |
50 | # as the default, since if they fail to initialise, cpufreq will be | 60 | # as the default, since if they fail to initialise, cpufreq will be |
@@ -78,29 +88,38 @@ config CPU_FREQ_DEFAULT_GOV_USERSPACE | |||
78 | endchoice | 88 | endchoice |
79 | 89 | ||
80 | config CPU_FREQ_GOV_PERFORMANCE | 90 | config CPU_FREQ_GOV_PERFORMANCE |
81 | tristate "'performance' governor" | 91 | tristate "'performance' governor" |
82 | help | 92 | help |
83 | This cpufreq governor sets the frequency statically to the | 93 | This cpufreq governor sets the frequency statically to the |
84 | highest available CPU frequency. | 94 | highest available CPU frequency. |
85 | 95 | ||
96 | To compile this driver as a module, choose M here: the | ||
97 | module will be called cpufreq_performance. | ||
98 | |||
86 | If in doubt, say Y. | 99 | If in doubt, say Y. |
87 | 100 | ||
88 | config CPU_FREQ_GOV_POWERSAVE | 101 | config CPU_FREQ_GOV_POWERSAVE |
89 | tristate "'powersave' governor" | 102 | tristate "'powersave' governor" |
90 | help | 103 | help |
91 | This cpufreq governor sets the frequency statically to the | 104 | This cpufreq governor sets the frequency statically to the |
92 | lowest available CPU frequency. | 105 | lowest available CPU frequency. |
93 | 106 | ||
107 | To compile this driver as a module, choose M here: the | ||
108 | module will be called cpufreq_powersave. | ||
109 | |||
94 | If in doubt, say Y. | 110 | If in doubt, say Y. |
95 | 111 | ||
96 | config CPU_FREQ_GOV_USERSPACE | 112 | config CPU_FREQ_GOV_USERSPACE |
97 | tristate "'userspace' governor for userspace frequency scaling" | 113 | tristate "'userspace' governor for userspace frequency scaling" |
98 | help | 114 | help |
99 | Enable this cpufreq governor when you either want to set the | 115 | Enable this cpufreq governor when you either want to set the |
100 | CPU frequency manually or when an userspace program shall | 116 | CPU frequency manually or when an userspace program shall |
101 | be able to set the CPU dynamically, like on LART | 117 | be able to set the CPU dynamically, like on LART |
102 | <http://www.lartmaker.nl/>. | 118 | <http://www.lartmaker.nl/>. |
103 | 119 | ||
120 | To compile this driver as a module, choose M here: the | ||
121 | module will be called cpufreq_userspace. | ||
122 | |||
104 | For details, take a look at <file:Documentation/cpu-freq/>. | 123 | For details, take a look at <file:Documentation/cpu-freq/>. |
105 | 124 | ||
106 | If in doubt, say Y. | 125 | If in doubt, say Y. |
@@ -116,6 +135,9 @@ config CPU_FREQ_GOV_ONDEMAND | |||
116 | do fast frequency switching (i.e, very low latency frequency | 135 | do fast frequency switching (i.e, very low latency frequency |
117 | transitions). | 136 | transitions). |
118 | 137 | ||
138 | To compile this driver as a module, choose M here: the | ||
139 | module will be called cpufreq_ondemand. | ||
140 | |||
119 | For details, take a look at linux/Documentation/cpu-freq. | 141 | For details, take a look at linux/Documentation/cpu-freq. |
120 | 142 | ||
121 | If in doubt, say N. | 143 | If in doubt, say N. |
@@ -136,6 +158,9 @@ config CPU_FREQ_GOV_CONSERVATIVE | |||
136 | step-by-step latency issues between the minimum and maximum frequency | 158 | step-by-step latency issues between the minimum and maximum frequency |
137 | transitions in the CPU) you will probably want to use this governor. | 159 | transitions in the CPU) you will probably want to use this governor. |
138 | 160 | ||
161 | To compile this driver as a module, choose M here: the | ||
162 | module will be called cpufreq_conservative. | ||
163 | |||
139 | For details, take a look at linux/Documentation/cpu-freq. | 164 | For details, take a look at linux/Documentation/cpu-freq. |
140 | 165 | ||
141 | If in doubt, say N. | 166 | If in doubt, say N. |
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 3162010900c9..893dbaf386fb 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -768,6 +768,9 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) | |||
768 | unlock_policy_rwsem_write(cpu); | 768 | unlock_policy_rwsem_write(cpu); |
769 | goto err_out; | 769 | goto err_out; |
770 | } | 770 | } |
771 | policy->user_policy.min = policy->cpuinfo.min_freq; | ||
772 | policy->user_policy.max = policy->cpuinfo.max_freq; | ||
773 | policy->user_policy.governor = policy->governor; | ||
771 | 774 | ||
772 | #ifdef CONFIG_SMP | 775 | #ifdef CONFIG_SMP |
773 | for_each_cpu_mask(j, policy->cpus) { | 776 | for_each_cpu_mask(j, policy->cpus) { |
@@ -858,10 +861,13 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) | |||
858 | 861 | ||
859 | policy->governor = NULL; /* to assure that the starting sequence is | 862 | policy->governor = NULL; /* to assure that the starting sequence is |
860 | * run in cpufreq_set_policy */ | 863 | * run in cpufreq_set_policy */ |
861 | unlock_policy_rwsem_write(cpu); | ||
862 | 864 | ||
863 | /* set default policy */ | 865 | /* set default policy */ |
864 | ret = cpufreq_set_policy(&new_policy); | 866 | ret = __cpufreq_set_policy(policy, &new_policy); |
867 | policy->user_policy.policy = policy->policy; | ||
868 | |||
869 | unlock_policy_rwsem_write(cpu); | ||
870 | |||
865 | if (ret) { | 871 | if (ret) { |
866 | dprintk("setting policy failed\n"); | 872 | dprintk("setting policy failed\n"); |
867 | goto err_out_unregister; | 873 | goto err_out_unregister; |
@@ -1620,43 +1626,6 @@ error_out: | |||
1620 | } | 1626 | } |
1621 | 1627 | ||
1622 | /** | 1628 | /** |
1623 | * cpufreq_set_policy - set a new CPUFreq policy | ||
1624 | * @policy: policy to be set. | ||
1625 | * | ||
1626 | * Sets a new CPU frequency and voltage scaling policy. | ||
1627 | */ | ||
1628 | int cpufreq_set_policy(struct cpufreq_policy *policy) | ||
1629 | { | ||
1630 | int ret = 0; | ||
1631 | struct cpufreq_policy *data; | ||
1632 | |||
1633 | if (!policy) | ||
1634 | return -EINVAL; | ||
1635 | |||
1636 | data = cpufreq_cpu_get(policy->cpu); | ||
1637 | if (!data) | ||
1638 | return -EINVAL; | ||
1639 | |||
1640 | if (unlikely(lock_policy_rwsem_write(policy->cpu))) | ||
1641 | return -EINVAL; | ||
1642 | |||
1643 | |||
1644 | ret = __cpufreq_set_policy(data, policy); | ||
1645 | data->user_policy.min = data->min; | ||
1646 | data->user_policy.max = data->max; | ||
1647 | data->user_policy.policy = data->policy; | ||
1648 | data->user_policy.governor = data->governor; | ||
1649 | |||
1650 | unlock_policy_rwsem_write(policy->cpu); | ||
1651 | |||
1652 | cpufreq_cpu_put(data); | ||
1653 | |||
1654 | return ret; | ||
1655 | } | ||
1656 | EXPORT_SYMBOL(cpufreq_set_policy); | ||
1657 | |||
1658 | |||
1659 | /** | ||
1660 | * cpufreq_update_policy - re-evaluate an existing cpufreq policy | 1629 | * cpufreq_update_policy - re-evaluate an existing cpufreq policy |
1661 | * @cpu: CPU which shall be re-evaluated | 1630 | * @cpu: CPU which shall be re-evaluated |
1662 | * | 1631 | * |
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index ff8c4beaace4..f21fe66c9eef 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig | |||
@@ -1,10 +1,10 @@ | |||
1 | menu "Hardware crypto devices" | 1 | menu "Hardware crypto devices" |
2 | 2 | ||
3 | config CRYPTO_DEV_PADLOCK | 3 | config CRYPTO_DEV_PADLOCK |
4 | tristate "Support for VIA PadLock ACE" | 4 | bool "Support for VIA PadLock ACE" |
5 | depends on X86_32 | 5 | depends on X86_32 |
6 | select CRYPTO_ALGAPI | 6 | select CRYPTO_ALGAPI |
7 | default m | 7 | default y |
8 | help | 8 | help |
9 | Some VIA processors come with an integrated crypto engine | 9 | Some VIA processors come with an integrated crypto engine |
10 | (so called VIA PadLock ACE, Advanced Cryptography Engine) | 10 | (so called VIA PadLock ACE, Advanced Cryptography Engine) |
@@ -14,16 +14,6 @@ config CRYPTO_DEV_PADLOCK | |||
14 | The instructions are used only when the CPU supports them. | 14 | The instructions are used only when the CPU supports them. |
15 | Otherwise software encryption is used. | 15 | Otherwise software encryption is used. |
16 | 16 | ||
17 | Selecting M for this option will compile a helper module | ||
18 | padlock.ko that should autoload all below configured | ||
19 | algorithms. Don't worry if your hardware does not support | ||
20 | some or all of them. In such case padlock.ko will | ||
21 | simply write a single line into the kernel log informing | ||
22 | about its failure but everything will keep working fine. | ||
23 | |||
24 | If you are unsure, say M. The compiled module will be | ||
25 | called padlock.ko | ||
26 | |||
27 | config CRYPTO_DEV_PADLOCK_AES | 17 | config CRYPTO_DEV_PADLOCK_AES |
28 | tristate "PadLock driver for AES algorithm" | 18 | tristate "PadLock driver for AES algorithm" |
29 | depends on CRYPTO_DEV_PADLOCK | 19 | depends on CRYPTO_DEV_PADLOCK |
@@ -55,7 +45,7 @@ source "arch/s390/crypto/Kconfig" | |||
55 | 45 | ||
56 | config CRYPTO_DEV_GEODE | 46 | config CRYPTO_DEV_GEODE |
57 | tristate "Support for the Geode LX AES engine" | 47 | tristate "Support for the Geode LX AES engine" |
58 | depends on CRYPTO && X86_32 && PCI | 48 | depends on X86_32 && PCI |
59 | select CRYPTO_ALGAPI | 49 | select CRYPTO_ALGAPI |
60 | select CRYPTO_BLKCIPHER | 50 | select CRYPTO_BLKCIPHER |
61 | default m | 51 | default m |
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 6059cf869414..d070030f7d7e 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile | |||
@@ -1,4 +1,3 @@ | |||
1 | obj-$(CONFIG_CRYPTO_DEV_PADLOCK) += padlock.o | ||
2 | obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o | 1 | obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o |
3 | obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o | 2 | obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o |
4 | obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o | 3 | obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o |
diff --git a/drivers/crypto/padlock.c b/drivers/crypto/padlock.c deleted file mode 100644 index d6d7dd5bb98c..000000000000 --- a/drivers/crypto/padlock.c +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | /* | ||
2 | * Cryptographic API. | ||
3 | * | ||
4 | * Support for VIA PadLock hardware crypto engine. | ||
5 | * | ||
6 | * Copyright (c) 2006 Michal Ludvig <michal@logix.cz> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/crypto.h> | ||
19 | #include <linux/cryptohash.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/scatterlist.h> | ||
23 | #include "padlock.h" | ||
24 | |||
25 | static int __init padlock_init(void) | ||
26 | { | ||
27 | int success = 0; | ||
28 | |||
29 | if (crypto_has_cipher("aes-padlock", 0, 0)) | ||
30 | success++; | ||
31 | |||
32 | if (crypto_has_hash("sha1-padlock", 0, 0)) | ||
33 | success++; | ||
34 | |||
35 | if (crypto_has_hash("sha256-padlock", 0, 0)) | ||
36 | success++; | ||
37 | |||
38 | if (!success) { | ||
39 | printk(KERN_WARNING PFX "No VIA PadLock drivers have been loaded.\n"); | ||
40 | return -ENODEV; | ||
41 | } | ||
42 | |||
43 | printk(KERN_NOTICE PFX "%d drivers are available.\n", success); | ||
44 | |||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | static void __exit padlock_fini(void) | ||
49 | { | ||
50 | } | ||
51 | |||
52 | module_init(padlock_init); | ||
53 | module_exit(padlock_fini); | ||
54 | |||
55 | MODULE_DESCRIPTION("Load all configured PadLock algorithms."); | ||
56 | MODULE_LICENSE("GPL"); | ||
57 | MODULE_AUTHOR("Michal Ludvig"); | ||
58 | |||
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 11935f66fcd8..434a61b415a3 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig | |||
@@ -2,9 +2,7 @@ | |||
2 | # I2C subsystem configuration | 2 | # I2C subsystem configuration |
3 | # | 3 | # |
4 | 4 | ||
5 | menu "I2C support" | 5 | menuconfig I2C |
6 | |||
7 | config I2C | ||
8 | tristate "I2C support" | 6 | tristate "I2C support" |
9 | ---help--- | 7 | ---help--- |
10 | I2C (pronounce: I-square-C) is a slow serial bus protocol used in | 8 | I2C (pronounce: I-square-C) is a slow serial bus protocol used in |
@@ -22,9 +20,14 @@ config I2C | |||
22 | This I2C support can also be built as a module. If so, the module | 20 | This I2C support can also be built as a module. If so, the module |
23 | will be called i2c-core. | 21 | will be called i2c-core. |
24 | 22 | ||
23 | if I2C | ||
24 | |||
25 | config I2C_BOARDINFO | ||
26 | boolean | ||
27 | default y | ||
28 | |||
25 | config I2C_CHARDEV | 29 | config I2C_CHARDEV |
26 | tristate "I2C device interface" | 30 | tristate "I2C device interface" |
27 | depends on I2C | ||
28 | help | 31 | help |
29 | Say Y here to use i2c-* device files, usually found in the /dev | 32 | Say Y here to use i2c-* device files, usually found in the /dev |
30 | directory on your system. They make it possible to have user-space | 33 | directory on your system. They make it possible to have user-space |
@@ -40,7 +43,6 @@ source drivers/i2c/chips/Kconfig | |||
40 | 43 | ||
41 | config I2C_DEBUG_CORE | 44 | config I2C_DEBUG_CORE |
42 | bool "I2C Core debugging messages" | 45 | bool "I2C Core debugging messages" |
43 | depends on I2C | ||
44 | help | 46 | help |
45 | Say Y here if you want the I2C core to produce a bunch of debug | 47 | Say Y here if you want the I2C core to produce a bunch of debug |
46 | messages to the system log. Select this if you are having a | 48 | messages to the system log. Select this if you are having a |
@@ -48,7 +50,6 @@ config I2C_DEBUG_CORE | |||
48 | 50 | ||
49 | config I2C_DEBUG_ALGO | 51 | config I2C_DEBUG_ALGO |
50 | bool "I2C Algorithm debugging messages" | 52 | bool "I2C Algorithm debugging messages" |
51 | depends on I2C | ||
52 | help | 53 | help |
53 | Say Y here if you want the I2C algorithm drivers to produce a bunch | 54 | Say Y here if you want the I2C algorithm drivers to produce a bunch |
54 | of debug messages to the system log. Select this if you are having | 55 | of debug messages to the system log. Select this if you are having |
@@ -57,7 +58,6 @@ config I2C_DEBUG_ALGO | |||
57 | 58 | ||
58 | config I2C_DEBUG_BUS | 59 | config I2C_DEBUG_BUS |
59 | bool "I2C Bus debugging messages" | 60 | bool "I2C Bus debugging messages" |
60 | depends on I2C | ||
61 | help | 61 | help |
62 | Say Y here if you want the I2C bus drivers to produce a bunch of | 62 | Say Y here if you want the I2C bus drivers to produce a bunch of |
63 | debug messages to the system log. Select this if you are having | 63 | debug messages to the system log. Select this if you are having |
@@ -66,12 +66,10 @@ config I2C_DEBUG_BUS | |||
66 | 66 | ||
67 | config I2C_DEBUG_CHIP | 67 | config I2C_DEBUG_CHIP |
68 | bool "I2C Chip debugging messages" | 68 | bool "I2C Chip debugging messages" |
69 | depends on I2C | ||
70 | help | 69 | help |
71 | Say Y here if you want the I2C chip drivers to produce a bunch of | 70 | Say Y here if you want the I2C chip drivers to produce a bunch of |
72 | debug messages to the system log. Select this if you are having | 71 | debug messages to the system log. Select this if you are having |
73 | a problem with I2C support and want to see more of what is going | 72 | a problem with I2C support and want to see more of what is going |
74 | on. | 73 | on. |
75 | 74 | ||
76 | endmenu | 75 | endif # I2C |
77 | |||
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 71c5a854ac5d..ba26e6cbe74e 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile | |||
@@ -2,6 +2,7 @@ | |||
2 | # Makefile for the i2c core. | 2 | # Makefile for the i2c core. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o | ||
5 | obj-$(CONFIG_I2C) += i2c-core.o | 6 | obj-$(CONFIG_I2C) += i2c-core.o |
6 | obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o | 7 | obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o |
7 | obj-y += busses/ chips/ algos/ | 8 | obj-y += busses/ chips/ algos/ |
diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig index af0203409dd1..58899078810b 100644 --- a/drivers/i2c/algos/Kconfig +++ b/drivers/i2c/algos/Kconfig | |||
@@ -3,11 +3,9 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | menu "I2C Algorithms" | 5 | menu "I2C Algorithms" |
6 | depends on I2C | ||
7 | 6 | ||
8 | config I2C_ALGOBIT | 7 | config I2C_ALGOBIT |
9 | tristate "I2C bit-banging interfaces" | 8 | tristate "I2C bit-banging interfaces" |
10 | depends on I2C | ||
11 | help | 9 | help |
12 | This allows you to use a range of I2C adapters called bit-banging | 10 | This allows you to use a range of I2C adapters called bit-banging |
13 | adapters. Say Y if you own an I2C adapter belonging to this class | 11 | adapters. Say Y if you own an I2C adapter belonging to this class |
@@ -18,7 +16,6 @@ config I2C_ALGOBIT | |||
18 | 16 | ||
19 | config I2C_ALGOPCF | 17 | config I2C_ALGOPCF |
20 | tristate "I2C PCF 8584 interfaces" | 18 | tristate "I2C PCF 8584 interfaces" |
21 | depends on I2C | ||
22 | help | 19 | help |
23 | This allows you to use a range of I2C adapters called PCF adapters. | 20 | This allows you to use a range of I2C adapters called PCF adapters. |
24 | Say Y if you own an I2C adapter belonging to this class and then say | 21 | Say Y if you own an I2C adapter belonging to this class and then say |
@@ -29,7 +26,6 @@ config I2C_ALGOPCF | |||
29 | 26 | ||
30 | config I2C_ALGOPCA | 27 | config I2C_ALGOPCA |
31 | tristate "I2C PCA 9564 interfaces" | 28 | tristate "I2C PCA 9564 interfaces" |
32 | depends on I2C | ||
33 | help | 29 | help |
34 | This allows you to use a range of I2C adapters called PCA adapters. | 30 | This allows you to use a range of I2C adapters called PCA adapters. |
35 | Say Y if you own an I2C adapter belonging to this class and then say | 31 | Say Y if you own an I2C adapter belonging to this class and then say |
@@ -40,11 +36,11 @@ config I2C_ALGOPCA | |||
40 | 36 | ||
41 | config I2C_ALGO8XX | 37 | config I2C_ALGO8XX |
42 | tristate "MPC8xx CPM I2C interface" | 38 | tristate "MPC8xx CPM I2C interface" |
43 | depends on 8xx && I2C | 39 | depends on 8xx |
44 | 40 | ||
45 | config I2C_ALGO_SGI | 41 | config I2C_ALGO_SGI |
46 | tristate "I2C SGI interfaces" | 42 | tristate "I2C SGI interfaces" |
47 | depends on I2C && (SGI_IP22 || SGI_IP32 || X86_VISWS) | 43 | depends on SGI_IP22 || SGI_IP32 || X86_VISWS |
48 | help | 44 | help |
49 | Supports the SGI interfaces like the ones found on SGI Indy VINO | 45 | Supports the SGI interfaces like the ones found on SGI Indy VINO |
50 | or SGI O2 MACE. | 46 | or SGI O2 MACE. |
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index 95aa5395a5be..8a5f5825bb72 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c | |||
@@ -33,19 +33,30 @@ | |||
33 | 33 | ||
34 | 34 | ||
35 | /* ----- global defines ----------------------------------------------- */ | 35 | /* ----- global defines ----------------------------------------------- */ |
36 | #define DEB(x) if (i2c_debug>=1) x; | ||
37 | #define DEB2(x) if (i2c_debug>=2) x; | ||
38 | #define DEBSTAT(x) if (i2c_debug>=3) x; /* print several statistical values*/ | ||
39 | #define DEBPROTO(x) if (i2c_debug>=9) { x; } | ||
40 | /* debug the protocol by showing transferred bits */ | ||
41 | 36 | ||
37 | #ifdef DEBUG | ||
38 | #define bit_dbg(level, dev, format, args...) \ | ||
39 | do { \ | ||
40 | if (i2c_debug >= level) \ | ||
41 | dev_dbg(dev, format, ##args); \ | ||
42 | } while (0) | ||
43 | #else | ||
44 | #define bit_dbg(level, dev, format, args...) \ | ||
45 | do {} while (0) | ||
46 | #endif /* DEBUG */ | ||
42 | 47 | ||
43 | /* ----- global variables --------------------------------------------- */ | 48 | /* ----- global variables --------------------------------------------- */ |
44 | 49 | ||
45 | /* module parameters: | ||
46 | */ | ||
47 | static int i2c_debug; | ||
48 | static int bit_test; /* see if the line-setting functions work */ | 50 | static int bit_test; /* see if the line-setting functions work */ |
51 | module_param(bit_test, bool, 0); | ||
52 | MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck"); | ||
53 | |||
54 | #ifdef DEBUG | ||
55 | static int i2c_debug = 1; | ||
56 | module_param(i2c_debug, int, S_IRUGO | S_IWUSR); | ||
57 | MODULE_PARM_DESC(i2c_debug, | ||
58 | "debug level - 0 off; 1 normal; 2 verbose; 3 very verbose"); | ||
59 | #endif | ||
49 | 60 | ||
50 | /* --- setting states on the bus with the right timing: --------------- */ | 61 | /* --- setting states on the bus with the right timing: --------------- */ |
51 | 62 | ||
@@ -57,19 +68,19 @@ static int bit_test; /* see if the line-setting functions work */ | |||
57 | static inline void sdalo(struct i2c_algo_bit_data *adap) | 68 | static inline void sdalo(struct i2c_algo_bit_data *adap) |
58 | { | 69 | { |
59 | setsda(adap,0); | 70 | setsda(adap,0); |
60 | udelay(adap->udelay); | 71 | udelay((adap->udelay + 1) / 2); |
61 | } | 72 | } |
62 | 73 | ||
63 | static inline void sdahi(struct i2c_algo_bit_data *adap) | 74 | static inline void sdahi(struct i2c_algo_bit_data *adap) |
64 | { | 75 | { |
65 | setsda(adap,1); | 76 | setsda(adap,1); |
66 | udelay(adap->udelay); | 77 | udelay((adap->udelay + 1) / 2); |
67 | } | 78 | } |
68 | 79 | ||
69 | static inline void scllo(struct i2c_algo_bit_data *adap) | 80 | static inline void scllo(struct i2c_algo_bit_data *adap) |
70 | { | 81 | { |
71 | setscl(adap,0); | 82 | setscl(adap,0); |
72 | udelay(adap->udelay); | 83 | udelay(adap->udelay / 2); |
73 | } | 84 | } |
74 | 85 | ||
75 | /* | 86 | /* |
@@ -98,7 +109,11 @@ static int sclhi(struct i2c_algo_bit_data *adap) | |||
98 | } | 109 | } |
99 | cond_resched(); | 110 | cond_resched(); |
100 | } | 111 | } |
101 | DEBSTAT(printk(KERN_DEBUG "needed %ld jiffies\n", jiffies-start)); | 112 | #ifdef DEBUG |
113 | if (jiffies != start && i2c_debug >= 3) | ||
114 | pr_debug("i2c-algo-bit: needed %ld jiffies for SCL to go " | ||
115 | "high\n", jiffies - start); | ||
116 | #endif | ||
102 | 117 | ||
103 | done: | 118 | done: |
104 | udelay(adap->udelay); | 119 | udelay(adap->udelay); |
@@ -110,30 +125,29 @@ done: | |||
110 | static void i2c_start(struct i2c_algo_bit_data *adap) | 125 | static void i2c_start(struct i2c_algo_bit_data *adap) |
111 | { | 126 | { |
112 | /* assert: scl, sda are high */ | 127 | /* assert: scl, sda are high */ |
113 | DEBPROTO(printk("S ")); | 128 | setsda(adap, 0); |
114 | sdalo(adap); | 129 | udelay(adap->udelay); |
115 | scllo(adap); | 130 | scllo(adap); |
116 | } | 131 | } |
117 | 132 | ||
118 | static void i2c_repstart(struct i2c_algo_bit_data *adap) | 133 | static void i2c_repstart(struct i2c_algo_bit_data *adap) |
119 | { | 134 | { |
120 | /* scl, sda may not be high */ | 135 | /* assert: scl is low */ |
121 | DEBPROTO(printk(" Sr ")); | 136 | sdahi(adap); |
122 | setsda(adap,1); | ||
123 | sclhi(adap); | 137 | sclhi(adap); |
124 | 138 | setsda(adap, 0); | |
125 | sdalo(adap); | 139 | udelay(adap->udelay); |
126 | scllo(adap); | 140 | scllo(adap); |
127 | } | 141 | } |
128 | 142 | ||
129 | 143 | ||
130 | static void i2c_stop(struct i2c_algo_bit_data *adap) | 144 | static void i2c_stop(struct i2c_algo_bit_data *adap) |
131 | { | 145 | { |
132 | DEBPROTO(printk("P\n")); | ||
133 | /* assert: scl is low */ | 146 | /* assert: scl is low */ |
134 | sdalo(adap); | 147 | sdalo(adap); |
135 | sclhi(adap); | 148 | sclhi(adap); |
136 | sdahi(adap); | 149 | setsda(adap, 1); |
150 | udelay(adap->udelay); | ||
137 | } | 151 | } |
138 | 152 | ||
139 | 153 | ||
@@ -145,7 +159,7 @@ static void i2c_stop(struct i2c_algo_bit_data *adap) | |||
145 | * 0 if the device did not ack | 159 | * 0 if the device did not ack |
146 | * -ETIMEDOUT if an error occurred (while raising the scl line) | 160 | * -ETIMEDOUT if an error occurred (while raising the scl line) |
147 | */ | 161 | */ |
148 | static int i2c_outb(struct i2c_adapter *i2c_adap, char c) | 162 | static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c) |
149 | { | 163 | { |
150 | int i; | 164 | int i; |
151 | int sb; | 165 | int sb; |
@@ -154,34 +168,32 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, char c) | |||
154 | 168 | ||
155 | /* assert: scl is low */ | 169 | /* assert: scl is low */ |
156 | for ( i=7 ; i>=0 ; i-- ) { | 170 | for ( i=7 ; i>=0 ; i-- ) { |
157 | sb = c & ( 1 << i ); | 171 | sb = (c >> i) & 1; |
158 | setsda(adap,sb); | 172 | setsda(adap,sb); |
159 | udelay(adap->udelay); | 173 | udelay((adap->udelay + 1) / 2); |
160 | DEBPROTO(printk(KERN_DEBUG "%d",sb!=0)); | ||
161 | if (sclhi(adap)<0) { /* timed out */ | 174 | if (sclhi(adap)<0) { /* timed out */ |
162 | sdahi(adap); /* we don't want to block the net */ | 175 | bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, " |
163 | DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at bit #%d\n", c&0xff, i)); | 176 | "timeout at bit #%d\n", (int)c, i); |
164 | return -ETIMEDOUT; | 177 | return -ETIMEDOUT; |
165 | }; | 178 | }; |
166 | /* do arbitration here: | 179 | /* do arbitration here: |
167 | * if ( sb && ! getsda(adap) ) -> ouch! Get out of here. | 180 | * if ( sb && ! getsda(adap) ) -> ouch! Get out of here. |
168 | */ | 181 | */ |
169 | setscl(adap, 0 ); | 182 | scllo(adap); |
170 | udelay(adap->udelay); | ||
171 | } | 183 | } |
172 | sdahi(adap); | 184 | sdahi(adap); |
173 | if (sclhi(adap)<0){ /* timeout */ | 185 | if (sclhi(adap)<0){ /* timeout */ |
174 | DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at ack\n", c&0xff)); | 186 | bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, " |
175 | return -ETIMEDOUT; | 187 | "timeout at ack\n", (int)c); |
188 | return -ETIMEDOUT; | ||
176 | }; | 189 | }; |
177 | /* read ack: SDA should be pulled down by slave */ | 190 | /* read ack: SDA should be pulled down by slave */ |
178 | ack=getsda(adap); /* ack: sda is pulled low ->success. */ | 191 | ack = !getsda(adap); /* ack: sda is pulled low -> success */ |
179 | DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x , getsda() = %d\n", c & 0xff, ack)); | 192 | bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c, |
193 | ack ? "A" : "NA"); | ||
180 | 194 | ||
181 | DEBPROTO( printk(KERN_DEBUG "[%2.2x]",c&0xff) ); | ||
182 | DEBPROTO(if (0==ack){ printk(KERN_DEBUG " A ");} else printk(KERN_DEBUG " NA ") ); | ||
183 | scllo(adap); | 195 | scllo(adap); |
184 | return 0==ack; /* return 1 if device acked */ | 196 | return ack; |
185 | /* assert: scl is low (sda undef) */ | 197 | /* assert: scl is low (sda undef) */ |
186 | } | 198 | } |
187 | 199 | ||
@@ -198,19 +210,18 @@ static int i2c_inb(struct i2c_adapter *i2c_adap) | |||
198 | sdahi(adap); | 210 | sdahi(adap); |
199 | for (i=0;i<8;i++) { | 211 | for (i=0;i<8;i++) { |
200 | if (sclhi(adap)<0) { /* timeout */ | 212 | if (sclhi(adap)<0) { /* timeout */ |
201 | DEB2(printk(KERN_DEBUG " i2c_inb: timeout at bit #%d\n", 7-i)); | 213 | bit_dbg(1, &i2c_adap->dev, "i2c_inb: timeout at bit " |
214 | "#%d\n", 7 - i); | ||
202 | return -ETIMEDOUT; | 215 | return -ETIMEDOUT; |
203 | }; | 216 | }; |
204 | indata *= 2; | 217 | indata *= 2; |
205 | if ( getsda(adap) ) | 218 | if ( getsda(adap) ) |
206 | indata |= 0x01; | 219 | indata |= 0x01; |
207 | scllo(adap); | 220 | setscl(adap, 0); |
221 | udelay(i == 7 ? adap->udelay / 2 : adap->udelay); | ||
208 | } | 222 | } |
209 | /* assert: scl is low */ | 223 | /* assert: scl is low */ |
210 | DEB2(printk(KERN_DEBUG "i2c_inb: 0x%02x\n", indata & 0xff)); | 224 | return indata; |
211 | |||
212 | DEBPROTO(printk(KERN_DEBUG " 0x%02x", indata & 0xff)); | ||
213 | return (int) (indata & 0xff); | ||
214 | } | 225 | } |
215 | 226 | ||
216 | /* | 227 | /* |
@@ -221,73 +232,67 @@ static int test_bus(struct i2c_algo_bit_data *adap, char* name) { | |||
221 | int scl,sda; | 232 | int scl,sda; |
222 | 233 | ||
223 | if (adap->getscl==NULL) | 234 | if (adap->getscl==NULL) |
224 | printk(KERN_INFO "i2c-algo-bit.o: Testing SDA only, " | 235 | pr_info("%s: Testing SDA only, SCL is not readable\n", name); |
225 | "SCL is not readable.\n"); | ||
226 | 236 | ||
227 | sda=getsda(adap); | 237 | sda=getsda(adap); |
228 | scl=(adap->getscl==NULL?1:getscl(adap)); | 238 | scl=(adap->getscl==NULL?1:getscl(adap)); |
229 | printk(KERN_DEBUG "i2c-algo-bit.o: (0) scl=%d, sda=%d\n",scl,sda); | ||
230 | if (!scl || !sda ) { | 239 | if (!scl || !sda ) { |
231 | printk(KERN_WARNING "i2c-algo-bit.o: %s seems to be busy.\n", name); | 240 | printk(KERN_WARNING "%s: bus seems to be busy\n", name); |
232 | goto bailout; | 241 | goto bailout; |
233 | } | 242 | } |
234 | 243 | ||
235 | sdalo(adap); | 244 | sdalo(adap); |
236 | sda=getsda(adap); | 245 | sda=getsda(adap); |
237 | scl=(adap->getscl==NULL?1:getscl(adap)); | 246 | scl=(adap->getscl==NULL?1:getscl(adap)); |
238 | printk(KERN_DEBUG "i2c-algo-bit.o: (1) scl=%d, sda=%d\n",scl,sda); | ||
239 | if ( 0 != sda ) { | 247 | if ( 0 != sda ) { |
240 | printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck high!\n"); | 248 | printk(KERN_WARNING "%s: SDA stuck high!\n", name); |
241 | goto bailout; | 249 | goto bailout; |
242 | } | 250 | } |
243 | if ( 0 == scl ) { | 251 | if ( 0 == scl ) { |
244 | printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low " | 252 | printk(KERN_WARNING "%s: SCL unexpected low " |
245 | "while pulling SDA low!\n"); | 253 | "while pulling SDA low!\n", name); |
246 | goto bailout; | 254 | goto bailout; |
247 | } | 255 | } |
248 | 256 | ||
249 | sdahi(adap); | 257 | sdahi(adap); |
250 | sda=getsda(adap); | 258 | sda=getsda(adap); |
251 | scl=(adap->getscl==NULL?1:getscl(adap)); | 259 | scl=(adap->getscl==NULL?1:getscl(adap)); |
252 | printk(KERN_DEBUG "i2c-algo-bit.o: (2) scl=%d, sda=%d\n",scl,sda); | ||
253 | if ( 0 == sda ) { | 260 | if ( 0 == sda ) { |
254 | printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck low!\n"); | 261 | printk(KERN_WARNING "%s: SDA stuck low!\n", name); |
255 | goto bailout; | 262 | goto bailout; |
256 | } | 263 | } |
257 | if ( 0 == scl ) { | 264 | if ( 0 == scl ) { |
258 | printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low " | 265 | printk(KERN_WARNING "%s: SCL unexpected low " |
259 | "while pulling SDA high!\n"); | 266 | "while pulling SDA high!\n", name); |
260 | goto bailout; | 267 | goto bailout; |
261 | } | 268 | } |
262 | 269 | ||
263 | scllo(adap); | 270 | scllo(adap); |
264 | sda=getsda(adap); | 271 | sda=getsda(adap); |
265 | scl=(adap->getscl==NULL?0:getscl(adap)); | 272 | scl=(adap->getscl==NULL?0:getscl(adap)); |
266 | printk(KERN_DEBUG "i2c-algo-bit.o: (3) scl=%d, sda=%d\n",scl,sda); | ||
267 | if ( 0 != scl ) { | 273 | if ( 0 != scl ) { |
268 | printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck high!\n"); | 274 | printk(KERN_WARNING "%s: SCL stuck high!\n", name); |
269 | goto bailout; | 275 | goto bailout; |
270 | } | 276 | } |
271 | if ( 0 == sda ) { | 277 | if ( 0 == sda ) { |
272 | printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low " | 278 | printk(KERN_WARNING "%s: SDA unexpected low " |
273 | "while pulling SCL low!\n"); | 279 | "while pulling SCL low!\n", name); |
274 | goto bailout; | 280 | goto bailout; |
275 | } | 281 | } |
276 | 282 | ||
277 | sclhi(adap); | 283 | sclhi(adap); |
278 | sda=getsda(adap); | 284 | sda=getsda(adap); |
279 | scl=(adap->getscl==NULL?1:getscl(adap)); | 285 | scl=(adap->getscl==NULL?1:getscl(adap)); |
280 | printk(KERN_DEBUG "i2c-algo-bit.o: (4) scl=%d, sda=%d\n",scl,sda); | ||
281 | if ( 0 == scl ) { | 286 | if ( 0 == scl ) { |
282 | printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck low!\n"); | 287 | printk(KERN_WARNING "%s: SCL stuck low!\n", name); |
283 | goto bailout; | 288 | goto bailout; |
284 | } | 289 | } |
285 | if ( 0 == sda ) { | 290 | if ( 0 == sda ) { |
286 | printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low " | 291 | printk(KERN_WARNING "%s: SDA unexpected low " |
287 | "while pulling SCL high!\n"); | 292 | "while pulling SCL high!\n", name); |
288 | goto bailout; | 293 | goto bailout; |
289 | } | 294 | } |
290 | printk(KERN_INFO "i2c-algo-bit.o: %s passed test.\n",name); | 295 | pr_info("%s: Test OK\n", name); |
291 | return 0; | 296 | return 0; |
292 | bailout: | 297 | bailout: |
293 | sdahi(adap); | 298 | sdahi(adap); |
@@ -312,44 +317,39 @@ static int try_address(struct i2c_adapter *i2c_adap, | |||
312 | int i,ret = -1; | 317 | int i,ret = -1; |
313 | for (i=0;i<=retries;i++) { | 318 | for (i=0;i<=retries;i++) { |
314 | ret = i2c_outb(i2c_adap,addr); | 319 | ret = i2c_outb(i2c_adap,addr); |
315 | if (ret==1) | 320 | if (ret == 1 || i == retries) |
316 | break; /* success! */ | ||
317 | i2c_stop(adap); | ||
318 | udelay(5/*adap->udelay*/); | ||
319 | if (i==retries) /* no success */ | ||
320 | break; | 321 | break; |
321 | i2c_start(adap); | 322 | bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n"); |
323 | i2c_stop(adap); | ||
322 | udelay(adap->udelay); | 324 | udelay(adap->udelay); |
325 | yield(); | ||
326 | bit_dbg(3, &i2c_adap->dev, "emitting start condition\n"); | ||
327 | i2c_start(adap); | ||
323 | } | 328 | } |
324 | DEB2(if (i) | 329 | if (i && ret) |
325 | printk(KERN_DEBUG "i2c-algo-bit.o: Used %d tries to %s client at 0x%02x : %s\n", | 330 | bit_dbg(1, &i2c_adap->dev, "Used %d tries to %s client at " |
326 | i+1, addr & 1 ? "read" : "write", addr>>1, | 331 | "0x%02x: %s\n", i + 1, |
327 | ret==1 ? "success" : ret==0 ? "no ack" : "failed, timeout?" ) | 332 | addr & 1 ? "read from" : "write to", addr >> 1, |
328 | ); | 333 | ret == 1 ? "success" : "failed, timeout?"); |
329 | return ret; | 334 | return ret; |
330 | } | 335 | } |
331 | 336 | ||
332 | static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) | 337 | static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) |
333 | { | 338 | { |
334 | struct i2c_algo_bit_data *adap = i2c_adap->algo_data; | 339 | const unsigned char *temp = msg->buf; |
335 | char c; | ||
336 | const char *temp = msg->buf; | ||
337 | int count = msg->len; | 340 | int count = msg->len; |
338 | unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; | 341 | unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; |
339 | int retval; | 342 | int retval; |
340 | int wrcount=0; | 343 | int wrcount=0; |
341 | 344 | ||
342 | while (count > 0) { | 345 | while (count > 0) { |
343 | c = *temp; | 346 | retval = i2c_outb(i2c_adap, *temp); |
344 | DEB2(dev_dbg(&i2c_adap->dev, "sendbytes: writing %2.2X\n", c&0xff)); | ||
345 | retval = i2c_outb(i2c_adap,c); | ||
346 | if ((retval>0) || (nak_ok && (retval==0))) { /* ok or ignored NAK */ | 347 | if ((retval>0) || (nak_ok && (retval==0))) { /* ok or ignored NAK */ |
347 | count--; | 348 | count--; |
348 | temp++; | 349 | temp++; |
349 | wrcount++; | 350 | wrcount++; |
350 | } else { /* arbitration or no acknowledge */ | 351 | } else { /* arbitration or no acknowledge */ |
351 | dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n"); | 352 | dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n"); |
352 | i2c_stop(adap); | ||
353 | return (retval<0)? retval : -EFAULT; | 353 | return (retval<0)? retval : -EFAULT; |
354 | /* got a better one ?? */ | 354 | /* got a better one ?? */ |
355 | } | 355 | } |
@@ -362,7 +362,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) | |||
362 | int inval; | 362 | int inval; |
363 | int rdcount=0; /* counts bytes read */ | 363 | int rdcount=0; /* counts bytes read */ |
364 | struct i2c_algo_bit_data *adap = i2c_adap->algo_data; | 364 | struct i2c_algo_bit_data *adap = i2c_adap->algo_data; |
365 | char *temp = msg->buf; | 365 | unsigned char *temp = msg->buf; |
366 | int count = msg->len; | 366 | int count = msg->len; |
367 | 367 | ||
368 | while (count > 0) { | 368 | while (count > 0) { |
@@ -371,30 +371,44 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) | |||
371 | *temp = inval; | 371 | *temp = inval; |
372 | rdcount++; | 372 | rdcount++; |
373 | } else { /* read timed out */ | 373 | } else { /* read timed out */ |
374 | printk(KERN_ERR "i2c-algo-bit.o: readbytes: i2c_inb timed out.\n"); | ||
375 | break; | 374 | break; |
376 | } | 375 | } |
377 | 376 | ||
378 | temp++; | 377 | temp++; |
379 | count--; | 378 | count--; |
380 | 379 | ||
381 | if (msg->flags & I2C_M_NO_RD_ACK) | 380 | if (msg->flags & I2C_M_NO_RD_ACK) { |
381 | bit_dbg(2, &i2c_adap->dev, "i2c_inb: 0x%02x\n", | ||
382 | inval); | ||
382 | continue; | 383 | continue; |
383 | |||
384 | if ( count > 0 ) { /* send ack */ | ||
385 | sdalo(adap); | ||
386 | DEBPROTO(printk(" Am ")); | ||
387 | } else { | ||
388 | sdahi(adap); /* neg. ack on last byte */ | ||
389 | DEBPROTO(printk(" NAm ")); | ||
390 | } | 384 | } |
385 | |||
386 | /* assert: sda is high */ | ||
387 | if (count) /* send ack */ | ||
388 | setsda(adap, 0); | ||
389 | udelay((adap->udelay + 1) / 2); | ||
390 | bit_dbg(2, &i2c_adap->dev, "i2c_inb: 0x%02x %s\n", inval, | ||
391 | count ? "A" : "NA"); | ||
391 | if (sclhi(adap)<0) { /* timeout */ | 392 | if (sclhi(adap)<0) { /* timeout */ |
392 | sdahi(adap); | 393 | dev_err(&i2c_adap->dev, "readbytes: timeout at ack\n"); |
393 | printk(KERN_ERR "i2c-algo-bit.o: readbytes: Timeout at ack\n"); | ||
394 | return -ETIMEDOUT; | 394 | return -ETIMEDOUT; |
395 | }; | 395 | }; |
396 | scllo(adap); | 396 | scllo(adap); |
397 | sdahi(adap); | 397 | |
398 | /* Some SMBus transactions require that we receive the | ||
399 | transaction length as the first read byte. */ | ||
400 | if (rdcount == 1 && (msg->flags & I2C_M_RECV_LEN)) { | ||
401 | if (inval <= 0 || inval > I2C_SMBUS_BLOCK_MAX) { | ||
402 | dev_err(&i2c_adap->dev, "readbytes: invalid " | ||
403 | "block length (%d)\n", inval); | ||
404 | return -EREMOTEIO; | ||
405 | } | ||
406 | /* The original count value accounts for the extra | ||
407 | bytes, that is, either 1 for a regular transaction, | ||
408 | or 2 for a PEC transaction. */ | ||
409 | count += inval; | ||
410 | msg->len += inval; | ||
411 | } | ||
398 | } | 412 | } |
399 | return rdcount; | 413 | return rdcount; |
400 | } | 414 | } |
@@ -421,27 +435,31 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) | |||
421 | if ( (flags & I2C_M_TEN) ) { | 435 | if ( (flags & I2C_M_TEN) ) { |
422 | /* a ten bit address */ | 436 | /* a ten bit address */ |
423 | addr = 0xf0 | (( msg->addr >> 7) & 0x03); | 437 | addr = 0xf0 | (( msg->addr >> 7) & 0x03); |
424 | DEB2(printk(KERN_DEBUG "addr0: %d\n",addr)); | 438 | bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr); |
425 | /* try extended address code...*/ | 439 | /* try extended address code...*/ |
426 | ret = try_address(i2c_adap, addr, retries); | 440 | ret = try_address(i2c_adap, addr, retries); |
427 | if ((ret != 1) && !nak_ok) { | 441 | if ((ret != 1) && !nak_ok) { |
428 | printk(KERN_ERR "died at extended address code.\n"); | 442 | dev_err(&i2c_adap->dev, |
443 | "died at extended address code\n"); | ||
429 | return -EREMOTEIO; | 444 | return -EREMOTEIO; |
430 | } | 445 | } |
431 | /* the remaining 8 bit address */ | 446 | /* the remaining 8 bit address */ |
432 | ret = i2c_outb(i2c_adap,msg->addr & 0x7f); | 447 | ret = i2c_outb(i2c_adap,msg->addr & 0x7f); |
433 | if ((ret != 1) && !nak_ok) { | 448 | if ((ret != 1) && !nak_ok) { |
434 | /* the chip did not ack / xmission error occurred */ | 449 | /* the chip did not ack / xmission error occurred */ |
435 | printk(KERN_ERR "died at 2nd address code.\n"); | 450 | dev_err(&i2c_adap->dev, "died at 2nd address code\n"); |
436 | return -EREMOTEIO; | 451 | return -EREMOTEIO; |
437 | } | 452 | } |
438 | if ( flags & I2C_M_RD ) { | 453 | if ( flags & I2C_M_RD ) { |
454 | bit_dbg(3, &i2c_adap->dev, "emitting repeated " | ||
455 | "start condition\n"); | ||
439 | i2c_repstart(adap); | 456 | i2c_repstart(adap); |
440 | /* okay, now switch into reading mode */ | 457 | /* okay, now switch into reading mode */ |
441 | addr |= 0x01; | 458 | addr |= 0x01; |
442 | ret = try_address(i2c_adap, addr, retries); | 459 | ret = try_address(i2c_adap, addr, retries); |
443 | if ((ret!=1) && !nak_ok) { | 460 | if ((ret!=1) && !nak_ok) { |
444 | printk(KERN_ERR "died at extended address code.\n"); | 461 | dev_err(&i2c_adap->dev, |
462 | "died at repeated address code\n"); | ||
445 | return -EREMOTEIO; | 463 | return -EREMOTEIO; |
446 | } | 464 | } |
447 | } | 465 | } |
@@ -468,44 +486,62 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, | |||
468 | int i,ret; | 486 | int i,ret; |
469 | unsigned short nak_ok; | 487 | unsigned short nak_ok; |
470 | 488 | ||
489 | bit_dbg(3, &i2c_adap->dev, "emitting start condition\n"); | ||
471 | i2c_start(adap); | 490 | i2c_start(adap); |
472 | for (i=0;i<num;i++) { | 491 | for (i=0;i<num;i++) { |
473 | pmsg = &msgs[i]; | 492 | pmsg = &msgs[i]; |
474 | nak_ok = pmsg->flags & I2C_M_IGNORE_NAK; | 493 | nak_ok = pmsg->flags & I2C_M_IGNORE_NAK; |
475 | if (!(pmsg->flags & I2C_M_NOSTART)) { | 494 | if (!(pmsg->flags & I2C_M_NOSTART)) { |
476 | if (i) { | 495 | if (i) { |
496 | bit_dbg(3, &i2c_adap->dev, "emitting " | ||
497 | "repeated start condition\n"); | ||
477 | i2c_repstart(adap); | 498 | i2c_repstart(adap); |
478 | } | 499 | } |
479 | ret = bit_doAddress(i2c_adap, pmsg); | 500 | ret = bit_doAddress(i2c_adap, pmsg); |
480 | if ((ret != 0) && !nak_ok) { | 501 | if ((ret != 0) && !nak_ok) { |
481 | DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device addr %2.2x msg #%d\n" | 502 | bit_dbg(1, &i2c_adap->dev, "NAK from " |
482 | ,msgs[i].addr,i)); | 503 | "device addr 0x%02x msg #%d\n", |
483 | return (ret<0) ? ret : -EREMOTEIO; | 504 | msgs[i].addr, i); |
505 | goto bailout; | ||
484 | } | 506 | } |
485 | } | 507 | } |
486 | if (pmsg->flags & I2C_M_RD ) { | 508 | if (pmsg->flags & I2C_M_RD ) { |
487 | /* read bytes into buffer*/ | 509 | /* read bytes into buffer*/ |
488 | ret = readbytes(i2c_adap, pmsg); | 510 | ret = readbytes(i2c_adap, pmsg); |
489 | DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: read %d bytes.\n",ret)); | 511 | if (ret >= 1) |
490 | if (ret < pmsg->len ) { | 512 | bit_dbg(2, &i2c_adap->dev, "read %d byte%s\n", |
491 | return (ret<0)? ret : -EREMOTEIO; | 513 | ret, ret == 1 ? "" : "s"); |
514 | if (ret < pmsg->len) { | ||
515 | if (ret >= 0) | ||
516 | ret = -EREMOTEIO; | ||
517 | goto bailout; | ||
492 | } | 518 | } |
493 | } else { | 519 | } else { |
494 | /* write bytes from buffer */ | 520 | /* write bytes from buffer */ |
495 | ret = sendbytes(i2c_adap, pmsg); | 521 | ret = sendbytes(i2c_adap, pmsg); |
496 | DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: wrote %d bytes.\n",ret)); | 522 | if (ret >= 1) |
497 | if (ret < pmsg->len ) { | 523 | bit_dbg(2, &i2c_adap->dev, "wrote %d byte%s\n", |
498 | return (ret<0) ? ret : -EREMOTEIO; | 524 | ret, ret == 1 ? "" : "s"); |
525 | if (ret < pmsg->len) { | ||
526 | if (ret >= 0) | ||
527 | ret = -EREMOTEIO; | ||
528 | goto bailout; | ||
499 | } | 529 | } |
500 | } | 530 | } |
501 | } | 531 | } |
532 | ret = i; | ||
533 | |||
534 | bailout: | ||
535 | bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n"); | ||
502 | i2c_stop(adap); | 536 | i2c_stop(adap); |
503 | return num; | 537 | return ret; |
504 | } | 538 | } |
505 | 539 | ||
506 | static u32 bit_func(struct i2c_adapter *adap) | 540 | static u32 bit_func(struct i2c_adapter *adap) |
507 | { | 541 | { |
508 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | | 542 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | |
543 | I2C_FUNC_SMBUS_READ_BLOCK_DATA | | ||
544 | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | | ||
509 | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; | 545 | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; |
510 | } | 546 | } |
511 | 547 | ||
@@ -520,7 +556,7 @@ static const struct i2c_algorithm i2c_bit_algo = { | |||
520 | /* | 556 | /* |
521 | * registering functions to load algorithms at runtime | 557 | * registering functions to load algorithms at runtime |
522 | */ | 558 | */ |
523 | int i2c_bit_add_bus(struct i2c_adapter *adap) | 559 | static int i2c_bit_prepare_bus(struct i2c_adapter *adap) |
524 | { | 560 | { |
525 | struct i2c_algo_bit_data *bit_adap = adap->algo_data; | 561 | struct i2c_algo_bit_data *bit_adap = adap->algo_data; |
526 | 562 | ||
@@ -530,25 +566,39 @@ int i2c_bit_add_bus(struct i2c_adapter *adap) | |||
530 | return -ENODEV; | 566 | return -ENODEV; |
531 | } | 567 | } |
532 | 568 | ||
533 | DEB2(dev_dbg(&adap->dev, "hw routines registered.\n")); | ||
534 | |||
535 | /* register new adapter to i2c module... */ | 569 | /* register new adapter to i2c module... */ |
536 | adap->algo = &i2c_bit_algo; | 570 | adap->algo = &i2c_bit_algo; |
537 | 571 | ||
538 | adap->timeout = 100; /* default values, should */ | 572 | adap->timeout = 100; /* default values, should */ |
539 | adap->retries = 3; /* be replaced by defines */ | 573 | adap->retries = 3; /* be replaced by defines */ |
540 | 574 | ||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | int i2c_bit_add_bus(struct i2c_adapter *adap) | ||
579 | { | ||
580 | int err; | ||
581 | |||
582 | err = i2c_bit_prepare_bus(adap); | ||
583 | if (err) | ||
584 | return err; | ||
585 | |||
541 | return i2c_add_adapter(adap); | 586 | return i2c_add_adapter(adap); |
542 | } | 587 | } |
543 | EXPORT_SYMBOL(i2c_bit_add_bus); | 588 | EXPORT_SYMBOL(i2c_bit_add_bus); |
544 | 589 | ||
590 | int i2c_bit_add_numbered_bus(struct i2c_adapter *adap) | ||
591 | { | ||
592 | int err; | ||
593 | |||
594 | err = i2c_bit_prepare_bus(adap); | ||
595 | if (err) | ||
596 | return err; | ||
597 | |||
598 | return i2c_add_numbered_adapter(adap); | ||
599 | } | ||
600 | EXPORT_SYMBOL(i2c_bit_add_numbered_bus); | ||
601 | |||
545 | MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); | 602 | MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); |
546 | MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm"); | 603 | MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm"); |
547 | MODULE_LICENSE("GPL"); | 604 | MODULE_LICENSE("GPL"); |
548 | |||
549 | module_param(bit_test, bool, 0); | ||
550 | module_param(i2c_debug, int, S_IRUGO | S_IWUSR); | ||
551 | |||
552 | MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck"); | ||
553 | MODULE_PARM_DESC(i2c_debug, | ||
554 | "debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol"); | ||
diff --git a/drivers/i2c/algos/i2c-algo-sgi.c b/drivers/i2c/algos/i2c-algo-sgi.c index ac2d5053078a..6eaf145e1ada 100644 --- a/drivers/i2c/algos/i2c-algo-sgi.c +++ b/drivers/i2c/algos/i2c-algo-sgi.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * i2c-algo-sgi.c: i2c driver algorithms for SGI adapters. | 2 | * i2c-algo-sgi.c: i2c driver algorithm used by the VINO (SGI Indy) and |
3 | * | 3 | * MACE (SGI O2) chips. |
4 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | 5 | * This file is subject to the terms and conditions of the GNU General Public |
5 | * License version 2 as published by the Free Software Foundation. | 6 | * License version 2 as published by the Free Software Foundation. |
6 | * | 7 | * |
@@ -162,8 +163,8 @@ static const struct i2c_algorithm sgi_algo = { | |||
162 | .functionality = sgi_func, | 163 | .functionality = sgi_func, |
163 | }; | 164 | }; |
164 | 165 | ||
165 | /* | 166 | /* |
166 | * registering functions to load algorithms at runtime | 167 | * registering functions to load algorithms at runtime |
167 | */ | 168 | */ |
168 | int i2c_sgi_add_bus(struct i2c_adapter *adap) | 169 | int i2c_sgi_add_bus(struct i2c_adapter *adap) |
169 | { | 170 | { |
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index ece31d2c6c64..838dc1c19d61 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -3,11 +3,10 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | menu "I2C Hardware Bus support" | 5 | menu "I2C Hardware Bus support" |
6 | depends on I2C | ||
7 | 6 | ||
8 | config I2C_ALI1535 | 7 | config I2C_ALI1535 |
9 | tristate "ALI 1535" | 8 | tristate "ALI 1535" |
10 | depends on I2C && PCI | 9 | depends on PCI |
11 | help | 10 | help |
12 | If you say yes to this option, support will be included for the SMB | 11 | If you say yes to this option, support will be included for the SMB |
13 | Host controller on Acer Labs Inc. (ALI) M1535 South Bridges. The SMB | 12 | Host controller on Acer Labs Inc. (ALI) M1535 South Bridges. The SMB |
@@ -19,7 +18,7 @@ config I2C_ALI1535 | |||
19 | 18 | ||
20 | config I2C_ALI1563 | 19 | config I2C_ALI1563 |
21 | tristate "ALI 1563" | 20 | tristate "ALI 1563" |
22 | depends on I2C && PCI && EXPERIMENTAL | 21 | depends on PCI && EXPERIMENTAL |
23 | help | 22 | help |
24 | If you say yes to this option, support will be included for the SMB | 23 | If you say yes to this option, support will be included for the SMB |
25 | Host controller on Acer Labs Inc. (ALI) M1563 South Bridges. The SMB | 24 | Host controller on Acer Labs Inc. (ALI) M1563 South Bridges. The SMB |
@@ -31,7 +30,7 @@ config I2C_ALI1563 | |||
31 | 30 | ||
32 | config I2C_ALI15X3 | 31 | config I2C_ALI15X3 |
33 | tristate "ALI 15x3" | 32 | tristate "ALI 15x3" |
34 | depends on I2C && PCI | 33 | depends on PCI |
35 | help | 34 | help |
36 | If you say yes to this option, support will be included for the | 35 | If you say yes to this option, support will be included for the |
37 | Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces. | 36 | Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces. |
@@ -41,7 +40,7 @@ config I2C_ALI15X3 | |||
41 | 40 | ||
42 | config I2C_AMD756 | 41 | config I2C_AMD756 |
43 | tristate "AMD 756/766/768/8111 and nVidia nForce" | 42 | tristate "AMD 756/766/768/8111 and nVidia nForce" |
44 | depends on I2C && PCI | 43 | depends on PCI |
45 | help | 44 | help |
46 | If you say yes to this option, support will be included for the AMD | 45 | If you say yes to this option, support will be included for the AMD |
47 | 756/766/768 mainboard I2C interfaces. The driver also includes | 46 | 756/766/768 mainboard I2C interfaces. The driver also includes |
@@ -66,7 +65,7 @@ config I2C_AMD756_S4882 | |||
66 | 65 | ||
67 | config I2C_AMD8111 | 66 | config I2C_AMD8111 |
68 | tristate "AMD 8111" | 67 | tristate "AMD 8111" |
69 | depends on I2C && PCI | 68 | depends on PCI |
70 | help | 69 | help |
71 | If you say yes to this option, support will be included for the | 70 | If you say yes to this option, support will be included for the |
72 | second (SMBus 2.0) AMD 8111 mainboard I2C interface. | 71 | second (SMBus 2.0) AMD 8111 mainboard I2C interface. |
@@ -76,14 +75,14 @@ config I2C_AMD8111 | |||
76 | 75 | ||
77 | config I2C_AT91 | 76 | config I2C_AT91 |
78 | tristate "Atmel AT91 I2C Two-Wire interface (TWI)" | 77 | tristate "Atmel AT91 I2C Two-Wire interface (TWI)" |
79 | depends on I2C && ARCH_AT91 && EXPERIMENTAL | 78 | depends on ARCH_AT91 && EXPERIMENTAL |
80 | help | 79 | help |
81 | This supports the use of the I2C interface on Atmel AT91 | 80 | This supports the use of the I2C interface on Atmel AT91 |
82 | processors. | 81 | processors. |
83 | 82 | ||
84 | config I2C_AU1550 | 83 | config I2C_AU1550 |
85 | tristate "Au1550/Au1200 SMBus interface" | 84 | tristate "Au1550/Au1200 SMBus interface" |
86 | depends on I2C && (SOC_AU1550 || SOC_AU1200) | 85 | depends on SOC_AU1550 || SOC_AU1200 |
87 | help | 86 | help |
88 | If you say yes to this option, support will be included for the | 87 | If you say yes to this option, support will be included for the |
89 | Au1550 and Au1200 SMBus interface. | 88 | Au1550 and Au1200 SMBus interface. |
@@ -91,9 +90,25 @@ config I2C_AU1550 | |||
91 | This driver can also be built as a module. If so, the module | 90 | This driver can also be built as a module. If so, the module |
92 | will be called i2c-au1550. | 91 | will be called i2c-au1550. |
93 | 92 | ||
93 | config I2C_BLACKFIN_TWI | ||
94 | tristate "Blackfin TWI I2C support" | ||
95 | depends on BF534 || BF536 || BF537 | ||
96 | help | ||
97 | This is the TWI I2C device driver for Blackfin 534/536/537. | ||
98 | This driver can also be built as a module. If so, the module | ||
99 | will be called i2c-bfin-twi. | ||
100 | |||
101 | config I2C_BLACKFIN_TWI_CLK_KHZ | ||
102 | int "Blackfin TWI I2C clock (kHz)" | ||
103 | depends on I2C_BLACKFIN_TWI | ||
104 | range 10 400 | ||
105 | default 50 | ||
106 | help | ||
107 | The unit of the TWI clock is kHz. | ||
108 | |||
94 | config I2C_ELEKTOR | 109 | config I2C_ELEKTOR |
95 | tristate "Elektor ISA card" | 110 | tristate "Elektor ISA card" |
96 | depends on I2C && ISA && BROKEN_ON_SMP | 111 | depends on ISA && BROKEN_ON_SMP |
97 | select I2C_ALGOPCF | 112 | select I2C_ALGOPCF |
98 | help | 113 | help |
99 | This supports the PCF8584 ISA bus I2C adapter. Say Y if you own | 114 | This supports the PCF8584 ISA bus I2C adapter. Say Y if you own |
@@ -102,9 +117,17 @@ config I2C_ELEKTOR | |||
102 | This support is also available as a module. If so, the module | 117 | This support is also available as a module. If so, the module |
103 | will be called i2c-elektor. | 118 | will be called i2c-elektor. |
104 | 119 | ||
120 | config I2C_GPIO | ||
121 | tristate "GPIO-based bitbanging I2C" | ||
122 | depends on GENERIC_GPIO | ||
123 | select I2C_ALGOBIT | ||
124 | help | ||
125 | This is a very simple bitbanging I2C driver utilizing the | ||
126 | arch-neutral GPIO API to control the SCL and SDA lines. | ||
127 | |||
105 | config I2C_HYDRA | 128 | config I2C_HYDRA |
106 | tristate "CHRP Apple Hydra Mac I/O I2C interface" | 129 | tristate "CHRP Apple Hydra Mac I/O I2C interface" |
107 | depends on I2C && PCI && PPC_CHRP && EXPERIMENTAL | 130 | depends on PCI && PPC_CHRP && EXPERIMENTAL |
108 | select I2C_ALGOBIT | 131 | select I2C_ALGOBIT |
109 | help | 132 | help |
110 | This supports the use of the I2C interface in the Apple Hydra Mac | 133 | This supports the use of the I2C interface in the Apple Hydra Mac |
@@ -116,7 +139,7 @@ config I2C_HYDRA | |||
116 | 139 | ||
117 | config I2C_I801 | 140 | config I2C_I801 |
118 | tristate "Intel 82801 (ICH)" | 141 | tristate "Intel 82801 (ICH)" |
119 | depends on I2C && PCI | 142 | depends on PCI |
120 | help | 143 | help |
121 | If you say yes to this option, support will be included for the Intel | 144 | If you say yes to this option, support will be included for the Intel |
122 | 801 family of mainboard I2C interfaces. Specifically, the following | 145 | 801 family of mainboard I2C interfaces. Specifically, the following |
@@ -139,7 +162,7 @@ config I2C_I801 | |||
139 | 162 | ||
140 | config I2C_I810 | 163 | config I2C_I810 |
141 | tristate "Intel 810/815" | 164 | tristate "Intel 810/815" |
142 | depends on I2C && PCI | 165 | depends on PCI |
143 | select I2C_ALGOBIT | 166 | select I2C_ALGOBIT |
144 | help | 167 | help |
145 | If you say yes to this option, support will be included for the Intel | 168 | If you say yes to this option, support will be included for the Intel |
@@ -156,7 +179,7 @@ config I2C_I810 | |||
156 | 179 | ||
157 | config I2C_PXA | 180 | config I2C_PXA |
158 | tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)" | 181 | tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)" |
159 | depends on I2C && EXPERIMENTAL && ARCH_PXA | 182 | depends on EXPERIMENTAL && ARCH_PXA |
160 | help | 183 | help |
161 | If you have devices in the PXA I2C bus, say yes to this option. | 184 | If you have devices in the PXA I2C bus, say yes to this option. |
162 | This driver can also be built as a module. If so, the module | 185 | This driver can also be built as a module. If so, the module |
@@ -172,7 +195,7 @@ config I2C_PXA_SLAVE | |||
172 | 195 | ||
173 | config I2C_PIIX4 | 196 | config I2C_PIIX4 |
174 | tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)" | 197 | tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)" |
175 | depends on I2C && PCI | 198 | depends on PCI |
176 | help | 199 | help |
177 | If you say yes to this option, support will be included for the Intel | 200 | If you say yes to this option, support will be included for the Intel |
178 | PIIX4 family of mainboard I2C interfaces. Specifically, the following | 201 | PIIX4 family of mainboard I2C interfaces. Specifically, the following |
@@ -195,7 +218,7 @@ config I2C_PIIX4 | |||
195 | 218 | ||
196 | config I2C_IBM_IIC | 219 | config I2C_IBM_IIC |
197 | tristate "IBM PPC 4xx on-chip I2C interface" | 220 | tristate "IBM PPC 4xx on-chip I2C interface" |
198 | depends on IBM_OCP && I2C | 221 | depends on IBM_OCP |
199 | help | 222 | help |
200 | Say Y here if you want to use IIC peripheral found on | 223 | Say Y here if you want to use IIC peripheral found on |
201 | embedded IBM PPC 4xx based systems. | 224 | embedded IBM PPC 4xx based systems. |
@@ -205,7 +228,7 @@ config I2C_IBM_IIC | |||
205 | 228 | ||
206 | config I2C_IOP3XX | 229 | config I2C_IOP3XX |
207 | tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface" | 230 | tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface" |
208 | depends on (ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX) && I2C | 231 | depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX |
209 | help | 232 | help |
210 | Say Y here if you want to use the IIC bus controller on | 233 | Say Y here if you want to use the IIC bus controller on |
211 | the Intel IOPx3xx I/O Processors or IXP4xx Network Processors. | 234 | the Intel IOPx3xx I/O Processors or IXP4xx Network Processors. |
@@ -215,11 +238,10 @@ config I2C_IOP3XX | |||
215 | 238 | ||
216 | config I2C_ISA | 239 | config I2C_ISA |
217 | tristate | 240 | tristate |
218 | depends on I2C | ||
219 | 241 | ||
220 | config I2C_IXP4XX | 242 | config I2C_IXP4XX |
221 | tristate "IXP4xx GPIO-Based I2C Interface" | 243 | tristate "IXP4xx GPIO-Based I2C Interface (DEPRECATED)" |
222 | depends on I2C && ARCH_IXP4XX | 244 | depends on ARCH_IXP4XX |
223 | select I2C_ALGOBIT | 245 | select I2C_ALGOBIT |
224 | help | 246 | help |
225 | Say Y here if you have an Intel IXP4xx(420,421,422,425) based | 247 | Say Y here if you have an Intel IXP4xx(420,421,422,425) based |
@@ -228,9 +250,12 @@ config I2C_IXP4XX | |||
228 | This support is also available as a module. If so, the module | 250 | This support is also available as a module. If so, the module |
229 | will be called i2c-ixp4xx. | 251 | will be called i2c-ixp4xx. |
230 | 252 | ||
253 | This driver is deprecated and will be dropped soon. Use i2c-gpio | ||
254 | instead. | ||
255 | |||
231 | config I2C_IXP2000 | 256 | config I2C_IXP2000 |
232 | tristate "IXP2000 GPIO-Based I2C Interface" | 257 | tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)" |
233 | depends on I2C && ARCH_IXP2000 | 258 | depends on ARCH_IXP2000 |
234 | select I2C_ALGOBIT | 259 | select I2C_ALGOBIT |
235 | help | 260 | help |
236 | Say Y here if you have an Intel IXP2000(2400, 2800, 2850) based | 261 | Say Y here if you have an Intel IXP2000(2400, 2800, 2850) based |
@@ -239,9 +264,12 @@ config I2C_IXP2000 | |||
239 | This support is also available as a module. If so, the module | 264 | This support is also available as a module. If so, the module |
240 | will be called i2c-ixp2000. | 265 | will be called i2c-ixp2000. |
241 | 266 | ||
267 | This driver is deprecated and will be dropped soon. Use i2c-gpio | ||
268 | instead. | ||
269 | |||
242 | config I2C_POWERMAC | 270 | config I2C_POWERMAC |
243 | tristate "Powermac I2C interface" | 271 | tristate "Powermac I2C interface" |
244 | depends on I2C && PPC_PMAC | 272 | depends on PPC_PMAC |
245 | default y | 273 | default y |
246 | help | 274 | help |
247 | This exposes the various PowerMac i2c interfaces to the linux i2c | 275 | This exposes the various PowerMac i2c interfaces to the linux i2c |
@@ -253,7 +281,7 @@ config I2C_POWERMAC | |||
253 | 281 | ||
254 | config I2C_MPC | 282 | config I2C_MPC |
255 | tristate "MPC107/824x/85xx/52xx/86xx" | 283 | tristate "MPC107/824x/85xx/52xx/86xx" |
256 | depends on I2C && PPC32 | 284 | depends on PPC32 |
257 | help | 285 | help |
258 | If you say yes to this option, support will be included for the | 286 | If you say yes to this option, support will be included for the |
259 | built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and | 287 | built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and |
@@ -265,7 +293,7 @@ config I2C_MPC | |||
265 | 293 | ||
266 | config I2C_NFORCE2 | 294 | config I2C_NFORCE2 |
267 | tristate "Nvidia nForce2, nForce3 and nForce4" | 295 | tristate "Nvidia nForce2, nForce3 and nForce4" |
268 | depends on I2C && PCI | 296 | depends on PCI |
269 | help | 297 | help |
270 | If you say yes to this option, support will be included for the Nvidia | 298 | If you say yes to this option, support will be included for the Nvidia |
271 | nForce2, nForce3 and nForce4 families of mainboard I2C interfaces. | 299 | nForce2, nForce3 and nForce4 families of mainboard I2C interfaces. |
@@ -275,7 +303,7 @@ config I2C_NFORCE2 | |||
275 | 303 | ||
276 | config I2C_OCORES | 304 | config I2C_OCORES |
277 | tristate "OpenCores I2C Controller" | 305 | tristate "OpenCores I2C Controller" |
278 | depends on I2C && EXPERIMENTAL | 306 | depends on EXPERIMENTAL |
279 | help | 307 | help |
280 | If you say yes to this option, support will be included for the | 308 | If you say yes to this option, support will be included for the |
281 | OpenCores I2C controller. For details see | 309 | OpenCores I2C controller. For details see |
@@ -286,7 +314,7 @@ config I2C_OCORES | |||
286 | 314 | ||
287 | config I2C_OMAP | 315 | config I2C_OMAP |
288 | tristate "OMAP I2C adapter" | 316 | tristate "OMAP I2C adapter" |
289 | depends on I2C && ARCH_OMAP | 317 | depends on ARCH_OMAP |
290 | default y if MACH_OMAP_H3 || MACH_OMAP_OSK | 318 | default y if MACH_OMAP_H3 || MACH_OMAP_OSK |
291 | help | 319 | help |
292 | If you say yes to this option, support will be included for the | 320 | If you say yes to this option, support will be included for the |
@@ -296,7 +324,7 @@ config I2C_OMAP | |||
296 | 324 | ||
297 | config I2C_PARPORT | 325 | config I2C_PARPORT |
298 | tristate "Parallel port adapter" | 326 | tristate "Parallel port adapter" |
299 | depends on I2C && PARPORT | 327 | depends on PARPORT |
300 | select I2C_ALGOBIT | 328 | select I2C_ALGOBIT |
301 | help | 329 | help |
302 | This supports parallel port I2C adapters such as the ones made by | 330 | This supports parallel port I2C adapters such as the ones made by |
@@ -320,7 +348,6 @@ config I2C_PARPORT | |||
320 | 348 | ||
321 | config I2C_PARPORT_LIGHT | 349 | config I2C_PARPORT_LIGHT |
322 | tristate "Parallel port adapter (light)" | 350 | tristate "Parallel port adapter (light)" |
323 | depends on I2C | ||
324 | select I2C_ALGOBIT | 351 | select I2C_ALGOBIT |
325 | help | 352 | help |
326 | This supports parallel port I2C adapters such as the ones made by | 353 | This supports parallel port I2C adapters such as the ones made by |
@@ -344,13 +371,13 @@ config I2C_PARPORT_LIGHT | |||
344 | 371 | ||
345 | config I2C_PASEMI | 372 | config I2C_PASEMI |
346 | tristate "PA Semi SMBus interface" | 373 | tristate "PA Semi SMBus interface" |
347 | depends on PPC_PASEMI && I2C && PCI | 374 | depends on PPC_PASEMI && PCI |
348 | help | 375 | help |
349 | Supports the PA Semi PWRficient on-chip SMBus interfaces. | 376 | Supports the PA Semi PWRficient on-chip SMBus interfaces. |
350 | 377 | ||
351 | config I2C_PROSAVAGE | 378 | config I2C_PROSAVAGE |
352 | tristate "S3/VIA (Pro)Savage" | 379 | tristate "S3/VIA (Pro)Savage" |
353 | depends on I2C && PCI | 380 | depends on PCI |
354 | select I2C_ALGOBIT | 381 | select I2C_ALGOBIT |
355 | help | 382 | help |
356 | If you say yes to this option, support will be included for the | 383 | If you say yes to this option, support will be included for the |
@@ -365,19 +392,19 @@ config I2C_PROSAVAGE | |||
365 | 392 | ||
366 | config I2C_RPXLITE | 393 | config I2C_RPXLITE |
367 | tristate "Embedded Planet RPX Lite/Classic support" | 394 | tristate "Embedded Planet RPX Lite/Classic support" |
368 | depends on (RPXLITE || RPXCLASSIC) && I2C | 395 | depends on RPXLITE || RPXCLASSIC |
369 | select I2C_ALGO8XX | 396 | select I2C_ALGO8XX |
370 | 397 | ||
371 | config I2C_S3C2410 | 398 | config I2C_S3C2410 |
372 | tristate "S3C2410 I2C Driver" | 399 | tristate "S3C2410 I2C Driver" |
373 | depends on I2C && ARCH_S3C2410 | 400 | depends on ARCH_S3C2410 |
374 | help | 401 | help |
375 | Say Y here to include support for I2C controller in the | 402 | Say Y here to include support for I2C controller in the |
376 | Samsung S3C2410 based System-on-Chip devices. | 403 | Samsung S3C2410 based System-on-Chip devices. |
377 | 404 | ||
378 | config I2C_SAVAGE4 | 405 | config I2C_SAVAGE4 |
379 | tristate "S3 Savage 4" | 406 | tristate "S3 Savage 4" |
380 | depends on I2C && PCI && EXPERIMENTAL | 407 | depends on PCI && EXPERIMENTAL |
381 | select I2C_ALGOBIT | 408 | select I2C_ALGOBIT |
382 | help | 409 | help |
383 | If you say yes to this option, support will be included for the | 410 | If you say yes to this option, support will be included for the |
@@ -388,13 +415,25 @@ config I2C_SAVAGE4 | |||
388 | 415 | ||
389 | config I2C_SIBYTE | 416 | config I2C_SIBYTE |
390 | tristate "SiByte SMBus interface" | 417 | tristate "SiByte SMBus interface" |
391 | depends on SIBYTE_SB1xxx_SOC && I2C | 418 | depends on SIBYTE_SB1xxx_SOC |
392 | help | 419 | help |
393 | Supports the SiByte SOC on-chip I2C interfaces (2 channels). | 420 | Supports the SiByte SOC on-chip I2C interfaces (2 channels). |
394 | 421 | ||
422 | config I2C_SIMTEC | ||
423 | tristate "Simtec Generic I2C interface" | ||
424 | select I2C_ALGOBIT | ||
425 | help | ||
426 | If you say yes to this option, support will be inclyded for | ||
427 | the Simtec Generic I2C interface. This driver is for the | ||
428 | simple I2C bus used on newer Simtec products for general | ||
429 | I2C, such as DDC on the Simtec BBD2016A. | ||
430 | |||
431 | This driver can also be build as a module. If so, the module | ||
432 | will be called i2c-simtec. | ||
433 | |||
395 | config SCx200_I2C | 434 | config SCx200_I2C |
396 | tristate "NatSemi SCx200 I2C using GPIO pins" | 435 | tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)" |
397 | depends on SCx200_GPIO && I2C | 436 | depends on SCx200_GPIO |
398 | select I2C_ALGOBIT | 437 | select I2C_ALGOBIT |
399 | help | 438 | help |
400 | Enable the use of two GPIO pins of a SCx200 processor as an I2C bus. | 439 | Enable the use of two GPIO pins of a SCx200 processor as an I2C bus. |
@@ -404,6 +443,9 @@ config SCx200_I2C | |||
404 | This support is also available as a module. If so, the module | 443 | This support is also available as a module. If so, the module |
405 | will be called scx200_i2c. | 444 | will be called scx200_i2c. |
406 | 445 | ||
446 | This driver is deprecated and will be dropped soon. Use i2c-gpio | ||
447 | (or scx200_acb) instead. | ||
448 | |||
407 | config SCx200_I2C_SCL | 449 | config SCx200_I2C_SCL |
408 | int "GPIO pin used for SCL" | 450 | int "GPIO pin used for SCL" |
409 | depends on SCx200_I2C | 451 | depends on SCx200_I2C |
@@ -422,7 +464,7 @@ config SCx200_I2C_SDA | |||
422 | 464 | ||
423 | config SCx200_ACB | 465 | config SCx200_ACB |
424 | tristate "Geode ACCESS.bus support" | 466 | tristate "Geode ACCESS.bus support" |
425 | depends on X86_32 && I2C && PCI | 467 | depends on X86_32 && PCI |
426 | help | 468 | help |
427 | Enable the use of the ACCESS.bus controllers on the Geode SCx200 and | 469 | Enable the use of the ACCESS.bus controllers on the Geode SCx200 and |
428 | SC1100 processors and the CS5535 and CS5536 Geode companion devices. | 470 | SC1100 processors and the CS5535 and CS5536 Geode companion devices. |
@@ -434,7 +476,7 @@ config SCx200_ACB | |||
434 | 476 | ||
435 | config I2C_SIS5595 | 477 | config I2C_SIS5595 |
436 | tristate "SiS 5595" | 478 | tristate "SiS 5595" |
437 | depends on I2C && PCI | 479 | depends on PCI |
438 | help | 480 | help |
439 | If you say yes to this option, support will be included for the | 481 | If you say yes to this option, support will be included for the |
440 | SiS5595 SMBus (a subset of I2C) interface. | 482 | SiS5595 SMBus (a subset of I2C) interface. |
@@ -444,7 +486,7 @@ config I2C_SIS5595 | |||
444 | 486 | ||
445 | config I2C_SIS630 | 487 | config I2C_SIS630 |
446 | tristate "SiS 630/730" | 488 | tristate "SiS 630/730" |
447 | depends on I2C && PCI | 489 | depends on PCI |
448 | help | 490 | help |
449 | If you say yes to this option, support will be included for the | 491 | If you say yes to this option, support will be included for the |
450 | SiS630 and SiS730 SMBus (a subset of I2C) interface. | 492 | SiS630 and SiS730 SMBus (a subset of I2C) interface. |
@@ -454,7 +496,7 @@ config I2C_SIS630 | |||
454 | 496 | ||
455 | config I2C_SIS96X | 497 | config I2C_SIS96X |
456 | tristate "SiS 96x" | 498 | tristate "SiS 96x" |
457 | depends on I2C && PCI | 499 | depends on PCI |
458 | help | 500 | help |
459 | If you say yes to this option, support will be included for the SiS | 501 | If you say yes to this option, support will be included for the SiS |
460 | 96x SMBus (a subset of I2C) interfaces. Specifically, the following | 502 | 96x SMBus (a subset of I2C) interfaces. Specifically, the following |
@@ -472,7 +514,7 @@ config I2C_SIS96X | |||
472 | 514 | ||
473 | config I2C_STUB | 515 | config I2C_STUB |
474 | tristate "I2C/SMBus Test Stub" | 516 | tristate "I2C/SMBus Test Stub" |
475 | depends on I2C && EXPERIMENTAL && 'm' | 517 | depends on EXPERIMENTAL && m |
476 | default 'n' | 518 | default 'n' |
477 | help | 519 | help |
478 | This module may be useful to developers of SMBus client drivers, | 520 | This module may be useful to developers of SMBus client drivers, |
@@ -483,9 +525,20 @@ config I2C_STUB | |||
483 | 525 | ||
484 | If you don't know what to do here, definitely say N. | 526 | If you don't know what to do here, definitely say N. |
485 | 527 | ||
528 | config I2C_TINY_USB | ||
529 | tristate "I2C-Tiny-USB" | ||
530 | depends on USB | ||
531 | help | ||
532 | If you say yes to this option, support will be included for the | ||
533 | i2c-tiny-usb, a simple do-it-yourself USB to I2C interface. See | ||
534 | http://www.harbaum.org/till/i2c_tiny_usb for hardware details. | ||
535 | |||
536 | This driver can also be built as a module. If so, the module | ||
537 | will be called i2c-tiny-usb. | ||
538 | |||
486 | config I2C_VERSATILE | 539 | config I2C_VERSATILE |
487 | tristate "ARM Versatile/Realview I2C bus support" | 540 | tristate "ARM Versatile/Realview I2C bus support" |
488 | depends on I2C && (ARCH_VERSATILE || ARCH_REALVIEW) | 541 | depends on ARCH_VERSATILE || ARCH_REALVIEW |
489 | select I2C_ALGOBIT | 542 | select I2C_ALGOBIT |
490 | help | 543 | help |
491 | Say yes if you want to support the I2C serial bus on ARMs Versatile | 544 | Say yes if you want to support the I2C serial bus on ARMs Versatile |
@@ -496,7 +549,7 @@ config I2C_VERSATILE | |||
496 | 549 | ||
497 | config I2C_ACORN | 550 | config I2C_ACORN |
498 | bool "Acorn IOC/IOMD I2C bus support" | 551 | bool "Acorn IOC/IOMD I2C bus support" |
499 | depends on I2C && ARCH_ACORN | 552 | depends on ARCH_ACORN |
500 | default y | 553 | default y |
501 | select I2C_ALGOBIT | 554 | select I2C_ALGOBIT |
502 | help | 555 | help |
@@ -506,7 +559,7 @@ config I2C_ACORN | |||
506 | 559 | ||
507 | config I2C_VIA | 560 | config I2C_VIA |
508 | tristate "VIA 82C586B" | 561 | tristate "VIA 82C586B" |
509 | depends on I2C && PCI && EXPERIMENTAL | 562 | depends on PCI && EXPERIMENTAL |
510 | select I2C_ALGOBIT | 563 | select I2C_ALGOBIT |
511 | help | 564 | help |
512 | If you say yes to this option, support will be included for the VIA | 565 | If you say yes to this option, support will be included for the VIA |
@@ -517,7 +570,7 @@ config I2C_VIA | |||
517 | 570 | ||
518 | config I2C_VIAPRO | 571 | config I2C_VIAPRO |
519 | tristate "VIA VT82C596/82C686/82xx and CX700" | 572 | tristate "VIA VT82C596/82C686/82xx and CX700" |
520 | depends on I2C && PCI | 573 | depends on PCI |
521 | help | 574 | help |
522 | If you say yes to this option, support will be included for the VIA | 575 | If you say yes to this option, support will be included for the VIA |
523 | VT82C596 and later SMBus interface. Specifically, the following | 576 | VT82C596 and later SMBus interface. Specifically, the following |
@@ -536,7 +589,7 @@ config I2C_VIAPRO | |||
536 | 589 | ||
537 | config I2C_VOODOO3 | 590 | config I2C_VOODOO3 |
538 | tristate "Voodoo 3" | 591 | tristate "Voodoo 3" |
539 | depends on I2C && PCI | 592 | depends on PCI |
540 | select I2C_ALGOBIT | 593 | select I2C_ALGOBIT |
541 | help | 594 | help |
542 | If you say yes to this option, support will be included for the | 595 | If you say yes to this option, support will be included for the |
@@ -547,7 +600,7 @@ config I2C_VOODOO3 | |||
547 | 600 | ||
548 | config I2C_PCA_ISA | 601 | config I2C_PCA_ISA |
549 | tristate "PCA9564 on an ISA bus" | 602 | tristate "PCA9564 on an ISA bus" |
550 | depends on I2C | 603 | depends on ISA |
551 | select I2C_ALGOPCA | 604 | select I2C_ALGOPCA |
552 | default n | 605 | default n |
553 | help | 606 | help |
@@ -564,7 +617,7 @@ config I2C_PCA_ISA | |||
564 | 617 | ||
565 | config I2C_MV64XXX | 618 | config I2C_MV64XXX |
566 | tristate "Marvell mv64xxx I2C Controller" | 619 | tristate "Marvell mv64xxx I2C Controller" |
567 | depends on I2C && MV64X60 && EXPERIMENTAL | 620 | depends on MV64X60 && EXPERIMENTAL |
568 | help | 621 | help |
569 | If you say yes to this option, support will be included for the | 622 | If you say yes to this option, support will be included for the |
570 | built-in I2C interface on the Marvell 64xxx line of host bridges. | 623 | built-in I2C interface on the Marvell 64xxx line of host bridges. |
@@ -574,7 +627,7 @@ config I2C_MV64XXX | |||
574 | 627 | ||
575 | config I2C_PNX | 628 | config I2C_PNX |
576 | tristate "I2C bus support for Philips PNX targets" | 629 | tristate "I2C bus support for Philips PNX targets" |
577 | depends on ARCH_PNX4008 && I2C | 630 | depends on ARCH_PNX4008 |
578 | help | 631 | help |
579 | This driver supports the Philips IP3204 I2C IP block master and/or | 632 | This driver supports the Philips IP3204 I2C IP block master and/or |
580 | slave controller | 633 | slave controller |
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 290b54018354..14d1432f698b 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile | |||
@@ -10,7 +10,9 @@ obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o | |||
10 | obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o | 10 | obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o |
11 | obj-$(CONFIG_I2C_AT91) += i2c-at91.o | 11 | obj-$(CONFIG_I2C_AT91) += i2c-at91.o |
12 | obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o | 12 | obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o |
13 | obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o | ||
13 | obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o | 14 | obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o |
15 | obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o | ||
14 | obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o | 16 | obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o |
15 | obj-$(CONFIG_I2C_I801) += i2c-i801.o | 17 | obj-$(CONFIG_I2C_I801) += i2c-i801.o |
16 | obj-$(CONFIG_I2C_I810) += i2c-i810.o | 18 | obj-$(CONFIG_I2C_I810) += i2c-i810.o |
@@ -37,10 +39,12 @@ obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o | |||
37 | obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o | 39 | obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o |
38 | obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o | 40 | obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o |
39 | obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o | 41 | obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o |
42 | obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o | ||
40 | obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o | 43 | obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o |
41 | obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o | 44 | obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o |
42 | obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o | 45 | obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o |
43 | obj-$(CONFIG_I2C_STUB) += i2c-stub.o | 46 | obj-$(CONFIG_I2C_STUB) += i2c-stub.o |
47 | obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o | ||
44 | obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o | 48 | obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o |
45 | obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o | 49 | obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o |
46 | obj-$(CONFIG_I2C_VIA) += i2c-via.o | 50 | obj-$(CONFIG_I2C_VIA) += i2c-via.o |
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index 1e277ba5a9f3..f14372ac2fc5 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c | |||
@@ -497,7 +497,7 @@ static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_ | |||
497 | /* set up the sysfs linkage to our parent device */ | 497 | /* set up the sysfs linkage to our parent device */ |
498 | ali1535_adapter.dev.parent = &dev->dev; | 498 | ali1535_adapter.dev.parent = &dev->dev; |
499 | 499 | ||
500 | snprintf(ali1535_adapter.name, I2C_NAME_SIZE, | 500 | snprintf(ali1535_adapter.name, sizeof(ali1535_adapter.name), |
501 | "SMBus ALI1535 adapter at %04x", ali1535_smba); | 501 | "SMBus ALI1535 adapter at %04x", ali1535_smba); |
502 | return i2c_add_adapter(&ali1535_adapter); | 502 | return i2c_add_adapter(&ali1535_adapter); |
503 | } | 503 | } |
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index e47fe01bf42a..93bf87d70961 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c | |||
@@ -492,7 +492,7 @@ static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_ | |||
492 | /* set up the sysfs linkage to our parent device */ | 492 | /* set up the sysfs linkage to our parent device */ |
493 | ali15x3_adapter.dev.parent = &dev->dev; | 493 | ali15x3_adapter.dev.parent = &dev->dev; |
494 | 494 | ||
495 | snprintf(ali15x3_adapter.name, I2C_NAME_SIZE, | 495 | snprintf(ali15x3_adapter.name, sizeof(ali15x3_adapter.name), |
496 | "SMBus ALI15X3 adapter at %04x", ali15x3_smba); | 496 | "SMBus ALI15X3 adapter at %04x", ali15x3_smba); |
497 | return i2c_add_adapter(&ali15x3_adapter); | 497 | return i2c_add_adapter(&ali15x3_adapter); |
498 | } | 498 | } |
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index 0c70f8293341..c9fca7b49267 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c | |||
@@ -365,7 +365,7 @@ static int __devinit amd8111_probe(struct pci_dev *dev, | |||
365 | } | 365 | } |
366 | 366 | ||
367 | smbus->adapter.owner = THIS_MODULE; | 367 | smbus->adapter.owner = THIS_MODULE; |
368 | snprintf(smbus->adapter.name, I2C_NAME_SIZE, | 368 | snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), |
369 | "SMBus2 AMD8111 adapter at %04x", smbus->base); | 369 | "SMBus2 AMD8111 adapter at %04x", smbus->base); |
370 | smbus->adapter.id = I2C_HW_SMBUS_AMD8111; | 370 | smbus->adapter.id = I2C_HW_SMBUS_AMD8111; |
371 | smbus->adapter.class = I2C_CLASS_HWMON; | 371 | smbus->adapter.class = I2C_CLASS_HWMON; |
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index 67f91bdda089..f35156c58922 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/version.h> | 17 | #include <linux/version.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/pci.h> | ||
21 | #include <linux/types.h> | 20 | #include <linux/types.h> |
22 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
23 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c new file mode 100644 index 000000000000..6311039dfe60 --- /dev/null +++ b/drivers/i2c/busses/i2c-bfin-twi.c | |||
@@ -0,0 +1,644 @@ | |||
1 | /* | ||
2 | * drivers/i2c/busses/i2c-bfin-twi.c | ||
3 | * | ||
4 | * Description: Driver for Blackfin Two Wire Interface | ||
5 | * | ||
6 | * Author: sonicz <sonic.zhang@analog.com> | ||
7 | * | ||
8 | * Copyright (c) 2005-2007 Analog Devices, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/i2c.h> | ||
29 | #include <linux/mm.h> | ||
30 | #include <linux/timer.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | #include <linux/completion.h> | ||
33 | #include <linux/interrupt.h> | ||
34 | #include <linux/platform_device.h> | ||
35 | |||
36 | #include <asm/blackfin.h> | ||
37 | #include <asm/irq.h> | ||
38 | |||
39 | #define POLL_TIMEOUT (2 * HZ) | ||
40 | |||
41 | /* SMBus mode*/ | ||
42 | #define TWI_I2C_MODE_STANDARD 0x01 | ||
43 | #define TWI_I2C_MODE_STANDARDSUB 0x02 | ||
44 | #define TWI_I2C_MODE_COMBINED 0x04 | ||
45 | |||
46 | struct bfin_twi_iface { | ||
47 | struct mutex twi_lock; | ||
48 | int irq; | ||
49 | spinlock_t lock; | ||
50 | char read_write; | ||
51 | u8 command; | ||
52 | u8 *transPtr; | ||
53 | int readNum; | ||
54 | int writeNum; | ||
55 | int cur_mode; | ||
56 | int manual_stop; | ||
57 | int result; | ||
58 | int timeout_count; | ||
59 | struct timer_list timeout_timer; | ||
60 | struct i2c_adapter adap; | ||
61 | struct completion complete; | ||
62 | }; | ||
63 | |||
64 | static struct bfin_twi_iface twi_iface; | ||
65 | |||
66 | static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) | ||
67 | { | ||
68 | unsigned short twi_int_status = bfin_read_TWI_INT_STAT(); | ||
69 | unsigned short mast_stat = bfin_read_TWI_MASTER_STAT(); | ||
70 | |||
71 | if (twi_int_status & XMTSERV) { | ||
72 | /* Transmit next data */ | ||
73 | if (iface->writeNum > 0) { | ||
74 | bfin_write_TWI_XMT_DATA8(*(iface->transPtr++)); | ||
75 | iface->writeNum--; | ||
76 | } | ||
77 | /* start receive immediately after complete sending in | ||
78 | * combine mode. | ||
79 | */ | ||
80 | else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { | ||
81 | bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | ||
82 | | MDIR | RSTART); | ||
83 | } else if (iface->manual_stop) | ||
84 | bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | ||
85 | | STOP); | ||
86 | SSYNC(); | ||
87 | /* Clear status */ | ||
88 | bfin_write_TWI_INT_STAT(XMTSERV); | ||
89 | SSYNC(); | ||
90 | } | ||
91 | if (twi_int_status & RCVSERV) { | ||
92 | if (iface->readNum > 0) { | ||
93 | /* Receive next data */ | ||
94 | *(iface->transPtr) = bfin_read_TWI_RCV_DATA8(); | ||
95 | if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { | ||
96 | /* Change combine mode into sub mode after | ||
97 | * read first data. | ||
98 | */ | ||
99 | iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; | ||
100 | /* Get read number from first byte in block | ||
101 | * combine mode. | ||
102 | */ | ||
103 | if (iface->readNum == 1 && iface->manual_stop) | ||
104 | iface->readNum = *iface->transPtr + 1; | ||
105 | } | ||
106 | iface->transPtr++; | ||
107 | iface->readNum--; | ||
108 | } else if (iface->manual_stop) { | ||
109 | bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | ||
110 | | STOP); | ||
111 | SSYNC(); | ||
112 | } | ||
113 | /* Clear interrupt source */ | ||
114 | bfin_write_TWI_INT_STAT(RCVSERV); | ||
115 | SSYNC(); | ||
116 | } | ||
117 | if (twi_int_status & MERR) { | ||
118 | bfin_write_TWI_INT_STAT(MERR); | ||
119 | bfin_write_TWI_INT_MASK(0); | ||
120 | bfin_write_TWI_MASTER_STAT(0x3e); | ||
121 | bfin_write_TWI_MASTER_CTL(0); | ||
122 | SSYNC(); | ||
123 | iface->result = -1; | ||
124 | /* if both err and complete int stats are set, return proper | ||
125 | * results. | ||
126 | */ | ||
127 | if (twi_int_status & MCOMP) { | ||
128 | bfin_write_TWI_INT_STAT(MCOMP); | ||
129 | bfin_write_TWI_INT_MASK(0); | ||
130 | bfin_write_TWI_MASTER_CTL(0); | ||
131 | SSYNC(); | ||
132 | /* If it is a quick transfer, only address bug no data, | ||
133 | * not an err, return 1. | ||
134 | */ | ||
135 | if (iface->writeNum == 0 && (mast_stat & BUFRDERR)) | ||
136 | iface->result = 1; | ||
137 | /* If address not acknowledged return -1, | ||
138 | * else return 0. | ||
139 | */ | ||
140 | else if (!(mast_stat & ANAK)) | ||
141 | iface->result = 0; | ||
142 | } | ||
143 | complete(&iface->complete); | ||
144 | return; | ||
145 | } | ||
146 | if (twi_int_status & MCOMP) { | ||
147 | bfin_write_TWI_INT_STAT(MCOMP); | ||
148 | SSYNC(); | ||
149 | if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { | ||
150 | if (iface->readNum == 0) { | ||
151 | /* set the read number to 1 and ask for manual | ||
152 | * stop in block combine mode | ||
153 | */ | ||
154 | iface->readNum = 1; | ||
155 | iface->manual_stop = 1; | ||
156 | bfin_write_TWI_MASTER_CTL( | ||
157 | bfin_read_TWI_MASTER_CTL() | ||
158 | | (0xff << 6)); | ||
159 | } else { | ||
160 | /* set the readd number in other | ||
161 | * combine mode. | ||
162 | */ | ||
163 | bfin_write_TWI_MASTER_CTL( | ||
164 | (bfin_read_TWI_MASTER_CTL() & | ||
165 | (~(0xff << 6))) | | ||
166 | ( iface->readNum << 6)); | ||
167 | } | ||
168 | /* remove restart bit and enable master receive */ | ||
169 | bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() & | ||
170 | ~RSTART); | ||
171 | bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | | ||
172 | MEN | MDIR); | ||
173 | SSYNC(); | ||
174 | } else { | ||
175 | iface->result = 1; | ||
176 | bfin_write_TWI_INT_MASK(0); | ||
177 | bfin_write_TWI_MASTER_CTL(0); | ||
178 | SSYNC(); | ||
179 | complete(&iface->complete); | ||
180 | } | ||
181 | } | ||
182 | } | ||
183 | |||
184 | /* Interrupt handler */ | ||
185 | static irqreturn_t bfin_twi_interrupt_entry(int irq, void *dev_id) | ||
186 | { | ||
187 | struct bfin_twi_iface *iface = dev_id; | ||
188 | unsigned long flags; | ||
189 | |||
190 | spin_lock_irqsave(&iface->lock, flags); | ||
191 | del_timer(&iface->timeout_timer); | ||
192 | bfin_twi_handle_interrupt(iface); | ||
193 | spin_unlock_irqrestore(&iface->lock, flags); | ||
194 | return IRQ_HANDLED; | ||
195 | } | ||
196 | |||
197 | static void bfin_twi_timeout(unsigned long data) | ||
198 | { | ||
199 | struct bfin_twi_iface *iface = (struct bfin_twi_iface *)data; | ||
200 | unsigned long flags; | ||
201 | |||
202 | spin_lock_irqsave(&iface->lock, flags); | ||
203 | bfin_twi_handle_interrupt(iface); | ||
204 | if (iface->result == 0) { | ||
205 | iface->timeout_count--; | ||
206 | if (iface->timeout_count > 0) { | ||
207 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
208 | add_timer(&iface->timeout_timer); | ||
209 | } else { | ||
210 | iface->result = -1; | ||
211 | complete(&iface->complete); | ||
212 | } | ||
213 | } | ||
214 | spin_unlock_irqrestore(&iface->lock, flags); | ||
215 | } | ||
216 | |||
217 | /* | ||
218 | * Generic i2c master transfer entrypoint | ||
219 | */ | ||
220 | static int bfin_twi_master_xfer(struct i2c_adapter *adap, | ||
221 | struct i2c_msg *msgs, int num) | ||
222 | { | ||
223 | struct bfin_twi_iface *iface = adap->algo_data; | ||
224 | struct i2c_msg *pmsg; | ||
225 | int i, ret; | ||
226 | int rc = 0; | ||
227 | |||
228 | if (!(bfin_read_TWI_CONTROL() & TWI_ENA)) | ||
229 | return -ENXIO; | ||
230 | |||
231 | mutex_lock(&iface->twi_lock); | ||
232 | |||
233 | while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) { | ||
234 | mutex_unlock(&iface->twi_lock); | ||
235 | yield(); | ||
236 | mutex_lock(&iface->twi_lock); | ||
237 | } | ||
238 | |||
239 | ret = 0; | ||
240 | for (i = 0; rc >= 0 && i < num; i++) { | ||
241 | pmsg = &msgs[i]; | ||
242 | if (pmsg->flags & I2C_M_TEN) { | ||
243 | dev_err(&(adap->dev), "i2c-bfin-twi: 10 bits addr " | ||
244 | "not supported !\n"); | ||
245 | rc = -EINVAL; | ||
246 | break; | ||
247 | } | ||
248 | |||
249 | iface->cur_mode = TWI_I2C_MODE_STANDARD; | ||
250 | iface->manual_stop = 0; | ||
251 | iface->transPtr = pmsg->buf; | ||
252 | iface->writeNum = iface->readNum = pmsg->len; | ||
253 | iface->result = 0; | ||
254 | iface->timeout_count = 10; | ||
255 | /* Set Transmit device address */ | ||
256 | bfin_write_TWI_MASTER_ADDR(pmsg->addr); | ||
257 | |||
258 | /* FIFO Initiation. Data in FIFO should be | ||
259 | * discarded before start a new operation. | ||
260 | */ | ||
261 | bfin_write_TWI_FIFO_CTL(0x3); | ||
262 | SSYNC(); | ||
263 | bfin_write_TWI_FIFO_CTL(0); | ||
264 | SSYNC(); | ||
265 | |||
266 | if (pmsg->flags & I2C_M_RD) | ||
267 | iface->read_write = I2C_SMBUS_READ; | ||
268 | else { | ||
269 | iface->read_write = I2C_SMBUS_WRITE; | ||
270 | /* Transmit first data */ | ||
271 | if (iface->writeNum > 0) { | ||
272 | bfin_write_TWI_XMT_DATA8(*(iface->transPtr++)); | ||
273 | iface->writeNum--; | ||
274 | SSYNC(); | ||
275 | } | ||
276 | } | ||
277 | |||
278 | /* clear int stat */ | ||
279 | bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV); | ||
280 | |||
281 | /* Interrupt mask . Enable XMT, RCV interrupt */ | ||
282 | bfin_write_TWI_INT_MASK(MCOMP | MERR | | ||
283 | ((iface->read_write == I2C_SMBUS_READ)? | ||
284 | RCVSERV : XMTSERV)); | ||
285 | SSYNC(); | ||
286 | |||
287 | if (pmsg->len > 0 && pmsg->len <= 255) | ||
288 | bfin_write_TWI_MASTER_CTL(pmsg->len << 6); | ||
289 | else if (pmsg->len > 255) { | ||
290 | bfin_write_TWI_MASTER_CTL(0xff << 6); | ||
291 | iface->manual_stop = 1; | ||
292 | } else | ||
293 | break; | ||
294 | |||
295 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
296 | add_timer(&iface->timeout_timer); | ||
297 | |||
298 | /* Master enable */ | ||
299 | bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN | | ||
300 | ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | | ||
301 | ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0)); | ||
302 | SSYNC(); | ||
303 | |||
304 | wait_for_completion(&iface->complete); | ||
305 | |||
306 | rc = iface->result; | ||
307 | if (rc == 1) | ||
308 | ret++; | ||
309 | else if (rc == -1) | ||
310 | break; | ||
311 | } | ||
312 | |||
313 | /* Release mutex */ | ||
314 | mutex_unlock(&iface->twi_lock); | ||
315 | |||
316 | return ret; | ||
317 | } | ||
318 | |||
319 | /* | ||
320 | * SMBus type transfer entrypoint | ||
321 | */ | ||
322 | |||
323 | int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, | ||
324 | unsigned short flags, char read_write, | ||
325 | u8 command, int size, union i2c_smbus_data *data) | ||
326 | { | ||
327 | struct bfin_twi_iface *iface = adap->algo_data; | ||
328 | int rc = 0; | ||
329 | |||
330 | if (!(bfin_read_TWI_CONTROL() & TWI_ENA)) | ||
331 | return -ENXIO; | ||
332 | |||
333 | mutex_lock(&iface->twi_lock); | ||
334 | |||
335 | while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) { | ||
336 | mutex_unlock(&iface->twi_lock); | ||
337 | yield(); | ||
338 | mutex_lock(&iface->twi_lock); | ||
339 | } | ||
340 | |||
341 | iface->writeNum = 0; | ||
342 | iface->readNum = 0; | ||
343 | |||
344 | /* Prepare datas & select mode */ | ||
345 | switch (size) { | ||
346 | case I2C_SMBUS_QUICK: | ||
347 | iface->transPtr = NULL; | ||
348 | iface->cur_mode = TWI_I2C_MODE_STANDARD; | ||
349 | break; | ||
350 | case I2C_SMBUS_BYTE: | ||
351 | if (data == NULL) | ||
352 | iface->transPtr = NULL; | ||
353 | else { | ||
354 | if (read_write == I2C_SMBUS_READ) | ||
355 | iface->readNum = 1; | ||
356 | else | ||
357 | iface->writeNum = 1; | ||
358 | iface->transPtr = &data->byte; | ||
359 | } | ||
360 | iface->cur_mode = TWI_I2C_MODE_STANDARD; | ||
361 | break; | ||
362 | case I2C_SMBUS_BYTE_DATA: | ||
363 | if (read_write == I2C_SMBUS_READ) { | ||
364 | iface->readNum = 1; | ||
365 | iface->cur_mode = TWI_I2C_MODE_COMBINED; | ||
366 | } else { | ||
367 | iface->writeNum = 1; | ||
368 | iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; | ||
369 | } | ||
370 | iface->transPtr = &data->byte; | ||
371 | break; | ||
372 | case I2C_SMBUS_WORD_DATA: | ||
373 | if (read_write == I2C_SMBUS_READ) { | ||
374 | iface->readNum = 2; | ||
375 | iface->cur_mode = TWI_I2C_MODE_COMBINED; | ||
376 | } else { | ||
377 | iface->writeNum = 2; | ||
378 | iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; | ||
379 | } | ||
380 | iface->transPtr = (u8 *)&data->word; | ||
381 | break; | ||
382 | case I2C_SMBUS_PROC_CALL: | ||
383 | iface->writeNum = 2; | ||
384 | iface->readNum = 2; | ||
385 | iface->cur_mode = TWI_I2C_MODE_COMBINED; | ||
386 | iface->transPtr = (u8 *)&data->word; | ||
387 | break; | ||
388 | case I2C_SMBUS_BLOCK_DATA: | ||
389 | if (read_write == I2C_SMBUS_READ) { | ||
390 | iface->readNum = 0; | ||
391 | iface->cur_mode = TWI_I2C_MODE_COMBINED; | ||
392 | } else { | ||
393 | iface->writeNum = data->block[0] + 1; | ||
394 | iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; | ||
395 | } | ||
396 | iface->transPtr = data->block; | ||
397 | break; | ||
398 | default: | ||
399 | return -1; | ||
400 | } | ||
401 | |||
402 | iface->result = 0; | ||
403 | iface->manual_stop = 0; | ||
404 | iface->read_write = read_write; | ||
405 | iface->command = command; | ||
406 | iface->timeout_count = 10; | ||
407 | |||
408 | /* FIFO Initiation. Data in FIFO should be discarded before | ||
409 | * start a new operation. | ||
410 | */ | ||
411 | bfin_write_TWI_FIFO_CTL(0x3); | ||
412 | SSYNC(); | ||
413 | bfin_write_TWI_FIFO_CTL(0); | ||
414 | |||
415 | /* clear int stat */ | ||
416 | bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV); | ||
417 | |||
418 | /* Set Transmit device address */ | ||
419 | bfin_write_TWI_MASTER_ADDR(addr); | ||
420 | SSYNC(); | ||
421 | |||
422 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
423 | add_timer(&iface->timeout_timer); | ||
424 | |||
425 | switch (iface->cur_mode) { | ||
426 | case TWI_I2C_MODE_STANDARDSUB: | ||
427 | bfin_write_TWI_XMT_DATA8(iface->command); | ||
428 | bfin_write_TWI_INT_MASK(MCOMP | MERR | | ||
429 | ((iface->read_write == I2C_SMBUS_READ) ? | ||
430 | RCVSERV : XMTSERV)); | ||
431 | SSYNC(); | ||
432 | |||
433 | if (iface->writeNum + 1 <= 255) | ||
434 | bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6); | ||
435 | else { | ||
436 | bfin_write_TWI_MASTER_CTL(0xff << 6); | ||
437 | iface->manual_stop = 1; | ||
438 | } | ||
439 | /* Master enable */ | ||
440 | bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN | | ||
441 | ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0)); | ||
442 | break; | ||
443 | case TWI_I2C_MODE_COMBINED: | ||
444 | bfin_write_TWI_XMT_DATA8(iface->command); | ||
445 | bfin_write_TWI_INT_MASK(MCOMP | MERR | RCVSERV | XMTSERV); | ||
446 | SSYNC(); | ||
447 | |||
448 | if (iface->writeNum > 0) | ||
449 | bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6); | ||
450 | else | ||
451 | bfin_write_TWI_MASTER_CTL(0x1 << 6); | ||
452 | /* Master enable */ | ||
453 | bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN | | ||
454 | ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0)); | ||
455 | break; | ||
456 | default: | ||
457 | bfin_write_TWI_MASTER_CTL(0); | ||
458 | if (size != I2C_SMBUS_QUICK) { | ||
459 | /* Don't access xmit data register when this is a | ||
460 | * read operation. | ||
461 | */ | ||
462 | if (iface->read_write != I2C_SMBUS_READ) { | ||
463 | if (iface->writeNum > 0) { | ||
464 | bfin_write_TWI_XMT_DATA8(*(iface->transPtr++)); | ||
465 | if (iface->writeNum <= 255) | ||
466 | bfin_write_TWI_MASTER_CTL(iface->writeNum << 6); | ||
467 | else { | ||
468 | bfin_write_TWI_MASTER_CTL(0xff << 6); | ||
469 | iface->manual_stop = 1; | ||
470 | } | ||
471 | iface->writeNum--; | ||
472 | } else { | ||
473 | bfin_write_TWI_XMT_DATA8(iface->command); | ||
474 | bfin_write_TWI_MASTER_CTL(1 << 6); | ||
475 | } | ||
476 | } else { | ||
477 | if (iface->readNum > 0 && iface->readNum <= 255) | ||
478 | bfin_write_TWI_MASTER_CTL(iface->readNum << 6); | ||
479 | else if (iface->readNum > 255) { | ||
480 | bfin_write_TWI_MASTER_CTL(0xff << 6); | ||
481 | iface->manual_stop = 1; | ||
482 | } else { | ||
483 | del_timer(&iface->timeout_timer); | ||
484 | break; | ||
485 | } | ||
486 | } | ||
487 | } | ||
488 | bfin_write_TWI_INT_MASK(MCOMP | MERR | | ||
489 | ((iface->read_write == I2C_SMBUS_READ) ? | ||
490 | RCVSERV : XMTSERV)); | ||
491 | SSYNC(); | ||
492 | |||
493 | /* Master enable */ | ||
494 | bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN | | ||
495 | ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | | ||
496 | ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0)); | ||
497 | break; | ||
498 | } | ||
499 | SSYNC(); | ||
500 | |||
501 | wait_for_completion(&iface->complete); | ||
502 | |||
503 | rc = (iface->result >= 0) ? 0 : -1; | ||
504 | |||
505 | /* Release mutex */ | ||
506 | mutex_unlock(&iface->twi_lock); | ||
507 | |||
508 | return rc; | ||
509 | } | ||
510 | |||
511 | /* | ||
512 | * Return what the adapter supports | ||
513 | */ | ||
514 | static u32 bfin_twi_functionality(struct i2c_adapter *adap) | ||
515 | { | ||
516 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | | ||
517 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | | ||
518 | I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL | | ||
519 | I2C_FUNC_I2C; | ||
520 | } | ||
521 | |||
522 | |||
523 | static struct i2c_algorithm bfin_twi_algorithm = { | ||
524 | .master_xfer = bfin_twi_master_xfer, | ||
525 | .smbus_xfer = bfin_twi_smbus_xfer, | ||
526 | .functionality = bfin_twi_functionality, | ||
527 | }; | ||
528 | |||
529 | |||
530 | static int i2c_bfin_twi_suspend(struct platform_device *dev, pm_message_t state) | ||
531 | { | ||
532 | /* struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/ | ||
533 | |||
534 | /* Disable TWI */ | ||
535 | bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() & ~TWI_ENA); | ||
536 | SSYNC(); | ||
537 | |||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | static int i2c_bfin_twi_resume(struct platform_device *dev) | ||
542 | { | ||
543 | /* struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/ | ||
544 | |||
545 | /* Enable TWI */ | ||
546 | bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA); | ||
547 | SSYNC(); | ||
548 | |||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | static int i2c_bfin_twi_probe(struct platform_device *dev) | ||
553 | { | ||
554 | struct bfin_twi_iface *iface = &twi_iface; | ||
555 | struct i2c_adapter *p_adap; | ||
556 | int rc; | ||
557 | |||
558 | mutex_init(&(iface->twi_lock)); | ||
559 | spin_lock_init(&(iface->lock)); | ||
560 | init_completion(&(iface->complete)); | ||
561 | iface->irq = IRQ_TWI; | ||
562 | |||
563 | init_timer(&(iface->timeout_timer)); | ||
564 | iface->timeout_timer.function = bfin_twi_timeout; | ||
565 | iface->timeout_timer.data = (unsigned long)iface; | ||
566 | |||
567 | p_adap = &iface->adap; | ||
568 | p_adap->id = I2C_HW_BLACKFIN; | ||
569 | strlcpy(p_adap->name, dev->name, sizeof(p_adap->name)); | ||
570 | p_adap->algo = &bfin_twi_algorithm; | ||
571 | p_adap->algo_data = iface; | ||
572 | p_adap->class = I2C_CLASS_ALL; | ||
573 | p_adap->dev.parent = &dev->dev; | ||
574 | |||
575 | rc = request_irq(iface->irq, bfin_twi_interrupt_entry, | ||
576 | IRQF_DISABLED, dev->name, iface); | ||
577 | if (rc) { | ||
578 | dev_err(&(p_adap->dev), "i2c-bfin-twi: can't get IRQ %d !\n", | ||
579 | iface->irq); | ||
580 | return -ENODEV; | ||
581 | } | ||
582 | |||
583 | /* Set TWI internal clock as 10MHz */ | ||
584 | bfin_write_TWI_CONTROL(((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F); | ||
585 | |||
586 | /* Set Twi interface clock as specified */ | ||
587 | bfin_write_TWI_CLKDIV((( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ ) | ||
588 | << 8) | (( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ ) | ||
589 | & 0xFF)); | ||
590 | |||
591 | /* Enable TWI */ | ||
592 | bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA); | ||
593 | SSYNC(); | ||
594 | |||
595 | rc = i2c_add_adapter(p_adap); | ||
596 | if (rc < 0) | ||
597 | free_irq(iface->irq, iface); | ||
598 | else | ||
599 | platform_set_drvdata(dev, iface); | ||
600 | |||
601 | return rc; | ||
602 | } | ||
603 | |||
604 | static int i2c_bfin_twi_remove(struct platform_device *pdev) | ||
605 | { | ||
606 | struct bfin_twi_iface *iface = platform_get_drvdata(pdev); | ||
607 | |||
608 | platform_set_drvdata(pdev, NULL); | ||
609 | |||
610 | i2c_del_adapter(&(iface->adap)); | ||
611 | free_irq(iface->irq, iface); | ||
612 | |||
613 | return 0; | ||
614 | } | ||
615 | |||
616 | static struct platform_driver i2c_bfin_twi_driver = { | ||
617 | .probe = i2c_bfin_twi_probe, | ||
618 | .remove = i2c_bfin_twi_remove, | ||
619 | .suspend = i2c_bfin_twi_suspend, | ||
620 | .resume = i2c_bfin_twi_resume, | ||
621 | .driver = { | ||
622 | .name = "i2c-bfin-twi", | ||
623 | .owner = THIS_MODULE, | ||
624 | }, | ||
625 | }; | ||
626 | |||
627 | static int __init i2c_bfin_twi_init(void) | ||
628 | { | ||
629 | pr_info("I2C: Blackfin I2C TWI driver\n"); | ||
630 | |||
631 | return platform_driver_register(&i2c_bfin_twi_driver); | ||
632 | } | ||
633 | |||
634 | static void __exit i2c_bfin_twi_exit(void) | ||
635 | { | ||
636 | platform_driver_unregister(&i2c_bfin_twi_driver); | ||
637 | } | ||
638 | |||
639 | MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); | ||
640 | MODULE_DESCRIPTION("I2C-Bus adapter routines for Blackfin TWI"); | ||
641 | MODULE_LICENSE("GPL"); | ||
642 | |||
643 | module_init(i2c_bfin_twi_init); | ||
644 | module_exit(i2c_bfin_twi_exit); | ||
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c index 834967464814..804f0a551c05 100644 --- a/drivers/i2c/busses/i2c-elektor.c +++ b/drivers/i2c/busses/i2c-elektor.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
36 | #include <linux/wait.h> | 36 | #include <linux/wait.h> |
37 | 37 | ||
38 | #include <linux/isa.h> | ||
38 | #include <linux/i2c.h> | 39 | #include <linux/i2c.h> |
39 | #include <linux/i2c-algo-pcf.h> | 40 | #include <linux/i2c-algo-pcf.h> |
40 | 41 | ||
@@ -207,7 +208,7 @@ static struct i2c_adapter pcf_isa_ops = { | |||
207 | .name = "i2c-elektor", | 208 | .name = "i2c-elektor", |
208 | }; | 209 | }; |
209 | 210 | ||
210 | static int __init i2c_pcfisa_init(void) | 211 | static int __devinit elektor_match(struct device *dev, unsigned int id) |
211 | { | 212 | { |
212 | #ifdef __alpha__ | 213 | #ifdef __alpha__ |
213 | /* check to see we have memory mapped PCF8584 connected to the | 214 | /* check to see we have memory mapped PCF8584 connected to the |
@@ -222,9 +223,8 @@ static int __init i2c_pcfisa_init(void) | |||
222 | /* yeap, we've found cypress, let's check config */ | 223 | /* yeap, we've found cypress, let's check config */ |
223 | if (!pci_read_config_byte(cy693_dev, 0x47, &config)) { | 224 | if (!pci_read_config_byte(cy693_dev, 0x47, &config)) { |
224 | 225 | ||
225 | pr_debug("%s: found cy82c693, config " | 226 | dev_dbg(dev, "found cy82c693, config " |
226 | "register 0x47 = 0x%02x\n", | 227 | "register 0x47 = 0x%02x\n", config); |
227 | pcf_isa_ops.name, config); | ||
228 | 228 | ||
229 | /* UP2000 board has this register set to 0xe1, | 229 | /* UP2000 board has this register set to 0xe1, |
230 | but the most significant bit as seems can be | 230 | but the most significant bit as seems can be |
@@ -244,9 +244,9 @@ static int __init i2c_pcfisa_init(void) | |||
244 | 8.25 MHz (PCI/4) clock | 244 | 8.25 MHz (PCI/4) clock |
245 | (this can be read from cypress) */ | 245 | (this can be read from cypress) */ |
246 | clock = I2C_PCF_CLK | I2C_PCF_TRNS90; | 246 | clock = I2C_PCF_CLK | I2C_PCF_TRNS90; |
247 | pr_info("%s: found API UP2000 like " | 247 | dev_info(dev, "found API UP2000 like " |
248 | "board, will probe PCF8584 " | 248 | "board, will probe PCF8584 " |
249 | "later\n", pcf_isa_ops.name); | 249 | "later\n"); |
250 | } | 250 | } |
251 | } | 251 | } |
252 | pci_dev_put(cy693_dev); | 252 | pci_dev_put(cy693_dev); |
@@ -256,22 +256,27 @@ static int __init i2c_pcfisa_init(void) | |||
256 | 256 | ||
257 | /* sanity checks for mmapped I/O */ | 257 | /* sanity checks for mmapped I/O */ |
258 | if (mmapped && base < 0xc8000) { | 258 | if (mmapped && base < 0xc8000) { |
259 | printk(KERN_ERR "%s: incorrect base address (%#x) specified " | 259 | dev_err(dev, "incorrect base address (%#x) specified " |
260 | "for mmapped I/O\n", pcf_isa_ops.name, base); | 260 | "for mmapped I/O\n", base); |
261 | return -ENODEV; | 261 | return 0; |
262 | } | 262 | } |
263 | 263 | ||
264 | if (base == 0) { | 264 | if (base == 0) { |
265 | base = DEFAULT_BASE; | 265 | base = DEFAULT_BASE; |
266 | } | 266 | } |
267 | return 1; | ||
268 | } | ||
267 | 269 | ||
270 | static int __devinit elektor_probe(struct device *dev, unsigned int id) | ||
271 | { | ||
268 | init_waitqueue_head(&pcf_wait); | 272 | init_waitqueue_head(&pcf_wait); |
269 | if (pcf_isa_init()) | 273 | if (pcf_isa_init()) |
270 | return -ENODEV; | 274 | return -ENODEV; |
275 | pcf_isa_ops.dev.parent = dev; | ||
271 | if (i2c_pcf_add_bus(&pcf_isa_ops) < 0) | 276 | if (i2c_pcf_add_bus(&pcf_isa_ops) < 0) |
272 | goto fail; | 277 | goto fail; |
273 | 278 | ||
274 | dev_info(&pcf_isa_ops.dev, "found device at %#x\n", base); | 279 | dev_info(dev, "found device at %#x\n", base); |
275 | 280 | ||
276 | return 0; | 281 | return 0; |
277 | 282 | ||
@@ -291,7 +296,7 @@ static int __init i2c_pcfisa_init(void) | |||
291 | return -ENODEV; | 296 | return -ENODEV; |
292 | } | 297 | } |
293 | 298 | ||
294 | static void i2c_pcfisa_exit(void) | 299 | static int __devexit elektor_remove(struct device *dev, unsigned int id) |
295 | { | 300 | { |
296 | i2c_del_adapter(&pcf_isa_ops); | 301 | i2c_del_adapter(&pcf_isa_ops); |
297 | 302 | ||
@@ -307,6 +312,28 @@ static void i2c_pcfisa_exit(void) | |||
307 | iounmap(base_iomem); | 312 | iounmap(base_iomem); |
308 | release_mem_region(base, 2); | 313 | release_mem_region(base, 2); |
309 | } | 314 | } |
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static struct isa_driver i2c_elektor_driver = { | ||
320 | .match = elektor_match, | ||
321 | .probe = elektor_probe, | ||
322 | .remove = __devexit_p(elektor_remove), | ||
323 | .driver = { | ||
324 | .owner = THIS_MODULE, | ||
325 | .name = "i2c-elektor", | ||
326 | }, | ||
327 | }; | ||
328 | |||
329 | static int __init i2c_pcfisa_init(void) | ||
330 | { | ||
331 | return isa_register_driver(&i2c_elektor_driver, 1); | ||
332 | } | ||
333 | |||
334 | static void __exit i2c_pcfisa_exit(void) | ||
335 | { | ||
336 | isa_unregister_driver(&i2c_elektor_driver); | ||
310 | } | 337 | } |
311 | 338 | ||
312 | MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>"); | 339 | MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>"); |
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c new file mode 100644 index 000000000000..a7dd54654a9a --- /dev/null +++ b/drivers/i2c/busses/i2c-gpio.c | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | * Bitbanging I2C bus driver using the GPIO API | ||
3 | * | ||
4 | * Copyright (C) 2007 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #include <linux/i2c.h> | ||
11 | #include <linux/i2c-algo-bit.h> | ||
12 | #include <linux/i2c-gpio.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | |||
17 | #include <asm/gpio.h> | ||
18 | |||
19 | /* Toggle SDA by changing the direction of the pin */ | ||
20 | static void i2c_gpio_setsda_dir(void *data, int state) | ||
21 | { | ||
22 | struct i2c_gpio_platform_data *pdata = data; | ||
23 | |||
24 | if (state) | ||
25 | gpio_direction_input(pdata->sda_pin); | ||
26 | else | ||
27 | gpio_direction_output(pdata->sda_pin, 0); | ||
28 | } | ||
29 | |||
30 | /* | ||
31 | * Toggle SDA by changing the output value of the pin. This is only | ||
32 | * valid for pins configured as open drain (i.e. setting the value | ||
33 | * high effectively turns off the output driver.) | ||
34 | */ | ||
35 | static void i2c_gpio_setsda_val(void *data, int state) | ||
36 | { | ||
37 | struct i2c_gpio_platform_data *pdata = data; | ||
38 | |||
39 | gpio_set_value(pdata->sda_pin, state); | ||
40 | } | ||
41 | |||
42 | /* Toggle SCL by changing the direction of the pin. */ | ||
43 | static void i2c_gpio_setscl_dir(void *data, int state) | ||
44 | { | ||
45 | struct i2c_gpio_platform_data *pdata = data; | ||
46 | |||
47 | if (state) | ||
48 | gpio_direction_input(pdata->scl_pin); | ||
49 | else | ||
50 | gpio_direction_output(pdata->scl_pin, 0); | ||
51 | } | ||
52 | |||
53 | /* | ||
54 | * Toggle SCL by changing the output value of the pin. This is used | ||
55 | * for pins that are configured as open drain and for output-only | ||
56 | * pins. The latter case will break the i2c protocol, but it will | ||
57 | * often work in practice. | ||
58 | */ | ||
59 | static void i2c_gpio_setscl_val(void *data, int state) | ||
60 | { | ||
61 | struct i2c_gpio_platform_data *pdata = data; | ||
62 | |||
63 | gpio_set_value(pdata->scl_pin, state); | ||
64 | } | ||
65 | |||
66 | int i2c_gpio_getsda(void *data) | ||
67 | { | ||
68 | struct i2c_gpio_platform_data *pdata = data; | ||
69 | |||
70 | return gpio_get_value(pdata->sda_pin); | ||
71 | } | ||
72 | |||
73 | int i2c_gpio_getscl(void *data) | ||
74 | { | ||
75 | struct i2c_gpio_platform_data *pdata = data; | ||
76 | |||
77 | return gpio_get_value(pdata->scl_pin); | ||
78 | } | ||
79 | |||
80 | static int __init i2c_gpio_probe(struct platform_device *pdev) | ||
81 | { | ||
82 | struct i2c_gpio_platform_data *pdata; | ||
83 | struct i2c_algo_bit_data *bit_data; | ||
84 | struct i2c_adapter *adap; | ||
85 | int ret; | ||
86 | |||
87 | pdata = pdev->dev.platform_data; | ||
88 | if (!pdata) | ||
89 | return -ENXIO; | ||
90 | |||
91 | ret = -ENOMEM; | ||
92 | adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); | ||
93 | if (!adap) | ||
94 | goto err_alloc_adap; | ||
95 | bit_data = kzalloc(sizeof(struct i2c_algo_bit_data), GFP_KERNEL); | ||
96 | if (!bit_data) | ||
97 | goto err_alloc_bit_data; | ||
98 | |||
99 | ret = gpio_request(pdata->sda_pin, "sda"); | ||
100 | if (ret) | ||
101 | goto err_request_sda; | ||
102 | ret = gpio_request(pdata->scl_pin, "scl"); | ||
103 | if (ret) | ||
104 | goto err_request_scl; | ||
105 | |||
106 | if (pdata->sda_is_open_drain) { | ||
107 | gpio_direction_output(pdata->sda_pin, 1); | ||
108 | bit_data->setsda = i2c_gpio_setsda_val; | ||
109 | } else { | ||
110 | gpio_direction_input(pdata->sda_pin); | ||
111 | bit_data->setsda = i2c_gpio_setsda_dir; | ||
112 | } | ||
113 | |||
114 | if (pdata->scl_is_open_drain || pdata->scl_is_output_only) { | ||
115 | gpio_direction_output(pdata->scl_pin, 1); | ||
116 | bit_data->setscl = i2c_gpio_setscl_val; | ||
117 | } else { | ||
118 | gpio_direction_input(pdata->scl_pin); | ||
119 | bit_data->setscl = i2c_gpio_setscl_dir; | ||
120 | } | ||
121 | |||
122 | if (!pdata->scl_is_output_only) | ||
123 | bit_data->getscl = i2c_gpio_getscl; | ||
124 | bit_data->getsda = i2c_gpio_getsda; | ||
125 | |||
126 | if (pdata->udelay) | ||
127 | bit_data->udelay = pdata->udelay; | ||
128 | else if (pdata->scl_is_output_only) | ||
129 | bit_data->udelay = 50; /* 10 kHz */ | ||
130 | else | ||
131 | bit_data->udelay = 5; /* 100 kHz */ | ||
132 | |||
133 | if (pdata->timeout) | ||
134 | bit_data->timeout = pdata->timeout; | ||
135 | else | ||
136 | bit_data->timeout = HZ / 10; /* 100 ms */ | ||
137 | |||
138 | bit_data->data = pdata; | ||
139 | |||
140 | adap->owner = THIS_MODULE; | ||
141 | snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id); | ||
142 | adap->algo_data = bit_data; | ||
143 | adap->dev.parent = &pdev->dev; | ||
144 | |||
145 | ret = i2c_bit_add_bus(adap); | ||
146 | if (ret) | ||
147 | goto err_add_bus; | ||
148 | |||
149 | platform_set_drvdata(pdev, adap); | ||
150 | |||
151 | dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n", | ||
152 | pdata->sda_pin, pdata->scl_pin, | ||
153 | pdata->scl_is_output_only | ||
154 | ? ", no clock stretching" : ""); | ||
155 | |||
156 | return 0; | ||
157 | |||
158 | err_add_bus: | ||
159 | gpio_free(pdata->scl_pin); | ||
160 | err_request_scl: | ||
161 | gpio_free(pdata->sda_pin); | ||
162 | err_request_sda: | ||
163 | kfree(bit_data); | ||
164 | err_alloc_bit_data: | ||
165 | kfree(adap); | ||
166 | err_alloc_adap: | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | static int __exit i2c_gpio_remove(struct platform_device *pdev) | ||
171 | { | ||
172 | struct i2c_gpio_platform_data *pdata; | ||
173 | struct i2c_adapter *adap; | ||
174 | |||
175 | adap = platform_get_drvdata(pdev); | ||
176 | pdata = pdev->dev.platform_data; | ||
177 | |||
178 | i2c_del_adapter(adap); | ||
179 | gpio_free(pdata->scl_pin); | ||
180 | gpio_free(pdata->sda_pin); | ||
181 | kfree(adap->algo_data); | ||
182 | kfree(adap); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static struct platform_driver i2c_gpio_driver = { | ||
188 | .driver = { | ||
189 | .name = "i2c-gpio", | ||
190 | .owner = THIS_MODULE, | ||
191 | }, | ||
192 | .remove = __exit_p(i2c_gpio_remove), | ||
193 | }; | ||
194 | |||
195 | static int __init i2c_gpio_init(void) | ||
196 | { | ||
197 | int ret; | ||
198 | |||
199 | ret = platform_driver_probe(&i2c_gpio_driver, i2c_gpio_probe); | ||
200 | if (ret) | ||
201 | printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret); | ||
202 | |||
203 | return ret; | ||
204 | } | ||
205 | module_init(i2c_gpio_init); | ||
206 | |||
207 | static void __exit i2c_gpio_exit(void) | ||
208 | { | ||
209 | platform_driver_unregister(&i2c_gpio_driver); | ||
210 | } | ||
211 | module_exit(i2c_gpio_exit); | ||
212 | |||
213 | MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); | ||
214 | MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver"); | ||
215 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index a320e7d82c1f..611b57192c96 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
@@ -527,7 +527,7 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id | |||
527 | /* set up the sysfs linkage to our parent device */ | 527 | /* set up the sysfs linkage to our parent device */ |
528 | i801_adapter.dev.parent = &dev->dev; | 528 | i801_adapter.dev.parent = &dev->dev; |
529 | 529 | ||
530 | snprintf(i801_adapter.name, I2C_NAME_SIZE, | 530 | snprintf(i801_adapter.name, sizeof(i801_adapter.name), |
531 | "SMBus I801 adapter at %04lx", i801_smba); | 531 | "SMBus I801 adapter at %04lx", i801_smba); |
532 | err = i2c_add_adapter(&i801_adapter); | 532 | err = i2c_add_adapter(&i801_adapter); |
533 | if (err) { | 533 | if (err) { |
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c index 5f33bc9c1e02..b0e1370075de 100644 --- a/drivers/i2c/busses/i2c-isa.c +++ b/drivers/i2c/busses/i2c-isa.c | |||
@@ -41,6 +41,10 @@ | |||
41 | #include <linux/platform_device.h> | 41 | #include <linux/platform_device.h> |
42 | #include <linux/completion.h> | 42 | #include <linux/completion.h> |
43 | 43 | ||
44 | /* Exported by i2c-core for i2c-isa only */ | ||
45 | extern void i2c_adapter_dev_release(struct device *dev); | ||
46 | extern struct class i2c_adapter_class; | ||
47 | |||
44 | static u32 isa_func(struct i2c_adapter *adapter); | 48 | static u32 isa_func(struct i2c_adapter *adapter); |
45 | 49 | ||
46 | /* This is the actual algorithm we define */ | 50 | /* This is the actual algorithm we define */ |
@@ -64,16 +68,6 @@ static u32 isa_func(struct i2c_adapter *adapter) | |||
64 | } | 68 | } |
65 | 69 | ||
66 | 70 | ||
67 | /* Copied from i2c-core */ | ||
68 | static ssize_t show_adapter_name(struct device *dev, | ||
69 | struct device_attribute *attr, char *buf) | ||
70 | { | ||
71 | struct i2c_adapter *adap = dev_to_i2c_adapter(dev); | ||
72 | return sprintf(buf, "%s\n", adap->name); | ||
73 | } | ||
74 | static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL); | ||
75 | |||
76 | |||
77 | /* We implement an interface which resembles i2c_{add,del}_driver, | 71 | /* We implement an interface which resembles i2c_{add,del}_driver, |
78 | but for i2c-isa drivers. We don't have to remember and handle lists | 72 | but for i2c-isa drivers. We don't have to remember and handle lists |
79 | of drivers and adapters so this is much more simple, of course. */ | 73 | of drivers and adapters so this is much more simple, of course. */ |
@@ -139,41 +133,18 @@ static int __init i2c_isa_init(void) | |||
139 | isa_adapter.nr = ANY_I2C_ISA_BUS; | 133 | isa_adapter.nr = ANY_I2C_ISA_BUS; |
140 | isa_adapter.dev.parent = &platform_bus; | 134 | isa_adapter.dev.parent = &platform_bus; |
141 | sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr); | 135 | sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr); |
142 | isa_adapter.dev.driver = &i2c_adapter_driver; | ||
143 | isa_adapter.dev.release = &i2c_adapter_dev_release; | 136 | isa_adapter.dev.release = &i2c_adapter_dev_release; |
137 | isa_adapter.dev.class = &i2c_adapter_class; | ||
144 | err = device_register(&isa_adapter.dev); | 138 | err = device_register(&isa_adapter.dev); |
145 | if (err) { | 139 | if (err) { |
146 | printk(KERN_ERR "i2c-isa: Failed to register device\n"); | 140 | printk(KERN_ERR "i2c-isa: Failed to register device\n"); |
147 | goto exit; | 141 | goto exit; |
148 | } | 142 | } |
149 | err = device_create_file(&isa_adapter.dev, &dev_attr_name); | ||
150 | if (err) { | ||
151 | printk(KERN_ERR "i2c-isa: Failed to create name file\n"); | ||
152 | goto exit_unregister; | ||
153 | } | ||
154 | |||
155 | /* Add this adapter to the i2c_adapter class */ | ||
156 | memset(&isa_adapter.class_dev, 0x00, sizeof(struct class_device)); | ||
157 | isa_adapter.class_dev.dev = &isa_adapter.dev; | ||
158 | isa_adapter.class_dev.class = &i2c_adapter_class; | ||
159 | strlcpy(isa_adapter.class_dev.class_id, isa_adapter.dev.bus_id, | ||
160 | BUS_ID_SIZE); | ||
161 | err = class_device_register(&isa_adapter.class_dev); | ||
162 | if (err) { | ||
163 | printk(KERN_ERR "i2c-isa: Failed to register class device\n"); | ||
164 | goto exit_remove_name; | ||
165 | } | ||
166 | 143 | ||
167 | dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name); | 144 | dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name); |
168 | 145 | ||
169 | return 0; | 146 | return 0; |
170 | 147 | ||
171 | exit_remove_name: | ||
172 | device_remove_file(&isa_adapter.dev, &dev_attr_name); | ||
173 | exit_unregister: | ||
174 | init_completion(&isa_adapter.dev_released); /* Needed? */ | ||
175 | device_unregister(&isa_adapter.dev); | ||
176 | wait_for_completion(&isa_adapter.dev_released); | ||
177 | exit: | 148 | exit: |
178 | return err; | 149 | return err; |
179 | } | 150 | } |
@@ -201,15 +172,11 @@ static void __exit i2c_isa_exit(void) | |||
201 | /* Clean up the sysfs representation */ | 172 | /* Clean up the sysfs representation */ |
202 | dev_dbg(&isa_adapter.dev, "Unregistering from sysfs\n"); | 173 | dev_dbg(&isa_adapter.dev, "Unregistering from sysfs\n"); |
203 | init_completion(&isa_adapter.dev_released); | 174 | init_completion(&isa_adapter.dev_released); |
204 | init_completion(&isa_adapter.class_dev_released); | ||
205 | class_device_unregister(&isa_adapter.class_dev); | ||
206 | device_remove_file(&isa_adapter.dev, &dev_attr_name); | ||
207 | device_unregister(&isa_adapter.dev); | 175 | device_unregister(&isa_adapter.dev); |
208 | 176 | ||
209 | /* Wait for sysfs to drop all references */ | 177 | /* Wait for sysfs to drop all references */ |
210 | dev_dbg(&isa_adapter.dev, "Waiting for sysfs completion\n"); | 178 | dev_dbg(&isa_adapter.dev, "Waiting for sysfs completion\n"); |
211 | wait_for_completion(&isa_adapter.dev_released); | 179 | wait_for_completion(&isa_adapter.dev_released); |
212 | wait_for_completion(&isa_adapter.class_dev_released); | ||
213 | 180 | ||
214 | dev_dbg(&isa_adapter.dev, "%s unregistered\n", isa_adapter.name); | 181 | dev_dbg(&isa_adapter.dev, "%s unregistered\n", isa_adapter.name); |
215 | } | 182 | } |
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c index efa3ecc5522a..6352121a2827 100644 --- a/drivers/i2c/busses/i2c-ixp2000.c +++ b/drivers/i2c/busses/i2c-ixp2000.c | |||
@@ -118,7 +118,7 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev) | |||
118 | 118 | ||
119 | drv_data->adapter.id = I2C_HW_B_IXP2000, | 119 | drv_data->adapter.id = I2C_HW_B_IXP2000, |
120 | strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, | 120 | strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, |
121 | I2C_NAME_SIZE); | 121 | sizeof(drv_data->adapter.name)); |
122 | drv_data->adapter.algo_data = &drv_data->algo_data, | 122 | drv_data->adapter.algo_data = &drv_data->algo_data, |
123 | 123 | ||
124 | drv_data->adapter.dev.parent = &plat_dev->dev; | 124 | drv_data->adapter.dev.parent = &plat_dev->dev; |
diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c index 08e89b83984a..069ed7f3b395 100644 --- a/drivers/i2c/busses/i2c-ixp4xx.c +++ b/drivers/i2c/busses/i2c-ixp4xx.c | |||
@@ -127,7 +127,7 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev) | |||
127 | drv_data->adapter.id = I2C_HW_B_IXP4XX; | 127 | drv_data->adapter.id = I2C_HW_B_IXP4XX; |
128 | drv_data->adapter.class = I2C_CLASS_HWMON; | 128 | drv_data->adapter.class = I2C_CLASS_HWMON; |
129 | strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, | 129 | strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, |
130 | I2C_NAME_SIZE); | 130 | sizeof(drv_data->adapter.name)); |
131 | drv_data->adapter.algo_data = &drv_data->algo_data; | 131 | drv_data->adapter.algo_data = &drv_data->algo_data; |
132 | 132 | ||
133 | drv_data->adapter.dev.parent = &plat_dev->dev; | 133 | drv_data->adapter.dev.parent = &plat_dev->dev; |
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index ee65aa1be13a..c6b6898592b1 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/pci.h> | ||
21 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
22 | 21 | ||
23 | #include <asm/io.h> | 22 | #include <asm/io.h> |
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index a3283b907eb8..a55b3335d1be 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c | |||
@@ -508,7 +508,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) | |||
508 | } | 508 | } |
509 | 509 | ||
510 | strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter", | 510 | strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter", |
511 | I2C_NAME_SIZE); | 511 | sizeof(drv_data->adapter.name)); |
512 | 512 | ||
513 | init_waitqueue_head(&drv_data->waitq); | 513 | init_waitqueue_head(&drv_data->waitq); |
514 | spin_lock_init(&drv_data->lock); | 514 | spin_lock_init(&drv_data->lock); |
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index 1514ec5b77f8..3cd0d63e7b50 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c | |||
@@ -33,6 +33,8 @@ | |||
33 | nForce4 MCP-04 0034 | 33 | nForce4 MCP-04 0034 |
34 | nForce4 MCP51 0264 | 34 | nForce4 MCP51 0264 |
35 | nForce4 MCP55 0368 | 35 | nForce4 MCP55 0368 |
36 | nForce MCP61 03EB | ||
37 | nForce MCP65 0446 | ||
36 | 38 | ||
37 | This driver supports the 2 SMBuses that are included in the MCP of the | 39 | This driver supports the 2 SMBuses that are included in the MCP of the |
38 | nForce2/3/4/5xx chipsets. | 40 | nForce2/3/4/5xx chipsets. |
@@ -200,6 +202,8 @@ static struct pci_device_id nforce2_ids[] = { | |||
200 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) }, | 202 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) }, |
201 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS) }, | 203 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS) }, |
202 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) }, | 204 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) }, |
205 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS) }, | ||
206 | { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS) }, | ||
203 | { 0 } | 207 | { 0 } |
204 | }; | 208 | }; |
205 | 209 | ||
@@ -240,7 +244,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar, | |||
240 | smbus->adapter.algo = &smbus_algorithm; | 244 | smbus->adapter.algo = &smbus_algorithm; |
241 | smbus->adapter.algo_data = smbus; | 245 | smbus->adapter.algo_data = smbus; |
242 | smbus->adapter.dev.parent = &dev->dev; | 246 | smbus->adapter.dev.parent = &dev->dev; |
243 | snprintf(smbus->adapter.name, I2C_NAME_SIZE, | 247 | snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), |
244 | "SMBus nForce2 adapter at %04x", smbus->base); | 248 | "SMBus nForce2 adapter at %04x", smbus->base); |
245 | 249 | ||
246 | error = i2c_add_adapter(&smbus->adapter); | 250 | error = i2c_add_adapter(&smbus->adapter); |
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index bcd8367cede1..e471e3bfdc1e 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
@@ -605,7 +605,8 @@ omap_i2c_probe(struct platform_device *pdev) | |||
605 | adap->dev.parent = &pdev->dev; | 605 | adap->dev.parent = &pdev->dev; |
606 | 606 | ||
607 | /* i2c device drivers may be active on return from add_adapter() */ | 607 | /* i2c device drivers may be active on return from add_adapter() */ |
608 | r = i2c_add_adapter(adap); | 608 | adap->nr = pdev->id; |
609 | r = i2c_add_numbered_adapter(adap); | ||
609 | if (r) { | 610 | if (r) { |
610 | dev_err(dev->dev, "failure adding adapter\n"); | 611 | dev_err(dev->dev, "failure adding adapter\n"); |
611 | goto err_free_irq; | 612 | goto err_free_irq; |
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c index 4bc42810b9aa..49a95e2887bc 100644 --- a/drivers/i2c/busses/i2c-parport-light.c +++ b/drivers/i2c/busses/i2c-parport-light.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* ------------------------------------------------------------------------ * | 1 | /* ------------------------------------------------------------------------ * |
2 | * i2c-parport.c I2C bus over parallel port * | 2 | * i2c-parport-light.c I2C bus over parallel port * |
3 | * ------------------------------------------------------------------------ * | 3 | * ------------------------------------------------------------------------ * |
4 | Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org> | 4 | Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org> |
5 | 5 | ||
6 | Based on older i2c-velleman.c driver | 6 | Based on older i2c-velleman.c driver |
7 | Copyright (C) 1995-2000 Simon G. Vogl | 7 | Copyright (C) 1995-2000 Simon G. Vogl |
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/platform_device.h> | ||
30 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
31 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
32 | #include <linux/i2c-algo-bit.h> | 33 | #include <linux/i2c-algo-bit.h> |
@@ -34,6 +35,9 @@ | |||
34 | #include "i2c-parport.h" | 35 | #include "i2c-parport.h" |
35 | 36 | ||
36 | #define DEFAULT_BASE 0x378 | 37 | #define DEFAULT_BASE 0x378 |
38 | #define DRVNAME "i2c-parport-light" | ||
39 | |||
40 | static struct platform_device *pdev; | ||
37 | 41 | ||
38 | static u16 base; | 42 | static u16 base; |
39 | module_param(base, ushort, 0); | 43 | module_param(base, ushort, 0); |
@@ -106,7 +110,7 @@ static struct i2c_algo_bit_data parport_algo_data = { | |||
106 | .timeout = HZ, | 110 | .timeout = HZ, |
107 | }; | 111 | }; |
108 | 112 | ||
109 | /* ----- I2c structure ---------------------------------------------------- */ | 113 | /* ----- Driver registration ---------------------------------------------- */ |
110 | 114 | ||
111 | static struct i2c_adapter parport_adapter = { | 115 | static struct i2c_adapter parport_adapter = { |
112 | .owner = THIS_MODULE, | 116 | .owner = THIS_MODULE, |
@@ -116,55 +120,141 @@ static struct i2c_adapter parport_adapter = { | |||
116 | .name = "Parallel port adapter (light)", | 120 | .name = "Parallel port adapter (light)", |
117 | }; | 121 | }; |
118 | 122 | ||
119 | /* ----- Module loading, unloading and information ------------------------ */ | 123 | static int __devinit i2c_parport_probe(struct platform_device *pdev) |
124 | { | ||
125 | int err; | ||
126 | struct resource *res; | ||
127 | |||
128 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
129 | if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) | ||
130 | return -EBUSY; | ||
131 | |||
132 | /* Reset hardware to a sane state (SCL and SDA high) */ | ||
133 | parport_setsda(NULL, 1); | ||
134 | parport_setscl(NULL, 1); | ||
135 | /* Other init if needed (power on...) */ | ||
136 | if (adapter_parm[type].init.val) | ||
137 | line_set(1, &adapter_parm[type].init); | ||
138 | |||
139 | parport_adapter.dev.parent = &pdev->dev; | ||
140 | err = i2c_bit_add_bus(&parport_adapter); | ||
141 | if (err) { | ||
142 | dev_err(&pdev->dev, "Unable to register with I2C\n"); | ||
143 | goto exit_region; | ||
144 | } | ||
145 | return 0; | ||
146 | |||
147 | exit_region: | ||
148 | release_region(res->start, res->end - res->start + 1); | ||
149 | return err; | ||
150 | } | ||
151 | |||
152 | static int __devexit i2c_parport_remove(struct platform_device *pdev) | ||
153 | { | ||
154 | struct resource *res; | ||
155 | |||
156 | i2c_del_adapter(&parport_adapter); | ||
157 | |||
158 | /* Un-init if needed (power off...) */ | ||
159 | if (adapter_parm[type].init.val) | ||
160 | line_set(0, &adapter_parm[type].init); | ||
161 | |||
162 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
163 | release_region(res->start, res->end - res->start + 1); | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static struct platform_driver i2c_parport_driver = { | ||
168 | .driver = { | ||
169 | .owner = THIS_MODULE, | ||
170 | .name = DRVNAME, | ||
171 | }, | ||
172 | .probe = i2c_parport_probe, | ||
173 | .remove = __devexit_p(i2c_parport_remove), | ||
174 | }; | ||
175 | |||
176 | static int __init i2c_parport_device_add(u16 address) | ||
177 | { | ||
178 | struct resource res = { | ||
179 | .start = address, | ||
180 | .end = address + 2, | ||
181 | .name = DRVNAME, | ||
182 | .flags = IORESOURCE_IO, | ||
183 | }; | ||
184 | int err; | ||
185 | |||
186 | pdev = platform_device_alloc(DRVNAME, -1); | ||
187 | if (!pdev) { | ||
188 | err = -ENOMEM; | ||
189 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); | ||
190 | goto exit; | ||
191 | } | ||
192 | |||
193 | err = platform_device_add_resources(pdev, &res, 1); | ||
194 | if (err) { | ||
195 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | ||
196 | "(%d)\n", err); | ||
197 | goto exit_device_put; | ||
198 | } | ||
199 | |||
200 | err = platform_device_add(pdev); | ||
201 | if (err) { | ||
202 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | ||
203 | err); | ||
204 | goto exit_device_put; | ||
205 | } | ||
206 | |||
207 | return 0; | ||
208 | |||
209 | exit_device_put: | ||
210 | platform_device_put(pdev); | ||
211 | exit: | ||
212 | return err; | ||
213 | } | ||
120 | 214 | ||
121 | static int __init i2c_parport_init(void) | 215 | static int __init i2c_parport_init(void) |
122 | { | 216 | { |
217 | int err; | ||
218 | |||
123 | if (type < 0) { | 219 | if (type < 0) { |
124 | printk(KERN_WARNING "i2c-parport: adapter type unspecified\n"); | 220 | printk(KERN_ERR DRVNAME ": adapter type unspecified\n"); |
125 | return -ENODEV; | 221 | return -ENODEV; |
126 | } | 222 | } |
127 | 223 | ||
128 | if (type >= ARRAY_SIZE(adapter_parm)) { | 224 | if (type >= ARRAY_SIZE(adapter_parm)) { |
129 | printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type); | 225 | printk(KERN_ERR DRVNAME ": invalid type (%d)\n", type); |
130 | return -ENODEV; | 226 | return -ENODEV; |
131 | } | 227 | } |
132 | 228 | ||
133 | if (base == 0) { | 229 | if (base == 0) { |
134 | printk(KERN_INFO "i2c-parport: using default base 0x%x\n", DEFAULT_BASE); | 230 | pr_info(DRVNAME ": using default base 0x%x\n", DEFAULT_BASE); |
135 | base = DEFAULT_BASE; | 231 | base = DEFAULT_BASE; |
136 | } | 232 | } |
137 | 233 | ||
138 | if (!request_region(base, 3, "i2c-parport")) | ||
139 | return -ENODEV; | ||
140 | |||
141 | if (!adapter_parm[type].getscl.val) | 234 | if (!adapter_parm[type].getscl.val) |
142 | parport_algo_data.getscl = NULL; | 235 | parport_algo_data.getscl = NULL; |
143 | 236 | ||
144 | /* Reset hardware to a sane state (SCL and SDA high) */ | 237 | /* Sets global pdev as a side effect */ |
145 | parport_setsda(NULL, 1); | 238 | err = i2c_parport_device_add(base); |
146 | parport_setscl(NULL, 1); | 239 | if (err) |
147 | /* Other init if needed (power on...) */ | 240 | goto exit; |
148 | if (adapter_parm[type].init.val) | ||
149 | line_set(1, &adapter_parm[type].init); | ||
150 | 241 | ||
151 | if (i2c_bit_add_bus(&parport_adapter) < 0) { | 242 | err = platform_driver_register(&i2c_parport_driver); |
152 | printk(KERN_ERR "i2c-parport: Unable to register with I2C\n"); | 243 | if (err) |
153 | release_region(base, 3); | 244 | goto exit_device; |
154 | return -ENODEV; | ||
155 | } | ||
156 | 245 | ||
157 | return 0; | 246 | return 0; |
247 | |||
248 | exit_device: | ||
249 | platform_device_unregister(pdev); | ||
250 | exit: | ||
251 | return err; | ||
158 | } | 252 | } |
159 | 253 | ||
160 | static void __exit i2c_parport_exit(void) | 254 | static void __exit i2c_parport_exit(void) |
161 | { | 255 | { |
162 | /* Un-init if needed (power off...) */ | 256 | platform_driver_unregister(&i2c_parport_driver); |
163 | if (adapter_parm[type].init.val) | 257 | platform_device_unregister(pdev); |
164 | line_set(0, &adapter_parm[type].init); | ||
165 | |||
166 | i2c_del_adapter(&parport_adapter); | ||
167 | release_region(base, 3); | ||
168 | } | 258 | } |
169 | 259 | ||
170 | MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); | 260 | MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); |
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c index 66696a40c7b5..8c953707253f 100644 --- a/drivers/i2c/busses/i2c-parport.c +++ b/drivers/i2c/busses/i2c-parport.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* ------------------------------------------------------------------------ * | 1 | /* ------------------------------------------------------------------------ * |
2 | * i2c-parport.c I2C bus over parallel port * | 2 | * i2c-parport.c I2C bus over parallel port * |
3 | * ------------------------------------------------------------------------ * | 3 | * ------------------------------------------------------------------------ * |
4 | Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org> | 4 | Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org> |
5 | 5 | ||
6 | Based on older i2c-philips-par.c driver | 6 | Based on older i2c-philips-par.c driver |
7 | Copyright (C) 1995-2000 Simon G. Vogl | 7 | Copyright (C) 1995-2000 Simon G. Vogl |
@@ -137,19 +137,12 @@ static struct i2c_algo_bit_data parport_algo_data = { | |||
137 | .setscl = parport_setscl, | 137 | .setscl = parport_setscl, |
138 | .getsda = parport_getsda, | 138 | .getsda = parport_getsda, |
139 | .getscl = parport_getscl, | 139 | .getscl = parport_getscl, |
140 | .udelay = 60, | 140 | .udelay = 10, /* ~50 kbps */ |
141 | .timeout = HZ, | 141 | .timeout = HZ, |
142 | }; | 142 | }; |
143 | 143 | ||
144 | /* ----- I2c and parallel port call-back functions and structures --------- */ | 144 | /* ----- I2c and parallel port call-back functions and structures --------- */ |
145 | 145 | ||
146 | static struct i2c_adapter parport_adapter = { | ||
147 | .owner = THIS_MODULE, | ||
148 | .class = I2C_CLASS_HWMON, | ||
149 | .id = I2C_HW_B_LP, | ||
150 | .name = "Parallel port adapter", | ||
151 | }; | ||
152 | |||
153 | static void i2c_parport_attach (struct parport *port) | 146 | static void i2c_parport_attach (struct parport *port) |
154 | { | 147 | { |
155 | struct i2c_par *adapter; | 148 | struct i2c_par *adapter; |
@@ -169,10 +162,17 @@ static void i2c_parport_attach (struct parport *port) | |||
169 | } | 162 | } |
170 | 163 | ||
171 | /* Fill the rest of the structure */ | 164 | /* Fill the rest of the structure */ |
172 | adapter->adapter = parport_adapter; | 165 | adapter->adapter.owner = THIS_MODULE; |
166 | adapter->adapter.class = I2C_CLASS_HWMON; | ||
167 | adapter->adapter.id = I2C_HW_B_LP; | ||
168 | strlcpy(adapter->adapter.name, "Parallel port adapter", | ||
169 | sizeof(adapter->adapter.name)); | ||
173 | adapter->algo_data = parport_algo_data; | 170 | adapter->algo_data = parport_algo_data; |
174 | if (!adapter_parm[type].getscl.val) | 171 | /* Slow down if we can't sense SCL */ |
172 | if (!adapter_parm[type].getscl.val) { | ||
175 | adapter->algo_data.getscl = NULL; | 173 | adapter->algo_data.getscl = NULL; |
174 | adapter->algo_data.udelay = 50; /* ~10 kbps */ | ||
175 | } | ||
176 | adapter->algo_data.data = port; | 176 | adapter->algo_data.data = port; |
177 | adapter->adapter.algo_data = &adapter->algo_data; | 177 | adapter->adapter.algo_data = &adapter->algo_data; |
178 | 178 | ||
@@ -214,11 +214,12 @@ static void i2c_parport_detach (struct parport *port) | |||
214 | for (prev = NULL, adapter = adapter_list; adapter; | 214 | for (prev = NULL, adapter = adapter_list; adapter; |
215 | prev = adapter, adapter = adapter->next) { | 215 | prev = adapter, adapter = adapter->next) { |
216 | if (adapter->pdev->port == port) { | 216 | if (adapter->pdev->port == port) { |
217 | i2c_del_adapter(&adapter->adapter); | ||
218 | |||
217 | /* Un-init if needed (power off...) */ | 219 | /* Un-init if needed (power off...) */ |
218 | if (adapter_parm[type].init.val) | 220 | if (adapter_parm[type].init.val) |
219 | line_set(port, 0, &adapter_parm[type].init); | 221 | line_set(port, 0, &adapter_parm[type].init); |
220 | 222 | ||
221 | i2c_del_adapter(&adapter->adapter); | ||
222 | parport_unregister_device(adapter->pdev); | 223 | parport_unregister_device(adapter->pdev); |
223 | if (prev) | 224 | if (prev) |
224 | prev->next = adapter->next; | 225 | prev->next = adapter->next; |
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index bf89eeef74e9..58e32714afb5 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c | |||
@@ -358,7 +358,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev, | |||
358 | } | 358 | } |
359 | 359 | ||
360 | smbus->adapter.owner = THIS_MODULE; | 360 | smbus->adapter.owner = THIS_MODULE; |
361 | snprintf(smbus->adapter.name, I2C_NAME_SIZE, | 361 | snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), |
362 | "PA Semi SMBus adapter at 0x%lx", smbus->base); | 362 | "PA Semi SMBus adapter at 0x%lx", smbus->base); |
363 | smbus->adapter.class = I2C_CLASS_HWMON; | 363 | smbus->adapter.class = I2C_CLASS_HWMON; |
364 | smbus->adapter.algo = &smbus_algorithm; | 364 | smbus->adapter.algo = &smbus_algorithm; |
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index cc6536a19eca..5161aaf9341b 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c | |||
@@ -25,9 +25,9 @@ | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
28 | #include <linux/pci.h> | ||
29 | #include <linux/wait.h> | 28 | #include <linux/wait.h> |
30 | 29 | ||
30 | #include <linux/isa.h> | ||
31 | #include <linux/i2c.h> | 31 | #include <linux/i2c.h> |
32 | #include <linux/i2c-algo-pca.h> | 32 | #include <linux/i2c-algo-pca.h> |
33 | 33 | ||
@@ -119,27 +119,26 @@ static struct i2c_adapter pca_isa_ops = { | |||
119 | .name = "PCA9564 ISA Adapter", | 119 | .name = "PCA9564 ISA Adapter", |
120 | }; | 120 | }; |
121 | 121 | ||
122 | static int __init pca_isa_init(void) | 122 | static int __devinit pca_isa_probe(struct device *dev, unsigned int id) |
123 | { | 123 | { |
124 | |||
125 | init_waitqueue_head(&pca_wait); | 124 | init_waitqueue_head(&pca_wait); |
126 | 125 | ||
127 | printk(KERN_INFO "i2c-pca-isa: i/o base %#08lx. irq %d\n", base, irq); | 126 | dev_info(dev, "i/o base %#08lx. irq %d\n", base, irq); |
128 | 127 | ||
129 | if (!request_region(base, IO_SIZE, "i2c-pca-isa")) { | 128 | if (!request_region(base, IO_SIZE, "i2c-pca-isa")) { |
130 | printk(KERN_ERR "i2c-pca-isa: I/O address %#08lx is in use.\n", base); | 129 | dev_err(dev, "I/O address %#08lx is in use\n", base); |
131 | goto out; | 130 | goto out; |
132 | } | 131 | } |
133 | 132 | ||
134 | if (irq > -1) { | 133 | if (irq > -1) { |
135 | if (request_irq(irq, pca_handler, 0, "i2c-pca-isa", &pca_isa_ops) < 0) { | 134 | if (request_irq(irq, pca_handler, 0, "i2c-pca-isa", &pca_isa_ops) < 0) { |
136 | printk(KERN_ERR "i2c-pca-isa: Request irq%d failed\n", irq); | 135 | dev_err(dev, "Request irq%d failed\n", irq); |
137 | goto out_region; | 136 | goto out_region; |
138 | } | 137 | } |
139 | } | 138 | } |
140 | 139 | ||
141 | if (i2c_pca_add_bus(&pca_isa_ops) < 0) { | 140 | if (i2c_pca_add_bus(&pca_isa_ops) < 0) { |
142 | printk(KERN_ERR "i2c-pca-isa: Failed to add i2c bus\n"); | 141 | dev_err(dev, "Failed to add i2c bus\n"); |
143 | goto out_irq; | 142 | goto out_irq; |
144 | } | 143 | } |
145 | 144 | ||
@@ -154,7 +153,7 @@ static int __init pca_isa_init(void) | |||
154 | return -ENODEV; | 153 | return -ENODEV; |
155 | } | 154 | } |
156 | 155 | ||
157 | static void pca_isa_exit(void) | 156 | static int __devexit pca_isa_remove(struct device *dev, unsigned int id) |
158 | { | 157 | { |
159 | i2c_del_adapter(&pca_isa_ops); | 158 | i2c_del_adapter(&pca_isa_ops); |
160 | 159 | ||
@@ -163,6 +162,27 @@ static void pca_isa_exit(void) | |||
163 | free_irq(irq, &pca_isa_ops); | 162 | free_irq(irq, &pca_isa_ops); |
164 | } | 163 | } |
165 | release_region(base, IO_SIZE); | 164 | release_region(base, IO_SIZE); |
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static struct isa_driver pca_isa_driver = { | ||
170 | .probe = pca_isa_probe, | ||
171 | .remove = __devexit_p(pca_isa_remove), | ||
172 | .driver = { | ||
173 | .owner = THIS_MODULE, | ||
174 | .name = "i2c-pca-isa", | ||
175 | } | ||
176 | }; | ||
177 | |||
178 | static int __init pca_isa_init(void) | ||
179 | { | ||
180 | return isa_register_driver(&pca_isa_driver, 1); | ||
181 | } | ||
182 | |||
183 | static void __exit pca_isa_exit(void) | ||
184 | { | ||
185 | isa_unregister_driver(&pca_isa_driver); | ||
166 | } | 186 | } |
167 | 187 | ||
168 | MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>"); | 188 | MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>"); |
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 21b180904085..5a52bf5e3fb0 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c | |||
@@ -428,7 +428,7 @@ static int __devinit piix4_probe(struct pci_dev *dev, | |||
428 | /* set up the sysfs linkage to our parent device */ | 428 | /* set up the sysfs linkage to our parent device */ |
429 | piix4_adapter.dev.parent = &dev->dev; | 429 | piix4_adapter.dev.parent = &dev->dev; |
430 | 430 | ||
431 | snprintf(piix4_adapter.name, I2C_NAME_SIZE, | 431 | snprintf(piix4_adapter.name, sizeof(piix4_adapter.name), |
432 | "SMBus PIIX4 adapter at %04x", piix4_smba); | 432 | "SMBus PIIX4 adapter at %04x", piix4_smba); |
433 | 433 | ||
434 | if ((retval = i2c_add_adapter(&piix4_adapter))) { | 434 | if ((retval = i2c_add_adapter(&piix4_adapter))) { |
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 14e83d0aac8c..c059b27fa881 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
@@ -539,6 +539,18 @@ static inline void i2c_pxa_start_message(struct pxa_i2c *i2c) | |||
539 | writel(icr | ICR_START | ICR_TB, _ICR(i2c)); | 539 | writel(icr | ICR_START | ICR_TB, _ICR(i2c)); |
540 | } | 540 | } |
541 | 541 | ||
542 | static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c) | ||
543 | { | ||
544 | u32 icr; | ||
545 | |||
546 | /* | ||
547 | * Clear the STOP and ACK flags | ||
548 | */ | ||
549 | icr = readl(_ICR(i2c)); | ||
550 | icr &= ~(ICR_STOP | ICR_ACKNAK); | ||
551 | writel(icr, _IRC(i2c)); | ||
552 | } | ||
553 | |||
542 | /* | 554 | /* |
543 | * We are protected by the adapter bus mutex. | 555 | * We are protected by the adapter bus mutex. |
544 | */ | 556 | */ |
@@ -581,6 +593,7 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) | |||
581 | * The rest of the processing occurs in the interrupt handler. | 593 | * The rest of the processing occurs in the interrupt handler. |
582 | */ | 594 | */ |
583 | timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); | 595 | timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); |
596 | i2c_pxa_stop_message(i2c); | ||
584 | 597 | ||
585 | /* | 598 | /* |
586 | * We place the return code in i2c->msg_idx. | 599 | * We place the return code in i2c->msg_idx. |
@@ -825,7 +838,7 @@ static const struct i2c_algorithm i2c_pxa_algorithm = { | |||
825 | }; | 838 | }; |
826 | 839 | ||
827 | static struct pxa_i2c i2c_pxa = { | 840 | static struct pxa_i2c i2c_pxa = { |
828 | .lock = SPIN_LOCK_UNLOCKED, | 841 | .lock = __SPIN_LOCK_UNLOCKED(i2c_pxa.lock), |
829 | .adap = { | 842 | .adap = { |
830 | .owner = THIS_MODULE, | 843 | .owner = THIS_MODULE, |
831 | .algo = &i2c_pxa_algorithm, | 844 | .algo = &i2c_pxa_algorithm, |
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 556f244aae76..e68a96f589fd 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c | |||
@@ -61,6 +61,8 @@ struct s3c24xx_i2c { | |||
61 | unsigned int msg_idx; | 61 | unsigned int msg_idx; |
62 | unsigned int msg_ptr; | 62 | unsigned int msg_ptr; |
63 | 63 | ||
64 | unsigned int tx_setup; | ||
65 | |||
64 | enum s3c24xx_i2c_state state; | 66 | enum s3c24xx_i2c_state state; |
65 | 67 | ||
66 | void __iomem *regs; | 68 | void __iomem *regs; |
@@ -199,8 +201,11 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, | |||
199 | dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr); | 201 | dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr); |
200 | writeb(addr, i2c->regs + S3C2410_IICDS); | 202 | writeb(addr, i2c->regs + S3C2410_IICDS); |
201 | 203 | ||
202 | // delay a bit and reset iiccon before setting start (per samsung) | 204 | /* delay here to ensure the data byte has gotten onto the bus |
203 | udelay(1); | 205 | * before the transaction is started */ |
206 | |||
207 | ndelay(i2c->tx_setup); | ||
208 | |||
204 | dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon); | 209 | dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon); |
205 | writel(iiccon, i2c->regs + S3C2410_IICCON); | 210 | writel(iiccon, i2c->regs + S3C2410_IICCON); |
206 | 211 | ||
@@ -322,7 +327,15 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) | |||
322 | if (!is_msgend(i2c)) { | 327 | if (!is_msgend(i2c)) { |
323 | byte = i2c->msg->buf[i2c->msg_ptr++]; | 328 | byte = i2c->msg->buf[i2c->msg_ptr++]; |
324 | writeb(byte, i2c->regs + S3C2410_IICDS); | 329 | writeb(byte, i2c->regs + S3C2410_IICDS); |
325 | 330 | ||
331 | /* delay after writing the byte to allow the | ||
332 | * data setup time on the bus, as writing the | ||
333 | * data to the register causes the first bit | ||
334 | * to appear on SDA, and SCL will change as | ||
335 | * soon as the interrupt is acknowledged */ | ||
336 | |||
337 | ndelay(i2c->tx_setup); | ||
338 | |||
326 | } else if (!is_lastmsg(i2c)) { | 339 | } else if (!is_lastmsg(i2c)) { |
327 | /* we need to go to the next i2c message */ | 340 | /* we need to go to the next i2c message */ |
328 | 341 | ||
@@ -570,9 +583,10 @@ static const struct i2c_algorithm s3c24xx_i2c_algorithm = { | |||
570 | }; | 583 | }; |
571 | 584 | ||
572 | static struct s3c24xx_i2c s3c24xx_i2c = { | 585 | static struct s3c24xx_i2c s3c24xx_i2c = { |
573 | .lock = SPIN_LOCK_UNLOCKED, | 586 | .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_i2c.lock), |
574 | .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait), | 587 | .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait), |
575 | .adap = { | 588 | .tx_setup = 50, |
589 | .adap = { | ||
576 | .name = "s3c2410-i2c", | 590 | .name = "s3c2410-i2c", |
577 | .owner = THIS_MODULE, | 591 | .owner = THIS_MODULE, |
578 | .algo = &s3c24xx_i2c_algorithm, | 592 | .algo = &s3c24xx_i2c_algorithm, |
@@ -731,26 +745,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) | |||
731 | return 0; | 745 | return 0; |
732 | } | 746 | } |
733 | 747 | ||
734 | static void s3c24xx_i2c_free(struct s3c24xx_i2c *i2c) | ||
735 | { | ||
736 | if (i2c->clk != NULL && !IS_ERR(i2c->clk)) { | ||
737 | clk_disable(i2c->clk); | ||
738 | clk_put(i2c->clk); | ||
739 | i2c->clk = NULL; | ||
740 | } | ||
741 | |||
742 | if (i2c->regs != NULL) { | ||
743 | iounmap(i2c->regs); | ||
744 | i2c->regs = NULL; | ||
745 | } | ||
746 | |||
747 | if (i2c->ioarea != NULL) { | ||
748 | release_resource(i2c->ioarea); | ||
749 | kfree(i2c->ioarea); | ||
750 | i2c->ioarea = NULL; | ||
751 | } | ||
752 | } | ||
753 | |||
754 | /* s3c24xx_i2c_probe | 748 | /* s3c24xx_i2c_probe |
755 | * | 749 | * |
756 | * called by the bus driver when a suitable device is found | 750 | * called by the bus driver when a suitable device is found |
@@ -769,7 +763,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
769 | if (IS_ERR(i2c->clk)) { | 763 | if (IS_ERR(i2c->clk)) { |
770 | dev_err(&pdev->dev, "cannot get clock\n"); | 764 | dev_err(&pdev->dev, "cannot get clock\n"); |
771 | ret = -ENOENT; | 765 | ret = -ENOENT; |
772 | goto out; | 766 | goto err_noclk; |
773 | } | 767 | } |
774 | 768 | ||
775 | dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk); | 769 | dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk); |
@@ -782,7 +776,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
782 | if (res == NULL) { | 776 | if (res == NULL) { |
783 | dev_err(&pdev->dev, "cannot find IO resource\n"); | 777 | dev_err(&pdev->dev, "cannot find IO resource\n"); |
784 | ret = -ENOENT; | 778 | ret = -ENOENT; |
785 | goto out; | 779 | goto err_clk; |
786 | } | 780 | } |
787 | 781 | ||
788 | i2c->ioarea = request_mem_region(res->start, (res->end-res->start)+1, | 782 | i2c->ioarea = request_mem_region(res->start, (res->end-res->start)+1, |
@@ -791,7 +785,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
791 | if (i2c->ioarea == NULL) { | 785 | if (i2c->ioarea == NULL) { |
792 | dev_err(&pdev->dev, "cannot request IO\n"); | 786 | dev_err(&pdev->dev, "cannot request IO\n"); |
793 | ret = -ENXIO; | 787 | ret = -ENXIO; |
794 | goto out; | 788 | goto err_clk; |
795 | } | 789 | } |
796 | 790 | ||
797 | i2c->regs = ioremap(res->start, (res->end-res->start)+1); | 791 | i2c->regs = ioremap(res->start, (res->end-res->start)+1); |
@@ -799,7 +793,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
799 | if (i2c->regs == NULL) { | 793 | if (i2c->regs == NULL) { |
800 | dev_err(&pdev->dev, "cannot map IO\n"); | 794 | dev_err(&pdev->dev, "cannot map IO\n"); |
801 | ret = -ENXIO; | 795 | ret = -ENXIO; |
802 | goto out; | 796 | goto err_ioarea; |
803 | } | 797 | } |
804 | 798 | ||
805 | dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res); | 799 | dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res); |
@@ -813,7 +807,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
813 | 807 | ||
814 | ret = s3c24xx_i2c_init(i2c); | 808 | ret = s3c24xx_i2c_init(i2c); |
815 | if (ret != 0) | 809 | if (ret != 0) |
816 | goto out; | 810 | goto err_iomap; |
817 | 811 | ||
818 | /* find the IRQ for this unit (note, this relies on the init call to | 812 | /* find the IRQ for this unit (note, this relies on the init call to |
819 | * ensure no current IRQs pending | 813 | * ensure no current IRQs pending |
@@ -823,7 +817,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
823 | if (res == NULL) { | 817 | if (res == NULL) { |
824 | dev_err(&pdev->dev, "cannot find IRQ\n"); | 818 | dev_err(&pdev->dev, "cannot find IRQ\n"); |
825 | ret = -ENOENT; | 819 | ret = -ENOENT; |
826 | goto out; | 820 | goto err_iomap; |
827 | } | 821 | } |
828 | 822 | ||
829 | ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED, | 823 | ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED, |
@@ -831,7 +825,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
831 | 825 | ||
832 | if (ret != 0) { | 826 | if (ret != 0) { |
833 | dev_err(&pdev->dev, "cannot claim IRQ\n"); | 827 | dev_err(&pdev->dev, "cannot claim IRQ\n"); |
834 | goto out; | 828 | goto err_iomap; |
835 | } | 829 | } |
836 | 830 | ||
837 | i2c->irq = res; | 831 | i2c->irq = res; |
@@ -841,17 +835,29 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
841 | ret = i2c_add_adapter(&i2c->adap); | 835 | ret = i2c_add_adapter(&i2c->adap); |
842 | if (ret < 0) { | 836 | if (ret < 0) { |
843 | dev_err(&pdev->dev, "failed to add bus to i2c core\n"); | 837 | dev_err(&pdev->dev, "failed to add bus to i2c core\n"); |
844 | goto out; | 838 | goto err_irq; |
845 | } | 839 | } |
846 | 840 | ||
847 | platform_set_drvdata(pdev, i2c); | 841 | platform_set_drvdata(pdev, i2c); |
848 | 842 | ||
849 | dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id); | 843 | dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id); |
844 | return 0; | ||
850 | 845 | ||
851 | out: | 846 | err_irq: |
852 | if (ret < 0) | 847 | free_irq(i2c->irq->start, i2c); |
853 | s3c24xx_i2c_free(i2c); | 848 | |
849 | err_iomap: | ||
850 | iounmap(i2c->regs); | ||
854 | 851 | ||
852 | err_ioarea: | ||
853 | release_resource(i2c->ioarea); | ||
854 | kfree(i2c->ioarea); | ||
855 | |||
856 | err_clk: | ||
857 | clk_disable(i2c->clk); | ||
858 | clk_put(i2c->clk); | ||
859 | |||
860 | err_noclk: | ||
855 | return ret; | 861 | return ret; |
856 | } | 862 | } |
857 | 863 | ||
@@ -863,11 +869,17 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
863 | static int s3c24xx_i2c_remove(struct platform_device *pdev) | 869 | static int s3c24xx_i2c_remove(struct platform_device *pdev) |
864 | { | 870 | { |
865 | struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); | 871 | struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); |
866 | 872 | ||
867 | if (i2c != NULL) { | 873 | i2c_del_adapter(&i2c->adap); |
868 | s3c24xx_i2c_free(i2c); | 874 | free_irq(i2c->irq->start, i2c); |
869 | platform_set_drvdata(pdev, NULL); | 875 | |
870 | } | 876 | clk_disable(i2c->clk); |
877 | clk_put(i2c->clk); | ||
878 | |||
879 | iounmap(i2c->regs); | ||
880 | |||
881 | release_resource(i2c->ioarea); | ||
882 | kfree(i2c->ioarea); | ||
871 | 883 | ||
872 | return 0; | 884 | return 0; |
873 | } | 885 | } |
diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c new file mode 100644 index 000000000000..10af8d31e12a --- /dev/null +++ b/drivers/i2c/busses/i2c-simtec.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Simtec Electronics | ||
3 | * Ben Dooks <ben@simtec.co.uk> | ||
4 | * | ||
5 | * Simtec Generic I2C Controller | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | |||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/i2c-algo-bit.h> | ||
29 | |||
30 | #include <asm/io.h> | ||
31 | |||
32 | struct simtec_i2c_data { | ||
33 | struct resource *ioarea; | ||
34 | void __iomem *reg; | ||
35 | struct i2c_adapter adap; | ||
36 | struct i2c_algo_bit_data bit; | ||
37 | }; | ||
38 | |||
39 | #define CMD_SET_SDA (1<<2) | ||
40 | #define CMD_SET_SCL (1<<3) | ||
41 | |||
42 | #define STATE_SDA (1<<0) | ||
43 | #define STATE_SCL (1<<1) | ||
44 | |||
45 | /* i2c bit-bus functions */ | ||
46 | |||
47 | static void simtec_i2c_setsda(void *pw, int state) | ||
48 | { | ||
49 | struct simtec_i2c_data *pd = pw; | ||
50 | writeb(CMD_SET_SDA | (state ? STATE_SDA : 0), pd->reg); | ||
51 | } | ||
52 | |||
53 | static void simtec_i2c_setscl(void *pw, int state) | ||
54 | { | ||
55 | struct simtec_i2c_data *pd = pw; | ||
56 | writeb(CMD_SET_SCL | (state ? STATE_SCL : 0), pd->reg); | ||
57 | } | ||
58 | |||
59 | static int simtec_i2c_getsda(void *pw) | ||
60 | { | ||
61 | struct simtec_i2c_data *pd = pw; | ||
62 | return readb(pd->reg) & STATE_SDA ? 1 : 0; | ||
63 | } | ||
64 | |||
65 | static int simtec_i2c_getscl(void *pw) | ||
66 | { | ||
67 | struct simtec_i2c_data *pd = pw; | ||
68 | return readb(pd->reg) & STATE_SCL ? 1 : 0; | ||
69 | } | ||
70 | |||
71 | /* device registration */ | ||
72 | |||
73 | static int simtec_i2c_probe(struct platform_device *dev) | ||
74 | { | ||
75 | struct simtec_i2c_data *pd; | ||
76 | struct resource *res; | ||
77 | int size; | ||
78 | int ret; | ||
79 | |||
80 | pd = kzalloc(sizeof(struct simtec_i2c_data), GFP_KERNEL); | ||
81 | if (pd == NULL) { | ||
82 | dev_err(&dev->dev, "cannot allocate private data\n"); | ||
83 | return -ENOMEM; | ||
84 | } | ||
85 | |||
86 | platform_set_drvdata(dev, pd); | ||
87 | |||
88 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
89 | if (res == NULL) { | ||
90 | dev_err(&dev->dev, "cannot find IO resource\n"); | ||
91 | ret = -ENOENT; | ||
92 | goto err; | ||
93 | } | ||
94 | |||
95 | size = (res->end-res->start)+1; | ||
96 | |||
97 | pd->ioarea = request_mem_region(res->start, size, dev->name); | ||
98 | if (pd->ioarea == NULL) { | ||
99 | dev_err(&dev->dev, "cannot request IO\n"); | ||
100 | ret = -ENXIO; | ||
101 | goto err; | ||
102 | } | ||
103 | |||
104 | pd->reg = ioremap(res->start, size); | ||
105 | if (pd->reg == NULL) { | ||
106 | dev_err(&dev->dev, "cannot map IO\n"); | ||
107 | ret = -ENXIO; | ||
108 | goto err_res; | ||
109 | } | ||
110 | |||
111 | /* setup the private data */ | ||
112 | |||
113 | pd->adap.owner = THIS_MODULE; | ||
114 | pd->adap.algo_data = &pd->bit; | ||
115 | pd->adap.dev.parent = &dev->dev; | ||
116 | |||
117 | strlcpy(pd->adap.name, "Simtec I2C", sizeof(pd->adap.name)); | ||
118 | |||
119 | pd->bit.data = pd; | ||
120 | pd->bit.setsda = simtec_i2c_setsda; | ||
121 | pd->bit.setscl = simtec_i2c_setscl; | ||
122 | pd->bit.getsda = simtec_i2c_getsda; | ||
123 | pd->bit.getscl = simtec_i2c_getscl; | ||
124 | pd->bit.timeout = HZ; | ||
125 | pd->bit.udelay = 20; | ||
126 | |||
127 | ret = i2c_bit_add_bus(&pd->adap); | ||
128 | if (ret) | ||
129 | goto err_all; | ||
130 | |||
131 | return 0; | ||
132 | |||
133 | err_all: | ||
134 | iounmap(pd->reg); | ||
135 | |||
136 | err_res: | ||
137 | release_resource(pd->ioarea); | ||
138 | kfree(pd->ioarea); | ||
139 | |||
140 | err: | ||
141 | kfree(pd); | ||
142 | return ret; | ||
143 | } | ||
144 | |||
145 | static int simtec_i2c_remove(struct platform_device *dev) | ||
146 | { | ||
147 | struct simtec_i2c_data *pd = platform_get_drvdata(dev); | ||
148 | |||
149 | i2c_del_adapter(&pd->adap); | ||
150 | |||
151 | iounmap(pd->reg); | ||
152 | release_resource(pd->ioarea); | ||
153 | kfree(pd->ioarea); | ||
154 | kfree(pd); | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | |||
160 | /* device driver */ | ||
161 | |||
162 | static struct platform_driver simtec_i2c_driver = { | ||
163 | .driver = { | ||
164 | .name = "simtec-i2c", | ||
165 | .owner = THIS_MODULE, | ||
166 | }, | ||
167 | .probe = simtec_i2c_probe, | ||
168 | .remove = simtec_i2c_remove, | ||
169 | }; | ||
170 | |||
171 | static int __init i2c_adap_simtec_init(void) | ||
172 | { | ||
173 | return platform_driver_register(&simtec_i2c_driver); | ||
174 | } | ||
175 | |||
176 | static void __exit i2c_adap_simtec_exit(void) | ||
177 | { | ||
178 | platform_driver_unregister(&simtec_i2c_driver); | ||
179 | } | ||
180 | |||
181 | module_init(i2c_adap_simtec_init); | ||
182 | module_exit(i2c_adap_simtec_exit); | ||
183 | |||
184 | MODULE_DESCRIPTION("Simtec Generic I2C Bus driver"); | ||
185 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | ||
186 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c index 4157b0cd604c..dc235bb8e24d 100644 --- a/drivers/i2c/busses/i2c-sis96x.c +++ b/drivers/i2c/busses/i2c-sis96x.c | |||
@@ -300,7 +300,7 @@ static int __devinit sis96x_probe(struct pci_dev *dev, | |||
300 | /* set up the sysfs linkage to our parent device */ | 300 | /* set up the sysfs linkage to our parent device */ |
301 | sis96x_adapter.dev.parent = &dev->dev; | 301 | sis96x_adapter.dev.parent = &dev->dev; |
302 | 302 | ||
303 | snprintf(sis96x_adapter.name, I2C_NAME_SIZE, | 303 | snprintf(sis96x_adapter.name, sizeof(sis96x_adapter.name), |
304 | "SiS96x SMBus adapter at 0x%04x", sis96x_smbus_base); | 304 | "SiS96x SMBus adapter at 0x%04x", sis96x_smbus_base); |
305 | 305 | ||
306 | if ((retval = i2c_add_adapter(&sis96x_adapter))) { | 306 | if ((retval = i2c_add_adapter(&sis96x_adapter))) { |
diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c new file mode 100644 index 000000000000..907999049d50 --- /dev/null +++ b/drivers/i2c/busses/i2c-tiny-usb.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | * driver for the i2c-tiny-usb adapter - 1.0 | ||
3 | * http://www.harbaum.org/till/i2c_tiny_usb | ||
4 | * | ||
5 | * Copyright (C) 2006-2007 Till Harbaum (Till@Harbaum.org) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation, version 2. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/module.h> | ||
16 | |||
17 | /* include interfaces to usb layer */ | ||
18 | #include <linux/usb.h> | ||
19 | |||
20 | /* include interface to i2c layer */ | ||
21 | #include <linux/i2c.h> | ||
22 | |||
23 | /* commands via USB, must match command ids in the firmware */ | ||
24 | #define CMD_ECHO 0 | ||
25 | #define CMD_GET_FUNC 1 | ||
26 | #define CMD_SET_DELAY 2 | ||
27 | #define CMD_GET_STATUS 3 | ||
28 | |||
29 | #define CMD_I2C_IO 4 | ||
30 | #define CMD_I2C_IO_BEGIN (1<<0) | ||
31 | #define CMD_I2C_IO_END (1<<1) | ||
32 | |||
33 | /* i2c bit delay, default is 10us -> 100kHz */ | ||
34 | static int delay = 10; | ||
35 | module_param(delay, int, 0); | ||
36 | MODULE_PARM_DESC(delay, "bit delay in microseconds, " | ||
37 | "e.g. 10 for 100kHz (default is 100kHz)"); | ||
38 | |||
39 | static int usb_read(struct i2c_adapter *adapter, int cmd, | ||
40 | int value, int index, void *data, int len); | ||
41 | |||
42 | static int usb_write(struct i2c_adapter *adapter, int cmd, | ||
43 | int value, int index, void *data, int len); | ||
44 | |||
45 | /* ----- begin of i2c layer ---------------------------------------------- */ | ||
46 | |||
47 | #define STATUS_IDLE 0 | ||
48 | #define STATUS_ADDRESS_ACK 1 | ||
49 | #define STATUS_ADDRESS_NAK 2 | ||
50 | |||
51 | static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) | ||
52 | { | ||
53 | unsigned char status; | ||
54 | struct i2c_msg *pmsg; | ||
55 | int i; | ||
56 | |||
57 | dev_dbg(&adapter->dev, "master xfer %d messages:\n", num); | ||
58 | |||
59 | for (i = 0 ; i < num ; i++) { | ||
60 | int cmd = CMD_I2C_IO; | ||
61 | |||
62 | if (i == 0) | ||
63 | cmd |= CMD_I2C_IO_BEGIN; | ||
64 | |||
65 | if (i == num-1) | ||
66 | cmd |= CMD_I2C_IO_END; | ||
67 | |||
68 | pmsg = &msgs[i]; | ||
69 | |||
70 | dev_dbg(&adapter->dev, | ||
71 | " %d: %s (flags %d) %d bytes to 0x%02x\n", | ||
72 | i, pmsg->flags & I2C_M_RD ? "read" : "write", | ||
73 | pmsg->flags, pmsg->len, pmsg->addr); | ||
74 | |||
75 | /* and directly send the message */ | ||
76 | if (pmsg->flags & I2C_M_RD) { | ||
77 | /* read data */ | ||
78 | if (usb_read(adapter, cmd, | ||
79 | pmsg->flags, pmsg->addr, | ||
80 | pmsg->buf, pmsg->len) != pmsg->len) { | ||
81 | dev_err(&adapter->dev, | ||
82 | "failure reading data\n"); | ||
83 | return -EREMOTEIO; | ||
84 | } | ||
85 | } else { | ||
86 | /* write data */ | ||
87 | if (usb_write(adapter, cmd, | ||
88 | pmsg->flags, pmsg->addr, | ||
89 | pmsg->buf, pmsg->len) != pmsg->len) { | ||
90 | dev_err(&adapter->dev, | ||
91 | "failure writing data\n"); | ||
92 | return -EREMOTEIO; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | /* read status */ | ||
97 | if (usb_read(adapter, CMD_GET_STATUS, 0, 0, &status, 1) != 1) { | ||
98 | dev_err(&adapter->dev, "failure reading status\n"); | ||
99 | return -EREMOTEIO; | ||
100 | } | ||
101 | |||
102 | dev_dbg(&adapter->dev, " status = %d\n", status); | ||
103 | if (status == STATUS_ADDRESS_NAK) | ||
104 | return -EREMOTEIO; | ||
105 | } | ||
106 | |||
107 | return i; | ||
108 | } | ||
109 | |||
110 | static u32 usb_func(struct i2c_adapter *adapter) | ||
111 | { | ||
112 | u32 func; | ||
113 | |||
114 | /* get functionality from adapter */ | ||
115 | if (usb_read(adapter, CMD_GET_FUNC, 0, 0, &func, sizeof(func)) != | ||
116 | sizeof(func)) { | ||
117 | dev_err(&adapter->dev, "failure reading functionality\n"); | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | return func; | ||
122 | } | ||
123 | |||
124 | /* This is the actual algorithm we define */ | ||
125 | static const struct i2c_algorithm usb_algorithm = { | ||
126 | .master_xfer = usb_xfer, | ||
127 | .functionality = usb_func, | ||
128 | }; | ||
129 | |||
130 | /* ----- end of i2c layer ------------------------------------------------ */ | ||
131 | |||
132 | /* ----- begin of usb layer ---------------------------------------------- */ | ||
133 | |||
134 | /* The usb i2c interface uses a vid/pid pair donated by */ | ||
135 | /* Future Technology Devices International Ltd. */ | ||
136 | static struct usb_device_id i2c_tiny_usb_table [] = { | ||
137 | { USB_DEVICE(0x0403, 0xc631) }, | ||
138 | { } /* Terminating entry */ | ||
139 | }; | ||
140 | |||
141 | MODULE_DEVICE_TABLE(usb, i2c_tiny_usb_table); | ||
142 | |||
143 | /* Structure to hold all of our device specific stuff */ | ||
144 | struct i2c_tiny_usb { | ||
145 | struct usb_device *usb_dev; /* the usb device for this device */ | ||
146 | struct usb_interface *interface; /* the interface for this device */ | ||
147 | struct i2c_adapter adapter; /* i2c related things */ | ||
148 | }; | ||
149 | |||
150 | static int usb_read(struct i2c_adapter *adapter, int cmd, | ||
151 | int value, int index, void *data, int len) | ||
152 | { | ||
153 | struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data; | ||
154 | |||
155 | /* do control transfer */ | ||
156 | return usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0), | ||
157 | cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | | ||
158 | USB_DIR_IN, value, index, data, len, 2000); | ||
159 | } | ||
160 | |||
161 | static int usb_write(struct i2c_adapter *adapter, int cmd, | ||
162 | int value, int index, void *data, int len) | ||
163 | { | ||
164 | struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data; | ||
165 | |||
166 | /* do control transfer */ | ||
167 | return usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0), | ||
168 | cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE, | ||
169 | value, index, data, len, 2000); | ||
170 | } | ||
171 | |||
172 | static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev) | ||
173 | { | ||
174 | usb_put_dev(dev->usb_dev); | ||
175 | kfree(dev); | ||
176 | } | ||
177 | |||
178 | static int i2c_tiny_usb_probe(struct usb_interface *interface, | ||
179 | const struct usb_device_id *id) | ||
180 | { | ||
181 | struct i2c_tiny_usb *dev; | ||
182 | int retval = -ENOMEM; | ||
183 | u16 version; | ||
184 | |||
185 | dev_dbg(&interface->dev, "probing usb device\n"); | ||
186 | |||
187 | /* allocate memory for our device state and initialize it */ | ||
188 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
189 | if (dev == NULL) { | ||
190 | dev_err(&interface->dev, "Out of memory\n"); | ||
191 | goto error; | ||
192 | } | ||
193 | |||
194 | dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); | ||
195 | dev->interface = interface; | ||
196 | |||
197 | /* save our data pointer in this interface device */ | ||
198 | usb_set_intfdata(interface, dev); | ||
199 | |||
200 | version = le16_to_cpu(dev->usb_dev->descriptor.bcdDevice); | ||
201 | dev_info(&interface->dev, | ||
202 | "version %x.%02x found at bus %03d address %03d\n", | ||
203 | version >> 8, version & 0xff, | ||
204 | dev->usb_dev->bus->busnum, dev->usb_dev->devnum); | ||
205 | |||
206 | /* setup i2c adapter description */ | ||
207 | dev->adapter.owner = THIS_MODULE; | ||
208 | dev->adapter.class = I2C_CLASS_HWMON; | ||
209 | dev->adapter.algo = &usb_algorithm; | ||
210 | dev->adapter.algo_data = dev; | ||
211 | snprintf(dev->adapter.name, I2C_NAME_SIZE, | ||
212 | "i2c-tiny-usb at bus %03d device %03d", | ||
213 | dev->usb_dev->bus->busnum, dev->usb_dev->devnum); | ||
214 | |||
215 | if (usb_write(&dev->adapter, CMD_SET_DELAY, | ||
216 | cpu_to_le16(delay), 0, NULL, 0) != 0) { | ||
217 | dev_err(&dev->adapter.dev, | ||
218 | "failure setting delay to %dus\n", delay); | ||
219 | retval = -EIO; | ||
220 | goto error; | ||
221 | } | ||
222 | |||
223 | dev->adapter.dev.parent = &dev->interface->dev; | ||
224 | |||
225 | /* and finally attach to i2c layer */ | ||
226 | i2c_add_adapter(&dev->adapter); | ||
227 | |||
228 | /* inform user about successful attachment to i2c layer */ | ||
229 | dev_info(&dev->adapter.dev, "connected i2c-tiny-usb device\n"); | ||
230 | |||
231 | return 0; | ||
232 | |||
233 | error: | ||
234 | if (dev) | ||
235 | i2c_tiny_usb_free(dev); | ||
236 | |||
237 | return retval; | ||
238 | } | ||
239 | |||
240 | static void i2c_tiny_usb_disconnect(struct usb_interface *interface) | ||
241 | { | ||
242 | struct i2c_tiny_usb *dev = usb_get_intfdata(interface); | ||
243 | |||
244 | i2c_del_adapter(&dev->adapter); | ||
245 | usb_set_intfdata(interface, NULL); | ||
246 | i2c_tiny_usb_free(dev); | ||
247 | |||
248 | dev_dbg(&interface->dev, "disconnected\n"); | ||
249 | } | ||
250 | |||
251 | static struct usb_driver i2c_tiny_usb_driver = { | ||
252 | .name = "i2c-tiny-usb", | ||
253 | .probe = i2c_tiny_usb_probe, | ||
254 | .disconnect = i2c_tiny_usb_disconnect, | ||
255 | .id_table = i2c_tiny_usb_table, | ||
256 | }; | ||
257 | |||
258 | static int __init usb_i2c_tiny_usb_init(void) | ||
259 | { | ||
260 | /* register this driver with the USB subsystem */ | ||
261 | return usb_register(&i2c_tiny_usb_driver); | ||
262 | } | ||
263 | |||
264 | static void __exit usb_i2c_tiny_usb_exit(void) | ||
265 | { | ||
266 | /* deregister this driver with the USB subsystem */ | ||
267 | usb_deregister(&i2c_tiny_usb_driver); | ||
268 | } | ||
269 | |||
270 | module_init(usb_i2c_tiny_usb_init); | ||
271 | module_exit(usb_i2c_tiny_usb_exit); | ||
272 | |||
273 | /* ----- end of usb layer ------------------------------------------------ */ | ||
274 | |||
275 | MODULE_AUTHOR("Till Harbaum <Till@Harbaum.org>"); | ||
276 | MODULE_DESCRIPTION("i2c-tiny-usb driver v1.0"); | ||
277 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index 03c5fc868548..7a2bc06304fc 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c | |||
@@ -404,7 +404,7 @@ found: | |||
404 | } | 404 | } |
405 | 405 | ||
406 | vt596_adapter.dev.parent = &pdev->dev; | 406 | vt596_adapter.dev.parent = &pdev->dev; |
407 | snprintf(vt596_adapter.name, I2C_NAME_SIZE, | 407 | snprintf(vt596_adapter.name, sizeof(vt596_adapter.name), |
408 | "SMBus Via Pro adapter at %04x", vt596_smba); | 408 | "SMBus Via Pro adapter at %04x", vt596_smba); |
409 | 409 | ||
410 | vt596_pdev = pci_dev_get(pdev); | 410 | vt596_pdev = pci_dev_get(pdev); |
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 0b082c5a0195..0db56e7bc34e 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c | |||
@@ -441,7 +441,7 @@ static __init struct scx200_acb_iface *scx200_create_iface(const char *text, | |||
441 | 441 | ||
442 | adapter = &iface->adapter; | 442 | adapter = &iface->adapter; |
443 | i2c_set_adapdata(adapter, iface); | 443 | i2c_set_adapdata(adapter, iface); |
444 | snprintf(adapter->name, I2C_NAME_SIZE, "%s ACB%d", text, index); | 444 | snprintf(adapter->name, sizeof(adapter->name), "%s ACB%d", text, index); |
445 | adapter->owner = THIS_MODULE; | 445 | adapter->owner = THIS_MODULE; |
446 | adapter->id = I2C_HW_SMBUS_SCX200; | 446 | adapter->id = I2C_HW_SMBUS_SCX200; |
447 | adapter->algo = &scx200_acb_algorithm; | 447 | adapter->algo = &scx200_acb_algorithm; |
@@ -599,6 +599,7 @@ static __init int scx200_scan_pci(void) | |||
599 | else { | 599 | else { |
600 | int i; | 600 | int i; |
601 | 601 | ||
602 | pci_dev_put(pdev); | ||
602 | for (i = 0; i < MAX_DEVICES; ++i) { | 603 | for (i = 0; i < MAX_DEVICES; ++i) { |
603 | if (base[i] == 0) | 604 | if (base[i] == 0) |
604 | continue; | 605 | continue; |
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index 87ee3ce58618..ea085a006ead 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig | |||
@@ -3,11 +3,10 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | menu "Miscellaneous I2C Chip support" | 5 | menu "Miscellaneous I2C Chip support" |
6 | depends on I2C | ||
7 | 6 | ||
8 | config SENSORS_DS1337 | 7 | config SENSORS_DS1337 |
9 | tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock" | 8 | tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock" |
10 | depends on I2C && EXPERIMENTAL | 9 | depends on EXPERIMENTAL |
11 | help | 10 | help |
12 | If you say yes here you get support for Dallas Semiconductor | 11 | If you say yes here you get support for Dallas Semiconductor |
13 | DS1337 and DS1339 real-time clock chips. | 12 | DS1337 and DS1339 real-time clock chips. |
@@ -17,7 +16,7 @@ config SENSORS_DS1337 | |||
17 | 16 | ||
18 | config SENSORS_DS1374 | 17 | config SENSORS_DS1374 |
19 | tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock" | 18 | tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock" |
20 | depends on I2C && EXPERIMENTAL | 19 | depends on EXPERIMENTAL |
21 | help | 20 | help |
22 | If you say yes here you get support for Dallas Semiconductor | 21 | If you say yes here you get support for Dallas Semiconductor |
23 | DS1374 real-time clock chips. | 22 | DS1374 real-time clock chips. |
@@ -27,7 +26,7 @@ config SENSORS_DS1374 | |||
27 | 26 | ||
28 | config SENSORS_EEPROM | 27 | config SENSORS_EEPROM |
29 | tristate "EEPROM reader" | 28 | tristate "EEPROM reader" |
30 | depends on I2C && EXPERIMENTAL | 29 | depends on EXPERIMENTAL |
31 | help | 30 | help |
32 | If you say yes here you get read-only access to the EEPROM data | 31 | If you say yes here you get read-only access to the EEPROM data |
33 | available on modern memory DIMMs and Sony Vaio laptops. Such | 32 | available on modern memory DIMMs and Sony Vaio laptops. Such |
@@ -38,7 +37,7 @@ config SENSORS_EEPROM | |||
38 | 37 | ||
39 | config SENSORS_PCF8574 | 38 | config SENSORS_PCF8574 |
40 | tristate "Philips PCF8574 and PCF8574A" | 39 | tristate "Philips PCF8574 and PCF8574A" |
41 | depends on I2C && EXPERIMENTAL | 40 | depends on EXPERIMENTAL |
42 | default n | 41 | default n |
43 | help | 42 | help |
44 | If you say yes here you get support for Philips PCF8574 and | 43 | If you say yes here you get support for Philips PCF8574 and |
@@ -52,7 +51,7 @@ config SENSORS_PCF8574 | |||
52 | 51 | ||
53 | config SENSORS_PCA9539 | 52 | config SENSORS_PCA9539 |
54 | tristate "Philips PCA9539 16-bit I/O port" | 53 | tristate "Philips PCA9539 16-bit I/O port" |
55 | depends on I2C && EXPERIMENTAL | 54 | depends on EXPERIMENTAL |
56 | help | 55 | help |
57 | If you say yes here you get support for the Philips PCA9539 | 56 | If you say yes here you get support for the Philips PCA9539 |
58 | 16-bit I/O port. | 57 | 16-bit I/O port. |
@@ -62,7 +61,7 @@ config SENSORS_PCA9539 | |||
62 | 61 | ||
63 | config SENSORS_PCF8591 | 62 | config SENSORS_PCF8591 |
64 | tristate "Philips PCF8591" | 63 | tristate "Philips PCF8591" |
65 | depends on I2C && EXPERIMENTAL | 64 | depends on EXPERIMENTAL |
66 | default n | 65 | default n |
67 | help | 66 | help |
68 | If you say yes here you get support for Philips PCF8591 chips. | 67 | If you say yes here you get support for Philips PCF8591 chips. |
@@ -75,7 +74,7 @@ config SENSORS_PCF8591 | |||
75 | 74 | ||
76 | config ISP1301_OMAP | 75 | config ISP1301_OMAP |
77 | tristate "Philips ISP1301 with OMAP OTG" | 76 | tristate "Philips ISP1301 with OMAP OTG" |
78 | depends on I2C && ARCH_OMAP_OTG | 77 | depends on ARCH_OMAP_OTG |
79 | help | 78 | help |
80 | If you say yes here you get support for the Philips ISP1301 | 79 | If you say yes here you get support for the Philips ISP1301 |
81 | USB-On-The-Go transceiver working with the OMAP OTG controller. | 80 | USB-On-The-Go transceiver working with the OMAP OTG controller. |
@@ -90,7 +89,7 @@ config ISP1301_OMAP | |||
90 | # and having mostly OMAP-specific board support | 89 | # and having mostly OMAP-specific board support |
91 | config TPS65010 | 90 | config TPS65010 |
92 | tristate "TPS6501x Power Management chips" | 91 | tristate "TPS6501x Power Management chips" |
93 | depends on I2C && ARCH_OMAP | 92 | depends on ARCH_OMAP |
94 | default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK | 93 | default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK |
95 | help | 94 | help |
96 | If you say yes here you get support for the TPS6501x series of | 95 | If you say yes here you get support for the TPS6501x series of |
@@ -103,7 +102,7 @@ config TPS65010 | |||
103 | 102 | ||
104 | config SENSORS_M41T00 | 103 | config SENSORS_M41T00 |
105 | tristate "ST M41T00 RTC chip" | 104 | tristate "ST M41T00 RTC chip" |
106 | depends on I2C && PPC32 | 105 | depends on PPC32 |
107 | help | 106 | help |
108 | If you say yes here you get support for the ST M41T00 RTC chip. | 107 | If you say yes here you get support for the ST M41T00 RTC chip. |
109 | 108 | ||
@@ -112,7 +111,7 @@ config SENSORS_M41T00 | |||
112 | 111 | ||
113 | config SENSORS_MAX6875 | 112 | config SENSORS_MAX6875 |
114 | tristate "Maxim MAX6875 Power supply supervisor" | 113 | tristate "Maxim MAX6875 Power supply supervisor" |
115 | depends on I2C && EXPERIMENTAL | 114 | depends on EXPERIMENTAL |
116 | help | 115 | help |
117 | If you say yes here you get support for the Maxim MAX6875 | 116 | If you say yes here you get support for the Maxim MAX6875 |
118 | EEPROM-programmable, quad power-supply sequencer/supervisor. | 117 | EEPROM-programmable, quad power-supply sequencer/supervisor. |
diff --git a/drivers/i2c/i2c-boardinfo.c b/drivers/i2c/i2c-boardinfo.c new file mode 100644 index 000000000000..ffb35f09df03 --- /dev/null +++ b/drivers/i2c/i2c-boardinfo.c | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * i2c-boardinfo.h - collect pre-declarations of I2C devices | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/i2c.h> | ||
21 | |||
22 | #include "i2c-core.h" | ||
23 | |||
24 | |||
25 | /* These symbols are exported ONLY FOR the i2c core. | ||
26 | * No other users will be supported. | ||
27 | */ | ||
28 | DEFINE_MUTEX(__i2c_board_lock); | ||
29 | EXPORT_SYMBOL_GPL(__i2c_board_lock); | ||
30 | |||
31 | LIST_HEAD(__i2c_board_list); | ||
32 | EXPORT_SYMBOL_GPL(__i2c_board_list); | ||
33 | |||
34 | int __i2c_first_dynamic_bus_num; | ||
35 | EXPORT_SYMBOL_GPL(__i2c_first_dynamic_bus_num); | ||
36 | |||
37 | |||
38 | /** | ||
39 | * i2c_register_board_info - statically declare I2C devices | ||
40 | * @busnum: identifies the bus to which these devices belong | ||
41 | * @info: vector of i2c device descriptors | ||
42 | * @len: how many descriptors in the vector; may be zero to reserve | ||
43 | * the specified bus number. | ||
44 | * | ||
45 | * Systems using the Linux I2C driver stack can declare tables of board info | ||
46 | * while they initialize. This should be done in board-specific init code | ||
47 | * near arch_initcall() time, or equivalent, before any I2C adapter driver is | ||
48 | * registered. For example, mainboard init code could define several devices, | ||
49 | * as could the init code for each daughtercard in a board stack. | ||
50 | * | ||
51 | * The I2C devices will be created later, after the adapter for the relevant | ||
52 | * bus has been registered. After that moment, standard driver model tools | ||
53 | * are used to bind "new style" I2C drivers to the devices. The bus number | ||
54 | * for any device declared using this routine is not available for dynamic | ||
55 | * allocation. | ||
56 | * | ||
57 | * The board info passed can safely be __initdata, but be careful of embedded | ||
58 | * pointers (for platform_data, functions, etc) since that won't be copied. | ||
59 | */ | ||
60 | int __init | ||
61 | i2c_register_board_info(int busnum, | ||
62 | struct i2c_board_info const *info, unsigned len) | ||
63 | { | ||
64 | int status; | ||
65 | |||
66 | mutex_lock(&__i2c_board_lock); | ||
67 | |||
68 | /* dynamic bus numbers will be assigned after the last static one */ | ||
69 | if (busnum >= __i2c_first_dynamic_bus_num) | ||
70 | __i2c_first_dynamic_bus_num = busnum + 1; | ||
71 | |||
72 | for (status = 0; len; len--, info++) { | ||
73 | struct i2c_devinfo *devinfo; | ||
74 | |||
75 | devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL); | ||
76 | if (!devinfo) { | ||
77 | pr_debug("i2c-core: can't register boardinfo!\n"); | ||
78 | status = -ENOMEM; | ||
79 | break; | ||
80 | } | ||
81 | |||
82 | devinfo->busnum = busnum; | ||
83 | devinfo->board_info = *info; | ||
84 | list_add_tail(&devinfo->list, &__i2c_board_list); | ||
85 | } | ||
86 | |||
87 | mutex_unlock(&__i2c_board_lock); | ||
88 | |||
89 | return status; | ||
90 | } | ||
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 21fe1406c8b4..64f8e56d300e 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -35,29 +35,92 @@ | |||
35 | #include <linux/completion.h> | 35 | #include <linux/completion.h> |
36 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
37 | 37 | ||
38 | #include "i2c-core.h" | ||
39 | |||
38 | 40 | ||
39 | static LIST_HEAD(adapters); | 41 | static LIST_HEAD(adapters); |
40 | static LIST_HEAD(drivers); | 42 | static LIST_HEAD(drivers); |
41 | static DEFINE_MUTEX(core_lists); | 43 | static DEFINE_MUTEX(core_lists); |
42 | static DEFINE_IDR(i2c_adapter_idr); | 44 | static DEFINE_IDR(i2c_adapter_idr); |
43 | 45 | ||
46 | #define is_newstyle_driver(d) ((d)->probe || (d)->remove) | ||
44 | 47 | ||
45 | /* ------------------------------------------------------------------------- */ | 48 | /* ------------------------------------------------------------------------- */ |
46 | 49 | ||
47 | /* match always succeeds, as we want the probe() to tell if we really accept this match */ | ||
48 | static int i2c_device_match(struct device *dev, struct device_driver *drv) | 50 | static int i2c_device_match(struct device *dev, struct device_driver *drv) |
49 | { | 51 | { |
50 | return 1; | 52 | struct i2c_client *client = to_i2c_client(dev); |
53 | struct i2c_driver *driver = to_i2c_driver(drv); | ||
54 | |||
55 | /* make legacy i2c drivers bypass driver model probing entirely; | ||
56 | * such drivers scan each i2c adapter/bus themselves. | ||
57 | */ | ||
58 | if (!is_newstyle_driver(driver)) | ||
59 | return 0; | ||
60 | |||
61 | /* new style drivers use the same kind of driver matching policy | ||
62 | * as platform devices or SPI: compare device and driver IDs. | ||
63 | */ | ||
64 | return strcmp(client->driver_name, drv->name) == 0; | ||
65 | } | ||
66 | |||
67 | #ifdef CONFIG_HOTPLUG | ||
68 | |||
69 | /* uevent helps with hotplug: modprobe -q $(MODALIAS) */ | ||
70 | static int i2c_device_uevent(struct device *dev, char **envp, int num_envp, | ||
71 | char *buffer, int buffer_size) | ||
72 | { | ||
73 | struct i2c_client *client = to_i2c_client(dev); | ||
74 | int i = 0, length = 0; | ||
75 | |||
76 | /* by definition, legacy drivers can't hotplug */ | ||
77 | if (dev->driver || !client->driver_name) | ||
78 | return 0; | ||
79 | |||
80 | if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, | ||
81 | "MODALIAS=%s", client->driver_name)) | ||
82 | return -ENOMEM; | ||
83 | envp[i] = NULL; | ||
84 | dev_dbg(dev, "uevent\n"); | ||
85 | return 0; | ||
51 | } | 86 | } |
52 | 87 | ||
88 | #else | ||
89 | #define i2c_device_uevent NULL | ||
90 | #endif /* CONFIG_HOTPLUG */ | ||
91 | |||
53 | static int i2c_device_probe(struct device *dev) | 92 | static int i2c_device_probe(struct device *dev) |
54 | { | 93 | { |
55 | return -ENODEV; | 94 | struct i2c_client *client = to_i2c_client(dev); |
95 | struct i2c_driver *driver = to_i2c_driver(dev->driver); | ||
96 | |||
97 | if (!driver->probe) | ||
98 | return -ENODEV; | ||
99 | client->driver = driver; | ||
100 | dev_dbg(dev, "probe\n"); | ||
101 | return driver->probe(client); | ||
56 | } | 102 | } |
57 | 103 | ||
58 | static int i2c_device_remove(struct device *dev) | 104 | static int i2c_device_remove(struct device *dev) |
59 | { | 105 | { |
60 | return 0; | 106 | struct i2c_client *client = to_i2c_client(dev); |
107 | struct i2c_driver *driver; | ||
108 | int status; | ||
109 | |||
110 | if (!dev->driver) | ||
111 | return 0; | ||
112 | |||
113 | driver = to_i2c_driver(dev->driver); | ||
114 | if (driver->remove) { | ||
115 | dev_dbg(dev, "remove\n"); | ||
116 | status = driver->remove(client); | ||
117 | } else { | ||
118 | dev->driver = NULL; | ||
119 | status = 0; | ||
120 | } | ||
121 | if (status == 0) | ||
122 | client->driver = NULL; | ||
123 | return status; | ||
61 | } | 124 | } |
62 | 125 | ||
63 | static void i2c_device_shutdown(struct device *dev) | 126 | static void i2c_device_shutdown(struct device *dev) |
@@ -95,122 +158,184 @@ static int i2c_device_resume(struct device * dev) | |||
95 | return driver->resume(to_i2c_client(dev)); | 158 | return driver->resume(to_i2c_client(dev)); |
96 | } | 159 | } |
97 | 160 | ||
161 | static void i2c_client_release(struct device *dev) | ||
162 | { | ||
163 | struct i2c_client *client = to_i2c_client(dev); | ||
164 | complete(&client->released); | ||
165 | } | ||
166 | |||
167 | static void i2c_client_dev_release(struct device *dev) | ||
168 | { | ||
169 | kfree(to_i2c_client(dev)); | ||
170 | } | ||
171 | |||
172 | static ssize_t show_client_name(struct device *dev, struct device_attribute *attr, char *buf) | ||
173 | { | ||
174 | struct i2c_client *client = to_i2c_client(dev); | ||
175 | return sprintf(buf, "%s\n", client->name); | ||
176 | } | ||
177 | |||
178 | static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf) | ||
179 | { | ||
180 | struct i2c_client *client = to_i2c_client(dev); | ||
181 | return client->driver_name | ||
182 | ? sprintf(buf, "%s\n", client->driver_name) | ||
183 | : 0; | ||
184 | } | ||
185 | |||
186 | static struct device_attribute i2c_dev_attrs[] = { | ||
187 | __ATTR(name, S_IRUGO, show_client_name, NULL), | ||
188 | /* modalias helps coldplug: modprobe $(cat .../modalias) */ | ||
189 | __ATTR(modalias, S_IRUGO, show_modalias, NULL), | ||
190 | { }, | ||
191 | }; | ||
192 | |||
98 | struct bus_type i2c_bus_type = { | 193 | struct bus_type i2c_bus_type = { |
99 | .name = "i2c", | 194 | .name = "i2c", |
195 | .dev_attrs = i2c_dev_attrs, | ||
100 | .match = i2c_device_match, | 196 | .match = i2c_device_match, |
197 | .uevent = i2c_device_uevent, | ||
101 | .probe = i2c_device_probe, | 198 | .probe = i2c_device_probe, |
102 | .remove = i2c_device_remove, | 199 | .remove = i2c_device_remove, |
103 | .shutdown = i2c_device_shutdown, | 200 | .shutdown = i2c_device_shutdown, |
104 | .suspend = i2c_device_suspend, | 201 | .suspend = i2c_device_suspend, |
105 | .resume = i2c_device_resume, | 202 | .resume = i2c_device_resume, |
106 | }; | 203 | }; |
204 | EXPORT_SYMBOL_GPL(i2c_bus_type); | ||
107 | 205 | ||
108 | /* ------------------------------------------------------------------------- */ | 206 | /** |
207 | * i2c_new_device - instantiate an i2c device for use with a new style driver | ||
208 | * @adap: the adapter managing the device | ||
209 | * @info: describes one I2C device; bus_num is ignored | ||
210 | * | ||
211 | * Create a device to work with a new style i2c driver, where binding is | ||
212 | * handled through driver model probe()/remove() methods. This call is not | ||
213 | * appropriate for use by mainboad initialization logic, which usually runs | ||
214 | * during an arch_initcall() long before any i2c_adapter could exist. | ||
215 | * | ||
216 | * This returns the new i2c client, which may be saved for later use with | ||
217 | * i2c_unregister_device(); or NULL to indicate an error. | ||
218 | */ | ||
219 | struct i2c_client * | ||
220 | i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) | ||
221 | { | ||
222 | struct i2c_client *client; | ||
223 | int status; | ||
109 | 224 | ||
110 | void i2c_adapter_dev_release(struct device *dev) | 225 | client = kzalloc(sizeof *client, GFP_KERNEL); |
226 | if (!client) | ||
227 | return NULL; | ||
228 | |||
229 | client->adapter = adap; | ||
230 | |||
231 | client->dev.platform_data = info->platform_data; | ||
232 | client->flags = info->flags; | ||
233 | client->addr = info->addr; | ||
234 | client->irq = info->irq; | ||
235 | |||
236 | strlcpy(client->driver_name, info->driver_name, | ||
237 | sizeof(client->driver_name)); | ||
238 | strlcpy(client->name, info->type, sizeof(client->name)); | ||
239 | |||
240 | /* a new style driver may be bound to this device when we | ||
241 | * return from this function, or any later moment (e.g. maybe | ||
242 | * hotplugging will load the driver module). and the device | ||
243 | * refcount model is the standard driver model one. | ||
244 | */ | ||
245 | status = i2c_attach_client(client); | ||
246 | if (status < 0) { | ||
247 | kfree(client); | ||
248 | client = NULL; | ||
249 | } | ||
250 | return client; | ||
251 | } | ||
252 | EXPORT_SYMBOL_GPL(i2c_new_device); | ||
253 | |||
254 | |||
255 | /** | ||
256 | * i2c_unregister_device - reverse effect of i2c_new_device() | ||
257 | * @client: value returned from i2c_new_device() | ||
258 | */ | ||
259 | void i2c_unregister_device(struct i2c_client *client) | ||
111 | { | 260 | { |
112 | struct i2c_adapter *adap = dev_to_i2c_adapter(dev); | 261 | struct i2c_adapter *adapter = client->adapter; |
113 | complete(&adap->dev_released); | 262 | struct i2c_driver *driver = client->driver; |
263 | |||
264 | if (driver && !is_newstyle_driver(driver)) { | ||
265 | dev_err(&client->dev, "can't unregister devices " | ||
266 | "with legacy drivers\n"); | ||
267 | WARN_ON(1); | ||
268 | return; | ||
269 | } | ||
270 | |||
271 | mutex_lock(&adapter->clist_lock); | ||
272 | list_del(&client->list); | ||
273 | mutex_unlock(&adapter->clist_lock); | ||
274 | |||
275 | device_unregister(&client->dev); | ||
114 | } | 276 | } |
277 | EXPORT_SYMBOL_GPL(i2c_unregister_device); | ||
115 | 278 | ||
116 | struct device_driver i2c_adapter_driver = { | ||
117 | .owner = THIS_MODULE, | ||
118 | .name = "i2c_adapter", | ||
119 | .bus = &i2c_bus_type, | ||
120 | }; | ||
121 | 279 | ||
122 | /* ------------------------------------------------------------------------- */ | 280 | /* ------------------------------------------------------------------------- */ |
123 | 281 | ||
124 | /* I2C bus adapters -- one roots each I2C or SMBUS segment */ | 282 | /* I2C bus adapters -- one roots each I2C or SMBUS segment */ |
125 | 283 | ||
126 | static void i2c_adapter_class_dev_release(struct class_device *dev) | 284 | void i2c_adapter_dev_release(struct device *dev) |
127 | { | 285 | { |
128 | struct i2c_adapter *adap = class_dev_to_i2c_adapter(dev); | 286 | struct i2c_adapter *adap = to_i2c_adapter(dev); |
129 | complete(&adap->class_dev_released); | 287 | complete(&adap->dev_released); |
130 | } | 288 | } |
289 | EXPORT_SYMBOL_GPL(i2c_adapter_dev_release); /* exported to i2c-isa */ | ||
131 | 290 | ||
132 | static ssize_t i2c_adapter_show_name(struct class_device *cdev, char *buf) | 291 | static ssize_t |
292 | show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf) | ||
133 | { | 293 | { |
134 | struct i2c_adapter *adap = class_dev_to_i2c_adapter(cdev); | 294 | struct i2c_adapter *adap = to_i2c_adapter(dev); |
135 | return sprintf(buf, "%s\n", adap->name); | 295 | return sprintf(buf, "%s\n", adap->name); |
136 | } | 296 | } |
137 | 297 | ||
138 | static struct class_device_attribute i2c_adapter_attrs[] = { | 298 | static struct device_attribute i2c_adapter_attrs[] = { |
139 | __ATTR(name, S_IRUGO, i2c_adapter_show_name, NULL), | 299 | __ATTR(name, S_IRUGO, show_adapter_name, NULL), |
140 | { }, | 300 | { }, |
141 | }; | 301 | }; |
142 | 302 | ||
143 | struct class i2c_adapter_class = { | 303 | struct class i2c_adapter_class = { |
144 | .owner = THIS_MODULE, | 304 | .owner = THIS_MODULE, |
145 | .name = "i2c-adapter", | 305 | .name = "i2c-adapter", |
146 | .class_dev_attrs = i2c_adapter_attrs, | 306 | .dev_attrs = i2c_adapter_attrs, |
147 | .release = &i2c_adapter_class_dev_release, | ||
148 | }; | 307 | }; |
308 | EXPORT_SYMBOL_GPL(i2c_adapter_class); /* exported to i2c-isa */ | ||
149 | 309 | ||
150 | static ssize_t show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf) | 310 | static void i2c_scan_static_board_info(struct i2c_adapter *adapter) |
151 | { | ||
152 | struct i2c_adapter *adap = dev_to_i2c_adapter(dev); | ||
153 | return sprintf(buf, "%s\n", adap->name); | ||
154 | } | ||
155 | static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL); | ||
156 | |||
157 | |||
158 | static void i2c_client_release(struct device *dev) | ||
159 | { | ||
160 | struct i2c_client *client = to_i2c_client(dev); | ||
161 | complete(&client->released); | ||
162 | } | ||
163 | |||
164 | static ssize_t show_client_name(struct device *dev, struct device_attribute *attr, char *buf) | ||
165 | { | 311 | { |
166 | struct i2c_client *client = to_i2c_client(dev); | 312 | struct i2c_devinfo *devinfo; |
167 | return sprintf(buf, "%s\n", client->name); | 313 | |
314 | mutex_lock(&__i2c_board_lock); | ||
315 | list_for_each_entry(devinfo, &__i2c_board_list, list) { | ||
316 | if (devinfo->busnum == adapter->nr | ||
317 | && !i2c_new_device(adapter, | ||
318 | &devinfo->board_info)) | ||
319 | printk(KERN_ERR "i2c-core: can't create i2c%d-%04x\n", | ||
320 | i2c_adapter_id(adapter), | ||
321 | devinfo->board_info.addr); | ||
322 | } | ||
323 | mutex_unlock(&__i2c_board_lock); | ||
168 | } | 324 | } |
169 | 325 | ||
170 | /* | 326 | static int i2c_register_adapter(struct i2c_adapter *adap) |
171 | * We can't use the DEVICE_ATTR() macro here, as we used the same name for | ||
172 | * an i2c adapter attribute (above). | ||
173 | */ | ||
174 | static struct device_attribute dev_attr_client_name = | ||
175 | __ATTR(name, S_IRUGO, &show_client_name, NULL); | ||
176 | |||
177 | |||
178 | /* --------------------------------------------------- | ||
179 | * registering functions | ||
180 | * --------------------------------------------------- | ||
181 | */ | ||
182 | |||
183 | /* ----- | ||
184 | * i2c_add_adapter is called from within the algorithm layer, | ||
185 | * when a new hw adapter registers. A new device is register to be | ||
186 | * available for clients. | ||
187 | */ | ||
188 | int i2c_add_adapter(struct i2c_adapter *adap) | ||
189 | { | 327 | { |
190 | int id, res = 0; | 328 | int res = 0; |
191 | struct list_head *item; | 329 | struct list_head *item; |
192 | struct i2c_driver *driver; | 330 | struct i2c_driver *driver; |
193 | 331 | ||
194 | mutex_lock(&core_lists); | ||
195 | |||
196 | if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) { | ||
197 | res = -ENOMEM; | ||
198 | goto out_unlock; | ||
199 | } | ||
200 | |||
201 | res = idr_get_new(&i2c_adapter_idr, adap, &id); | ||
202 | if (res < 0) { | ||
203 | if (res == -EAGAIN) | ||
204 | res = -ENOMEM; | ||
205 | goto out_unlock; | ||
206 | } | ||
207 | |||
208 | adap->nr = id & MAX_ID_MASK; | ||
209 | mutex_init(&adap->bus_lock); | 332 | mutex_init(&adap->bus_lock); |
210 | mutex_init(&adap->clist_lock); | 333 | mutex_init(&adap->clist_lock); |
211 | list_add_tail(&adap->list,&adapters); | ||
212 | INIT_LIST_HEAD(&adap->clients); | 334 | INIT_LIST_HEAD(&adap->clients); |
213 | 335 | ||
336 | mutex_lock(&core_lists); | ||
337 | list_add_tail(&adap->list, &adapters); | ||
338 | |||
214 | /* Add the adapter to the driver core. | 339 | /* Add the adapter to the driver core. |
215 | * If the parent pointer is not set up, | 340 | * If the parent pointer is not set up, |
216 | * we add this adapter to the host bus. | 341 | * we add this adapter to the host bus. |
@@ -221,27 +346,19 @@ int i2c_add_adapter(struct i2c_adapter *adap) | |||
221 | "physical device\n", adap->name); | 346 | "physical device\n", adap->name); |
222 | } | 347 | } |
223 | sprintf(adap->dev.bus_id, "i2c-%d", adap->nr); | 348 | sprintf(adap->dev.bus_id, "i2c-%d", adap->nr); |
224 | adap->dev.driver = &i2c_adapter_driver; | ||
225 | adap->dev.release = &i2c_adapter_dev_release; | 349 | adap->dev.release = &i2c_adapter_dev_release; |
350 | adap->dev.class = &i2c_adapter_class; | ||
226 | res = device_register(&adap->dev); | 351 | res = device_register(&adap->dev); |
227 | if (res) | 352 | if (res) |
228 | goto out_list; | 353 | goto out_list; |
229 | res = device_create_file(&adap->dev, &dev_attr_name); | ||
230 | if (res) | ||
231 | goto out_unregister; | ||
232 | |||
233 | /* Add this adapter to the i2c_adapter class */ | ||
234 | memset(&adap->class_dev, 0x00, sizeof(struct class_device)); | ||
235 | adap->class_dev.dev = &adap->dev; | ||
236 | adap->class_dev.class = &i2c_adapter_class; | ||
237 | strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE); | ||
238 | res = class_device_register(&adap->class_dev); | ||
239 | if (res) | ||
240 | goto out_remove_name; | ||
241 | 354 | ||
242 | dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); | 355 | dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); |
243 | 356 | ||
244 | /* inform drivers of new adapters */ | 357 | /* create pre-declared device nodes for new-style drivers */ |
358 | if (adap->nr < __i2c_first_dynamic_bus_num) | ||
359 | i2c_scan_static_board_info(adap); | ||
360 | |||
361 | /* let legacy drivers scan this bus for matching devices */ | ||
245 | list_for_each(item,&drivers) { | 362 | list_for_each(item,&drivers) { |
246 | driver = list_entry(item, struct i2c_driver, list); | 363 | driver = list_entry(item, struct i2c_driver, list); |
247 | if (driver->attach_adapter) | 364 | if (driver->attach_adapter) |
@@ -253,18 +370,98 @@ out_unlock: | |||
253 | mutex_unlock(&core_lists); | 370 | mutex_unlock(&core_lists); |
254 | return res; | 371 | return res; |
255 | 372 | ||
256 | out_remove_name: | ||
257 | device_remove_file(&adap->dev, &dev_attr_name); | ||
258 | out_unregister: | ||
259 | init_completion(&adap->dev_released); /* Needed? */ | ||
260 | device_unregister(&adap->dev); | ||
261 | wait_for_completion(&adap->dev_released); | ||
262 | out_list: | 373 | out_list: |
263 | list_del(&adap->list); | 374 | list_del(&adap->list); |
264 | idr_remove(&i2c_adapter_idr, adap->nr); | 375 | idr_remove(&i2c_adapter_idr, adap->nr); |
265 | goto out_unlock; | 376 | goto out_unlock; |
266 | } | 377 | } |
267 | 378 | ||
379 | /** | ||
380 | * i2c_add_adapter - declare i2c adapter, use dynamic bus number | ||
381 | * @adapter: the adapter to add | ||
382 | * | ||
383 | * This routine is used to declare an I2C adapter when its bus number | ||
384 | * doesn't matter. Examples: for I2C adapters dynamically added by | ||
385 | * USB links or PCI plugin cards. | ||
386 | * | ||
387 | * When this returns zero, a new bus number was allocated and stored | ||
388 | * in adap->nr, and the specified adapter became available for clients. | ||
389 | * Otherwise, a negative errno value is returned. | ||
390 | */ | ||
391 | int i2c_add_adapter(struct i2c_adapter *adapter) | ||
392 | { | ||
393 | int id, res = 0; | ||
394 | |||
395 | retry: | ||
396 | if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) | ||
397 | return -ENOMEM; | ||
398 | |||
399 | mutex_lock(&core_lists); | ||
400 | /* "above" here means "above or equal to", sigh */ | ||
401 | res = idr_get_new_above(&i2c_adapter_idr, adapter, | ||
402 | __i2c_first_dynamic_bus_num, &id); | ||
403 | mutex_unlock(&core_lists); | ||
404 | |||
405 | if (res < 0) { | ||
406 | if (res == -EAGAIN) | ||
407 | goto retry; | ||
408 | return res; | ||
409 | } | ||
410 | |||
411 | adapter->nr = id; | ||
412 | return i2c_register_adapter(adapter); | ||
413 | } | ||
414 | EXPORT_SYMBOL(i2c_add_adapter); | ||
415 | |||
416 | /** | ||
417 | * i2c_add_numbered_adapter - declare i2c adapter, use static bus number | ||
418 | * @adap: the adapter to register (with adap->nr initialized) | ||
419 | * | ||
420 | * This routine is used to declare an I2C adapter when its bus number | ||
421 | * matters. Example: for I2C adapters from system-on-chip CPUs, or | ||
422 | * otherwise built in to the system's mainboard, and where i2c_board_info | ||
423 | * is used to properly configure I2C devices. | ||
424 | * | ||
425 | * If no devices have pre-been declared for this bus, then be sure to | ||
426 | * register the adapter before any dynamically allocated ones. Otherwise | ||
427 | * the required bus ID may not be available. | ||
428 | * | ||
429 | * When this returns zero, the specified adapter became available for | ||
430 | * clients using the bus number provided in adap->nr. Also, the table | ||
431 | * of I2C devices pre-declared using i2c_register_board_info() is scanned, | ||
432 | * and the appropriate driver model device nodes are created. Otherwise, a | ||
433 | * negative errno value is returned. | ||
434 | */ | ||
435 | int i2c_add_numbered_adapter(struct i2c_adapter *adap) | ||
436 | { | ||
437 | int id; | ||
438 | int status; | ||
439 | |||
440 | if (adap->nr & ~MAX_ID_MASK) | ||
441 | return -EINVAL; | ||
442 | |||
443 | retry: | ||
444 | if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) | ||
445 | return -ENOMEM; | ||
446 | |||
447 | mutex_lock(&core_lists); | ||
448 | /* "above" here means "above or equal to", sigh; | ||
449 | * we need the "equal to" result to force the result | ||
450 | */ | ||
451 | status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id); | ||
452 | if (status == 0 && id != adap->nr) { | ||
453 | status = -EBUSY; | ||
454 | idr_remove(&i2c_adapter_idr, id); | ||
455 | } | ||
456 | mutex_unlock(&core_lists); | ||
457 | if (status == -EAGAIN) | ||
458 | goto retry; | ||
459 | |||
460 | if (status == 0) | ||
461 | status = i2c_register_adapter(adap); | ||
462 | return status; | ||
463 | } | ||
464 | EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter); | ||
268 | 465 | ||
269 | int i2c_del_adapter(struct i2c_adapter *adap) | 466 | int i2c_del_adapter(struct i2c_adapter *adap) |
270 | { | 467 | { |
@@ -302,9 +499,19 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
302 | /* detach any active clients. This must be done first, because | 499 | /* detach any active clients. This must be done first, because |
303 | * it can fail; in which case we give up. */ | 500 | * it can fail; in which case we give up. */ |
304 | list_for_each_safe(item, _n, &adap->clients) { | 501 | list_for_each_safe(item, _n, &adap->clients) { |
502 | struct i2c_driver *driver; | ||
503 | |||
305 | client = list_entry(item, struct i2c_client, list); | 504 | client = list_entry(item, struct i2c_client, list); |
505 | driver = client->driver; | ||
506 | |||
507 | /* new style, follow standard driver model */ | ||
508 | if (!driver || is_newstyle_driver(driver)) { | ||
509 | i2c_unregister_device(client); | ||
510 | continue; | ||
511 | } | ||
306 | 512 | ||
307 | if ((res=client->driver->detach_client(client))) { | 513 | /* legacy drivers create and remove clients themselves */ |
514 | if ((res = driver->detach_client(client))) { | ||
308 | dev_err(&adap->dev, "detach_client failed for client " | 515 | dev_err(&adap->dev, "detach_client failed for client " |
309 | "[%s] at address 0x%02x\n", client->name, | 516 | "[%s] at address 0x%02x\n", client->name, |
310 | client->addr); | 517 | client->addr); |
@@ -314,17 +521,13 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
314 | 521 | ||
315 | /* clean up the sysfs representation */ | 522 | /* clean up the sysfs representation */ |
316 | init_completion(&adap->dev_released); | 523 | init_completion(&adap->dev_released); |
317 | init_completion(&adap->class_dev_released); | ||
318 | class_device_unregister(&adap->class_dev); | ||
319 | device_remove_file(&adap->dev, &dev_attr_name); | ||
320 | device_unregister(&adap->dev); | 524 | device_unregister(&adap->dev); |
321 | list_del(&adap->list); | 525 | list_del(&adap->list); |
322 | 526 | ||
323 | /* wait for sysfs to drop all references */ | 527 | /* wait for sysfs to drop all references */ |
324 | wait_for_completion(&adap->dev_released); | 528 | wait_for_completion(&adap->dev_released); |
325 | wait_for_completion(&adap->class_dev_released); | ||
326 | 529 | ||
327 | /* free dynamically allocated bus id */ | 530 | /* free bus id */ |
328 | idr_remove(&i2c_adapter_idr, adap->nr); | 531 | idr_remove(&i2c_adapter_idr, adap->nr); |
329 | 532 | ||
330 | dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); | 533 | dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); |
@@ -333,24 +536,42 @@ int i2c_del_adapter(struct i2c_adapter *adap) | |||
333 | mutex_unlock(&core_lists); | 536 | mutex_unlock(&core_lists); |
334 | return res; | 537 | return res; |
335 | } | 538 | } |
539 | EXPORT_SYMBOL(i2c_del_adapter); | ||
540 | |||
336 | 541 | ||
542 | /* ------------------------------------------------------------------------- */ | ||
337 | 543 | ||
338 | /* ----- | 544 | /* |
339 | * What follows is the "upwards" interface: commands for talking to clients, | 545 | * An i2c_driver is used with one or more i2c_client (device) nodes to access |
340 | * which implement the functions to access the physical information of the | 546 | * i2c slave chips, on a bus instance associated with some i2c_adapter. There |
341 | * chips. | 547 | * are two models for binding the driver to its device: "new style" drivers |
548 | * follow the standard Linux driver model and just respond to probe() calls | ||
549 | * issued if the driver core sees they match(); "legacy" drivers create device | ||
550 | * nodes themselves. | ||
342 | */ | 551 | */ |
343 | 552 | ||
344 | int i2c_register_driver(struct module *owner, struct i2c_driver *driver) | 553 | int i2c_register_driver(struct module *owner, struct i2c_driver *driver) |
345 | { | 554 | { |
346 | struct list_head *item; | ||
347 | struct i2c_adapter *adapter; | ||
348 | int res; | 555 | int res; |
349 | 556 | ||
557 | /* new style driver methods can't mix with legacy ones */ | ||
558 | if (is_newstyle_driver(driver)) { | ||
559 | if (driver->attach_adapter || driver->detach_adapter | ||
560 | || driver->detach_client) { | ||
561 | printk(KERN_WARNING | ||
562 | "i2c-core: driver [%s] is confused\n", | ||
563 | driver->driver.name); | ||
564 | return -EINVAL; | ||
565 | } | ||
566 | } | ||
567 | |||
350 | /* add the driver to the list of i2c drivers in the driver core */ | 568 | /* add the driver to the list of i2c drivers in the driver core */ |
351 | driver->driver.owner = owner; | 569 | driver->driver.owner = owner; |
352 | driver->driver.bus = &i2c_bus_type; | 570 | driver->driver.bus = &i2c_bus_type; |
353 | 571 | ||
572 | /* for new style drivers, when registration returns the driver core | ||
573 | * will have called probe() for all matching-but-unbound devices. | ||
574 | */ | ||
354 | res = driver_register(&driver->driver); | 575 | res = driver_register(&driver->driver); |
355 | if (res) | 576 | if (res) |
356 | return res; | 577 | return res; |
@@ -360,10 +581,11 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) | |||
360 | list_add_tail(&driver->list,&drivers); | 581 | list_add_tail(&driver->list,&drivers); |
361 | pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); | 582 | pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); |
362 | 583 | ||
363 | /* now look for instances of driver on our adapters */ | 584 | /* legacy drivers scan i2c busses directly */ |
364 | if (driver->attach_adapter) { | 585 | if (driver->attach_adapter) { |
365 | list_for_each(item,&adapters) { | 586 | struct i2c_adapter *adapter; |
366 | adapter = list_entry(item, struct i2c_adapter, list); | 587 | |
588 | list_for_each_entry(adapter, &adapters, list) { | ||
367 | driver->attach_adapter(adapter); | 589 | driver->attach_adapter(adapter); |
368 | } | 590 | } |
369 | } | 591 | } |
@@ -373,16 +595,22 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) | |||
373 | } | 595 | } |
374 | EXPORT_SYMBOL(i2c_register_driver); | 596 | EXPORT_SYMBOL(i2c_register_driver); |
375 | 597 | ||
376 | int i2c_del_driver(struct i2c_driver *driver) | 598 | /** |
599 | * i2c_del_driver - unregister I2C driver | ||
600 | * @driver: the driver being unregistered | ||
601 | */ | ||
602 | void i2c_del_driver(struct i2c_driver *driver) | ||
377 | { | 603 | { |
378 | struct list_head *item1, *item2, *_n; | 604 | struct list_head *item1, *item2, *_n; |
379 | struct i2c_client *client; | 605 | struct i2c_client *client; |
380 | struct i2c_adapter *adap; | 606 | struct i2c_adapter *adap; |
381 | 607 | ||
382 | int res = 0; | ||
383 | |||
384 | mutex_lock(&core_lists); | 608 | mutex_lock(&core_lists); |
385 | 609 | ||
610 | /* new-style driver? */ | ||
611 | if (is_newstyle_driver(driver)) | ||
612 | goto unregister; | ||
613 | |||
386 | /* Have a look at each adapter, if clients of this driver are still | 614 | /* Have a look at each adapter, if clients of this driver are still |
387 | * attached. If so, detach them to be able to kill the driver | 615 | * attached. If so, detach them to be able to kill the driver |
388 | * afterwards. | 616 | * afterwards. |
@@ -390,11 +618,10 @@ int i2c_del_driver(struct i2c_driver *driver) | |||
390 | list_for_each(item1,&adapters) { | 618 | list_for_each(item1,&adapters) { |
391 | adap = list_entry(item1, struct i2c_adapter, list); | 619 | adap = list_entry(item1, struct i2c_adapter, list); |
392 | if (driver->detach_adapter) { | 620 | if (driver->detach_adapter) { |
393 | if ((res = driver->detach_adapter(adap))) { | 621 | if (driver->detach_adapter(adap)) { |
394 | dev_err(&adap->dev, "detach_adapter failed " | 622 | dev_err(&adap->dev, "detach_adapter failed " |
395 | "for driver [%s]\n", | 623 | "for driver [%s]\n", |
396 | driver->driver.name); | 624 | driver->driver.name); |
397 | goto out_unlock; | ||
398 | } | 625 | } |
399 | } else { | 626 | } else { |
400 | list_for_each_safe(item2, _n, &adap->clients) { | 627 | list_for_each_safe(item2, _n, &adap->clients) { |
@@ -404,25 +631,26 @@ int i2c_del_driver(struct i2c_driver *driver) | |||
404 | dev_dbg(&adap->dev, "detaching client [%s] " | 631 | dev_dbg(&adap->dev, "detaching client [%s] " |
405 | "at 0x%02x\n", client->name, | 632 | "at 0x%02x\n", client->name, |
406 | client->addr); | 633 | client->addr); |
407 | if ((res = driver->detach_client(client))) { | 634 | if (driver->detach_client(client)) { |
408 | dev_err(&adap->dev, "detach_client " | 635 | dev_err(&adap->dev, "detach_client " |
409 | "failed for client [%s] at " | 636 | "failed for client [%s] at " |
410 | "0x%02x\n", client->name, | 637 | "0x%02x\n", client->name, |
411 | client->addr); | 638 | client->addr); |
412 | goto out_unlock; | ||
413 | } | 639 | } |
414 | } | 640 | } |
415 | } | 641 | } |
416 | } | 642 | } |
417 | 643 | ||
644 | unregister: | ||
418 | driver_unregister(&driver->driver); | 645 | driver_unregister(&driver->driver); |
419 | list_del(&driver->list); | 646 | list_del(&driver->list); |
420 | pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); | 647 | pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); |
421 | 648 | ||
422 | out_unlock: | ||
423 | mutex_unlock(&core_lists); | 649 | mutex_unlock(&core_lists); |
424 | return 0; | ||
425 | } | 650 | } |
651 | EXPORT_SYMBOL(i2c_del_driver); | ||
652 | |||
653 | /* ------------------------------------------------------------------------- */ | ||
426 | 654 | ||
427 | static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr) | 655 | static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr) |
428 | { | 656 | { |
@@ -447,6 +675,7 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr) | |||
447 | 675 | ||
448 | return rval; | 676 | return rval; |
449 | } | 677 | } |
678 | EXPORT_SYMBOL(i2c_check_addr); | ||
450 | 679 | ||
451 | int i2c_attach_client(struct i2c_client *client) | 680 | int i2c_attach_client(struct i2c_client *client) |
452 | { | 681 | { |
@@ -463,9 +692,15 @@ int i2c_attach_client(struct i2c_client *client) | |||
463 | client->usage_count = 0; | 692 | client->usage_count = 0; |
464 | 693 | ||
465 | client->dev.parent = &client->adapter->dev; | 694 | client->dev.parent = &client->adapter->dev; |
466 | client->dev.driver = &client->driver->driver; | ||
467 | client->dev.bus = &i2c_bus_type; | 695 | client->dev.bus = &i2c_bus_type; |
468 | client->dev.release = &i2c_client_release; | 696 | |
697 | if (client->driver) | ||
698 | client->dev.driver = &client->driver->driver; | ||
699 | |||
700 | if (client->driver && !is_newstyle_driver(client->driver)) | ||
701 | client->dev.release = i2c_client_release; | ||
702 | else | ||
703 | client->dev.release = i2c_client_dev_release; | ||
469 | 704 | ||
470 | snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id), | 705 | snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id), |
471 | "%d-%04x", i2c_adapter_id(adapter), client->addr); | 706 | "%d-%04x", i2c_adapter_id(adapter), client->addr); |
@@ -474,9 +709,6 @@ int i2c_attach_client(struct i2c_client *client) | |||
474 | res = device_register(&client->dev); | 709 | res = device_register(&client->dev); |
475 | if (res) | 710 | if (res) |
476 | goto out_list; | 711 | goto out_list; |
477 | res = device_create_file(&client->dev, &dev_attr_client_name); | ||
478 | if (res) | ||
479 | goto out_unregister; | ||
480 | mutex_unlock(&adapter->clist_lock); | 712 | mutex_unlock(&adapter->clist_lock); |
481 | 713 | ||
482 | if (adapter->client_register) { | 714 | if (adapter->client_register) { |
@@ -489,10 +721,6 @@ int i2c_attach_client(struct i2c_client *client) | |||
489 | 721 | ||
490 | return 0; | 722 | return 0; |
491 | 723 | ||
492 | out_unregister: | ||
493 | init_completion(&client->released); /* Needed? */ | ||
494 | device_unregister(&client->dev); | ||
495 | wait_for_completion(&client->released); | ||
496 | out_list: | 724 | out_list: |
497 | list_del(&client->list); | 725 | list_del(&client->list); |
498 | dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x " | 726 | dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x " |
@@ -501,7 +729,7 @@ out_unlock: | |||
501 | mutex_unlock(&adapter->clist_lock); | 729 | mutex_unlock(&adapter->clist_lock); |
502 | return res; | 730 | return res; |
503 | } | 731 | } |
504 | 732 | EXPORT_SYMBOL(i2c_attach_client); | |
505 | 733 | ||
506 | int i2c_detach_client(struct i2c_client *client) | 734 | int i2c_detach_client(struct i2c_client *client) |
507 | { | 735 | { |
@@ -527,7 +755,6 @@ int i2c_detach_client(struct i2c_client *client) | |||
527 | mutex_lock(&adapter->clist_lock); | 755 | mutex_lock(&adapter->clist_lock); |
528 | list_del(&client->list); | 756 | list_del(&client->list); |
529 | init_completion(&client->released); | 757 | init_completion(&client->released); |
530 | device_remove_file(&client->dev, &dev_attr_client_name); | ||
531 | device_unregister(&client->dev); | 758 | device_unregister(&client->dev); |
532 | mutex_unlock(&adapter->clist_lock); | 759 | mutex_unlock(&adapter->clist_lock); |
533 | wait_for_completion(&client->released); | 760 | wait_for_completion(&client->released); |
@@ -535,6 +762,7 @@ int i2c_detach_client(struct i2c_client *client) | |||
535 | out: | 762 | out: |
536 | return res; | 763 | return res; |
537 | } | 764 | } |
765 | EXPORT_SYMBOL(i2c_detach_client); | ||
538 | 766 | ||
539 | static int i2c_inc_use_client(struct i2c_client *client) | 767 | static int i2c_inc_use_client(struct i2c_client *client) |
540 | { | 768 | { |
@@ -567,6 +795,7 @@ int i2c_use_client(struct i2c_client *client) | |||
567 | 795 | ||
568 | return 0; | 796 | return 0; |
569 | } | 797 | } |
798 | EXPORT_SYMBOL(i2c_use_client); | ||
570 | 799 | ||
571 | int i2c_release_client(struct i2c_client *client) | 800 | int i2c_release_client(struct i2c_client *client) |
572 | { | 801 | { |
@@ -581,6 +810,7 @@ int i2c_release_client(struct i2c_client *client) | |||
581 | 810 | ||
582 | return 0; | 811 | return 0; |
583 | } | 812 | } |
813 | EXPORT_SYMBOL(i2c_release_client); | ||
584 | 814 | ||
585 | void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) | 815 | void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) |
586 | { | 816 | { |
@@ -601,6 +831,7 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) | |||
601 | } | 831 | } |
602 | mutex_unlock(&adap->clist_lock); | 832 | mutex_unlock(&adap->clist_lock); |
603 | } | 833 | } |
834 | EXPORT_SYMBOL(i2c_clients_command); | ||
604 | 835 | ||
605 | static int __init i2c_init(void) | 836 | static int __init i2c_init(void) |
606 | { | 837 | { |
@@ -609,16 +840,12 @@ static int __init i2c_init(void) | |||
609 | retval = bus_register(&i2c_bus_type); | 840 | retval = bus_register(&i2c_bus_type); |
610 | if (retval) | 841 | if (retval) |
611 | return retval; | 842 | return retval; |
612 | retval = driver_register(&i2c_adapter_driver); | ||
613 | if (retval) | ||
614 | return retval; | ||
615 | return class_register(&i2c_adapter_class); | 843 | return class_register(&i2c_adapter_class); |
616 | } | 844 | } |
617 | 845 | ||
618 | static void __exit i2c_exit(void) | 846 | static void __exit i2c_exit(void) |
619 | { | 847 | { |
620 | class_unregister(&i2c_adapter_class); | 848 | class_unregister(&i2c_adapter_class); |
621 | driver_unregister(&i2c_adapter_driver); | ||
622 | bus_unregister(&i2c_bus_type); | 849 | bus_unregister(&i2c_bus_type); |
623 | } | 850 | } |
624 | 851 | ||
@@ -638,8 +865,9 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) | |||
638 | #ifdef DEBUG | 865 | #ifdef DEBUG |
639 | for (ret = 0; ret < num; ret++) { | 866 | for (ret = 0; ret < num; ret++) { |
640 | dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, " | 867 | dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, " |
641 | "len=%d\n", ret, msgs[ret].flags & I2C_M_RD ? | 868 | "len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD) |
642 | 'R' : 'W', msgs[ret].addr, msgs[ret].len); | 869 | ? 'R' : 'W', msgs[ret].addr, msgs[ret].len, |
870 | (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : ""); | ||
643 | } | 871 | } |
644 | #endif | 872 | #endif |
645 | 873 | ||
@@ -653,6 +881,7 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) | |||
653 | return -ENOSYS; | 881 | return -ENOSYS; |
654 | } | 882 | } |
655 | } | 883 | } |
884 | EXPORT_SYMBOL(i2c_transfer); | ||
656 | 885 | ||
657 | int i2c_master_send(struct i2c_client *client,const char *buf ,int count) | 886 | int i2c_master_send(struct i2c_client *client,const char *buf ,int count) |
658 | { | 887 | { |
@@ -671,6 +900,7 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count) | |||
671 | transmitted, else error code. */ | 900 | transmitted, else error code. */ |
672 | return (ret == 1) ? count : ret; | 901 | return (ret == 1) ? count : ret; |
673 | } | 902 | } |
903 | EXPORT_SYMBOL(i2c_master_send); | ||
674 | 904 | ||
675 | int i2c_master_recv(struct i2c_client *client, char *buf ,int count) | 905 | int i2c_master_recv(struct i2c_client *client, char *buf ,int count) |
676 | { | 906 | { |
@@ -690,7 +920,7 @@ int i2c_master_recv(struct i2c_client *client, char *buf ,int count) | |||
690 | transmitted, else error code. */ | 920 | transmitted, else error code. */ |
691 | return (ret == 1) ? count : ret; | 921 | return (ret == 1) ? count : ret; |
692 | } | 922 | } |
693 | 923 | EXPORT_SYMBOL(i2c_master_recv); | |
694 | 924 | ||
695 | int i2c_control(struct i2c_client *client, | 925 | int i2c_control(struct i2c_client *client, |
696 | unsigned int cmd, unsigned long arg) | 926 | unsigned int cmd, unsigned long arg) |
@@ -712,6 +942,7 @@ int i2c_control(struct i2c_client *client, | |||
712 | } | 942 | } |
713 | return ret; | 943 | return ret; |
714 | } | 944 | } |
945 | EXPORT_SYMBOL(i2c_control); | ||
715 | 946 | ||
716 | /* ---------------------------------------------------- | 947 | /* ---------------------------------------------------- |
717 | * the i2c address scanning function | 948 | * the i2c address scanning function |
@@ -853,6 +1084,70 @@ int i2c_probe(struct i2c_adapter *adapter, | |||
853 | 1084 | ||
854 | return 0; | 1085 | return 0; |
855 | } | 1086 | } |
1087 | EXPORT_SYMBOL(i2c_probe); | ||
1088 | |||
1089 | struct i2c_client * | ||
1090 | i2c_new_probed_device(struct i2c_adapter *adap, | ||
1091 | struct i2c_board_info *info, | ||
1092 | unsigned short const *addr_list) | ||
1093 | { | ||
1094 | int i; | ||
1095 | |||
1096 | /* Stop here if the bus doesn't support probing */ | ||
1097 | if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE)) { | ||
1098 | dev_err(&adap->dev, "Probing not supported\n"); | ||
1099 | return NULL; | ||
1100 | } | ||
1101 | |||
1102 | mutex_lock(&adap->clist_lock); | ||
1103 | for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) { | ||
1104 | /* Check address validity */ | ||
1105 | if (addr_list[i] < 0x03 || addr_list[i] > 0x77) { | ||
1106 | dev_warn(&adap->dev, "Invalid 7-bit address " | ||
1107 | "0x%02x\n", addr_list[i]); | ||
1108 | continue; | ||
1109 | } | ||
1110 | |||
1111 | /* Check address availability */ | ||
1112 | if (__i2c_check_addr(adap, addr_list[i])) { | ||
1113 | dev_dbg(&adap->dev, "Address 0x%02x already in " | ||
1114 | "use, not probing\n", addr_list[i]); | ||
1115 | continue; | ||
1116 | } | ||
1117 | |||
1118 | /* Test address responsiveness | ||
1119 | The default probe method is a quick write, but it is known | ||
1120 | to corrupt the 24RF08 EEPROMs due to a state machine bug, | ||
1121 | and could also irreversibly write-protect some EEPROMs, so | ||
1122 | for address ranges 0x30-0x37 and 0x50-0x5f, we use a byte | ||
1123 | read instead. Also, some bus drivers don't implement | ||
1124 | quick write, so we fallback to a byte read it that case | ||
1125 | too. */ | ||
1126 | if ((addr_list[i] & ~0x07) == 0x30 | ||
1127 | || (addr_list[i] & ~0x0f) == 0x50 | ||
1128 | || !i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) { | ||
1129 | if (i2c_smbus_xfer(adap, addr_list[i], 0, | ||
1130 | I2C_SMBUS_READ, 0, | ||
1131 | I2C_SMBUS_BYTE, NULL) >= 0) | ||
1132 | break; | ||
1133 | } else { | ||
1134 | if (i2c_smbus_xfer(adap, addr_list[i], 0, | ||
1135 | I2C_SMBUS_WRITE, 0, | ||
1136 | I2C_SMBUS_QUICK, NULL) >= 0) | ||
1137 | break; | ||
1138 | } | ||
1139 | } | ||
1140 | mutex_unlock(&adap->clist_lock); | ||
1141 | |||
1142 | if (addr_list[i] == I2C_CLIENT_END) { | ||
1143 | dev_dbg(&adap->dev, "Probing failed, no device found\n"); | ||
1144 | return NULL; | ||
1145 | } | ||
1146 | |||
1147 | info->addr = addr_list[i]; | ||
1148 | return i2c_new_device(adap, info); | ||
1149 | } | ||
1150 | EXPORT_SYMBOL_GPL(i2c_new_probed_device); | ||
856 | 1151 | ||
857 | struct i2c_adapter* i2c_get_adapter(int id) | 1152 | struct i2c_adapter* i2c_get_adapter(int id) |
858 | { | 1153 | { |
@@ -866,11 +1161,13 @@ struct i2c_adapter* i2c_get_adapter(int id) | |||
866 | mutex_unlock(&core_lists); | 1161 | mutex_unlock(&core_lists); |
867 | return adapter; | 1162 | return adapter; |
868 | } | 1163 | } |
1164 | EXPORT_SYMBOL(i2c_get_adapter); | ||
869 | 1165 | ||
870 | void i2c_put_adapter(struct i2c_adapter *adap) | 1166 | void i2c_put_adapter(struct i2c_adapter *adap) |
871 | { | 1167 | { |
872 | module_put(adap->owner); | 1168 | module_put(adap->owner); |
873 | } | 1169 | } |
1170 | EXPORT_SYMBOL(i2c_put_adapter); | ||
874 | 1171 | ||
875 | /* The SMBus parts */ | 1172 | /* The SMBus parts */ |
876 | 1173 | ||
@@ -939,6 +1236,7 @@ s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value) | |||
939 | return i2c_smbus_xfer(client->adapter,client->addr,client->flags, | 1236 | return i2c_smbus_xfer(client->adapter,client->addr,client->flags, |
940 | value,0,I2C_SMBUS_QUICK,NULL); | 1237 | value,0,I2C_SMBUS_QUICK,NULL); |
941 | } | 1238 | } |
1239 | EXPORT_SYMBOL(i2c_smbus_write_quick); | ||
942 | 1240 | ||
943 | s32 i2c_smbus_read_byte(struct i2c_client *client) | 1241 | s32 i2c_smbus_read_byte(struct i2c_client *client) |
944 | { | 1242 | { |
@@ -949,12 +1247,14 @@ s32 i2c_smbus_read_byte(struct i2c_client *client) | |||
949 | else | 1247 | else |
950 | return data.byte; | 1248 | return data.byte; |
951 | } | 1249 | } |
1250 | EXPORT_SYMBOL(i2c_smbus_read_byte); | ||
952 | 1251 | ||
953 | s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value) | 1252 | s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value) |
954 | { | 1253 | { |
955 | return i2c_smbus_xfer(client->adapter,client->addr,client->flags, | 1254 | return i2c_smbus_xfer(client->adapter,client->addr,client->flags, |
956 | I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL); | 1255 | I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL); |
957 | } | 1256 | } |
1257 | EXPORT_SYMBOL(i2c_smbus_write_byte); | ||
958 | 1258 | ||
959 | s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command) | 1259 | s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command) |
960 | { | 1260 | { |
@@ -965,6 +1265,7 @@ s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command) | |||
965 | else | 1265 | else |
966 | return data.byte; | 1266 | return data.byte; |
967 | } | 1267 | } |
1268 | EXPORT_SYMBOL(i2c_smbus_read_byte_data); | ||
968 | 1269 | ||
969 | s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value) | 1270 | s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value) |
970 | { | 1271 | { |
@@ -974,6 +1275,7 @@ s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value) | |||
974 | I2C_SMBUS_WRITE,command, | 1275 | I2C_SMBUS_WRITE,command, |
975 | I2C_SMBUS_BYTE_DATA,&data); | 1276 | I2C_SMBUS_BYTE_DATA,&data); |
976 | } | 1277 | } |
1278 | EXPORT_SYMBOL(i2c_smbus_write_byte_data); | ||
977 | 1279 | ||
978 | s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command) | 1280 | s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command) |
979 | { | 1281 | { |
@@ -984,6 +1286,7 @@ s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command) | |||
984 | else | 1286 | else |
985 | return data.word; | 1287 | return data.word; |
986 | } | 1288 | } |
1289 | EXPORT_SYMBOL(i2c_smbus_read_word_data); | ||
987 | 1290 | ||
988 | s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value) | 1291 | s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value) |
989 | { | 1292 | { |
@@ -993,6 +1296,23 @@ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value) | |||
993 | I2C_SMBUS_WRITE,command, | 1296 | I2C_SMBUS_WRITE,command, |
994 | I2C_SMBUS_WORD_DATA,&data); | 1297 | I2C_SMBUS_WORD_DATA,&data); |
995 | } | 1298 | } |
1299 | EXPORT_SYMBOL(i2c_smbus_write_word_data); | ||
1300 | |||
1301 | /* Returns the number of read bytes */ | ||
1302 | s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command, | ||
1303 | u8 *values) | ||
1304 | { | ||
1305 | union i2c_smbus_data data; | ||
1306 | |||
1307 | if (i2c_smbus_xfer(client->adapter, client->addr, client->flags, | ||
1308 | I2C_SMBUS_READ, command, | ||
1309 | I2C_SMBUS_BLOCK_DATA, &data)) | ||
1310 | return -1; | ||
1311 | |||
1312 | memcpy(values, &data.block[1], data.block[0]); | ||
1313 | return data.block[0]; | ||
1314 | } | ||
1315 | EXPORT_SYMBOL(i2c_smbus_read_block_data); | ||
996 | 1316 | ||
997 | s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, | 1317 | s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, |
998 | u8 length, const u8 *values) | 1318 | u8 length, const u8 *values) |
@@ -1007,6 +1327,7 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, | |||
1007 | I2C_SMBUS_WRITE,command, | 1327 | I2C_SMBUS_WRITE,command, |
1008 | I2C_SMBUS_BLOCK_DATA,&data); | 1328 | I2C_SMBUS_BLOCK_DATA,&data); |
1009 | } | 1329 | } |
1330 | EXPORT_SYMBOL(i2c_smbus_write_block_data); | ||
1010 | 1331 | ||
1011 | /* Returns the number of read bytes */ | 1332 | /* Returns the number of read bytes */ |
1012 | s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values) | 1333 | s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values) |
@@ -1021,6 +1342,7 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *val | |||
1021 | memcpy(values, &data.block[1], data.block[0]); | 1342 | memcpy(values, &data.block[1], data.block[0]); |
1022 | return data.block[0]; | 1343 | return data.block[0]; |
1023 | } | 1344 | } |
1345 | EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data); | ||
1024 | 1346 | ||
1025 | s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, | 1347 | s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, |
1026 | u8 length, const u8 *values) | 1348 | u8 length, const u8 *values) |
@@ -1035,6 +1357,7 @@ s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, | |||
1035 | I2C_SMBUS_WRITE, command, | 1357 | I2C_SMBUS_WRITE, command, |
1036 | I2C_SMBUS_I2C_BLOCK_DATA, &data); | 1358 | I2C_SMBUS_I2C_BLOCK_DATA, &data); |
1037 | } | 1359 | } |
1360 | EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data); | ||
1038 | 1361 | ||
1039 | /* Simulate a SMBus command using the i2c protocol | 1362 | /* Simulate a SMBus command using the i2c protocol |
1040 | No checking of parameters is done! */ | 1363 | No checking of parameters is done! */ |
@@ -1098,9 +1421,9 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, | |||
1098 | break; | 1421 | break; |
1099 | case I2C_SMBUS_BLOCK_DATA: | 1422 | case I2C_SMBUS_BLOCK_DATA: |
1100 | if (read_write == I2C_SMBUS_READ) { | 1423 | if (read_write == I2C_SMBUS_READ) { |
1101 | dev_err(&adapter->dev, "Block read not supported " | 1424 | msg[1].flags |= I2C_M_RECV_LEN; |
1102 | "under I2C emulation!\n"); | 1425 | msg[1].len = 1; /* block length will be added by |
1103 | return -1; | 1426 | the underlying bus driver */ |
1104 | } else { | 1427 | } else { |
1105 | msg[0].len = data->block[0] + 2; | 1428 | msg[0].len = data->block[0] + 2; |
1106 | if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) { | 1429 | if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) { |
@@ -1114,9 +1437,21 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, | |||
1114 | } | 1437 | } |
1115 | break; | 1438 | break; |
1116 | case I2C_SMBUS_BLOCK_PROC_CALL: | 1439 | case I2C_SMBUS_BLOCK_PROC_CALL: |
1117 | dev_dbg(&adapter->dev, "Block process call not supported " | 1440 | num = 2; /* Another special case */ |
1118 | "under I2C emulation!\n"); | 1441 | read_write = I2C_SMBUS_READ; |
1119 | return -1; | 1442 | if (data->block[0] > I2C_SMBUS_BLOCK_MAX) { |
1443 | dev_err(&adapter->dev, "%s called with invalid " | ||
1444 | "block proc call size (%d)\n", __FUNCTION__, | ||
1445 | data->block[0]); | ||
1446 | return -1; | ||
1447 | } | ||
1448 | msg[0].len = data->block[0] + 2; | ||
1449 | for (i = 1; i < msg[0].len; i++) | ||
1450 | msgbuf0[i] = data->block[i-1]; | ||
1451 | msg[1].flags |= I2C_M_RECV_LEN; | ||
1452 | msg[1].len = 1; /* block length will be added by | ||
1453 | the underlying bus driver */ | ||
1454 | break; | ||
1120 | case I2C_SMBUS_I2C_BLOCK_DATA: | 1455 | case I2C_SMBUS_I2C_BLOCK_DATA: |
1121 | if (read_write == I2C_SMBUS_READ) { | 1456 | if (read_write == I2C_SMBUS_READ) { |
1122 | msg[1].len = I2C_SMBUS_BLOCK_MAX; | 1457 | msg[1].len = I2C_SMBUS_BLOCK_MAX; |
@@ -1180,6 +1515,11 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, | |||
1180 | for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++) | 1515 | for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++) |
1181 | data->block[i+1] = msgbuf1[i]; | 1516 | data->block[i+1] = msgbuf1[i]; |
1182 | break; | 1517 | break; |
1518 | case I2C_SMBUS_BLOCK_DATA: | ||
1519 | case I2C_SMBUS_BLOCK_PROC_CALL: | ||
1520 | for (i = 0; i < msgbuf1[0] + 1; i++) | ||
1521 | data->block[i] = msgbuf1[i]; | ||
1522 | break; | ||
1183 | } | 1523 | } |
1184 | return 0; | 1524 | return 0; |
1185 | } | 1525 | } |
@@ -1204,43 +1544,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, | |||
1204 | 1544 | ||
1205 | return res; | 1545 | return res; |
1206 | } | 1546 | } |
1207 | |||
1208 | |||
1209 | /* Next four are needed by i2c-isa */ | ||
1210 | EXPORT_SYMBOL_GPL(i2c_adapter_dev_release); | ||
1211 | EXPORT_SYMBOL_GPL(i2c_adapter_driver); | ||
1212 | EXPORT_SYMBOL_GPL(i2c_adapter_class); | ||
1213 | EXPORT_SYMBOL_GPL(i2c_bus_type); | ||
1214 | |||
1215 | EXPORT_SYMBOL(i2c_add_adapter); | ||
1216 | EXPORT_SYMBOL(i2c_del_adapter); | ||
1217 | EXPORT_SYMBOL(i2c_del_driver); | ||
1218 | EXPORT_SYMBOL(i2c_attach_client); | ||
1219 | EXPORT_SYMBOL(i2c_detach_client); | ||
1220 | EXPORT_SYMBOL(i2c_use_client); | ||
1221 | EXPORT_SYMBOL(i2c_release_client); | ||
1222 | EXPORT_SYMBOL(i2c_clients_command); | ||
1223 | EXPORT_SYMBOL(i2c_check_addr); | ||
1224 | |||
1225 | EXPORT_SYMBOL(i2c_master_send); | ||
1226 | EXPORT_SYMBOL(i2c_master_recv); | ||
1227 | EXPORT_SYMBOL(i2c_control); | ||
1228 | EXPORT_SYMBOL(i2c_transfer); | ||
1229 | EXPORT_SYMBOL(i2c_get_adapter); | ||
1230 | EXPORT_SYMBOL(i2c_put_adapter); | ||
1231 | EXPORT_SYMBOL(i2c_probe); | ||
1232 | |||
1233 | EXPORT_SYMBOL(i2c_smbus_xfer); | 1547 | EXPORT_SYMBOL(i2c_smbus_xfer); |
1234 | EXPORT_SYMBOL(i2c_smbus_write_quick); | ||
1235 | EXPORT_SYMBOL(i2c_smbus_read_byte); | ||
1236 | EXPORT_SYMBOL(i2c_smbus_write_byte); | ||
1237 | EXPORT_SYMBOL(i2c_smbus_read_byte_data); | ||
1238 | EXPORT_SYMBOL(i2c_smbus_write_byte_data); | ||
1239 | EXPORT_SYMBOL(i2c_smbus_read_word_data); | ||
1240 | EXPORT_SYMBOL(i2c_smbus_write_word_data); | ||
1241 | EXPORT_SYMBOL(i2c_smbus_write_block_data); | ||
1242 | EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data); | ||
1243 | EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data); | ||
1244 | 1548 | ||
1245 | MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); | 1549 | MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); |
1246 | MODULE_DESCRIPTION("I2C-Bus main module"); | 1550 | MODULE_DESCRIPTION("I2C-Bus main module"); |
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h new file mode 100644 index 000000000000..cd5bff874855 --- /dev/null +++ b/drivers/i2c/i2c-core.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * i2c-core.h - interfaces internal to the I2C framework | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
17 | */ | ||
18 | |||
19 | struct i2c_devinfo { | ||
20 | struct list_head list; | ||
21 | int busnum; | ||
22 | struct i2c_board_info board_info; | ||
23 | }; | ||
24 | |||
25 | /* board_lock protects board_list and first_dynamic_bus_num. | ||
26 | * only i2c core components are allowed to use these symbols. | ||
27 | */ | ||
28 | extern struct mutex __i2c_board_lock; | ||
29 | extern struct list_head __i2c_board_list; | ||
30 | extern int __i2c_first_dynamic_bus_num; | ||
31 | |||
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c index 6164a9a83396..bd0755c789c5 100644 --- a/drivers/ieee1394/hosts.c +++ b/drivers/ieee1394/hosts.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/list.h> | 15 | #include <linux/list.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/pci.h> | ||
19 | #include <linux/timer.h> | 18 | #include <linux/timer.h> |
20 | #include <linux/jiffies.h> | 19 | #include <linux/jiffies.h> |
21 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 842cd0b53e91..eff591deeb46 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <linux/err.h> | 40 | #include <linux/err.h> |
41 | #include <linux/idr.h> | 41 | #include <linux/idr.h> |
42 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
43 | #include <linux/pci.h> | ||
44 | #include <linux/random.h> | 43 | #include <linux/random.h> |
45 | #include <linux/rbtree.h> | 44 | #include <linux/rbtree.h> |
46 | #include <linux/spinlock.h> | 45 | #include <linux/spinlock.h> |
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 891d1fa7b2eb..223b1aa7d92b 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <linux/err.h> | 39 | #include <linux/err.h> |
40 | #include <linux/idr.h> | 40 | #include <linux/idr.h> |
41 | #include <linux/interrupt.h> | 41 | #include <linux/interrupt.h> |
42 | #include <linux/pci.h> | ||
43 | #include <linux/rbtree.h> | 42 | #include <linux/rbtree.h> |
44 | #include <linux/spinlock.h> | 43 | #include <linux/spinlock.h> |
45 | #include <linux/workqueue.h> | 44 | #include <linux/workqueue.h> |
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h index de89717f49fe..9be5cc00a3a9 100644 --- a/drivers/infiniband/core/mad_priv.h +++ b/drivers/infiniband/core/mad_priv.h | |||
@@ -39,7 +39,6 @@ | |||
39 | 39 | ||
40 | #include <linux/completion.h> | 40 | #include <linux/completion.h> |
41 | #include <linux/err.h> | 41 | #include <linux/err.h> |
42 | #include <linux/pci.h> | ||
43 | #include <linux/workqueue.h> | 42 | #include <linux/workqueue.h> |
44 | #include <rdma/ib_mad.h> | 43 | #include <rdma/ib_mad.h> |
45 | #include <rdma/ib_smi.h> | 44 | #include <rdma/ib_smi.h> |
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c index 4a579b3a1c90..1e13ab42b70b 100644 --- a/drivers/infiniband/core/multicast.c +++ b/drivers/infiniband/core/multicast.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/dma-mapping.h> | 34 | #include <linux/dma-mapping.h> |
35 | #include <linux/err.h> | 35 | #include <linux/err.h> |
36 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
37 | #include <linux/pci.h> | ||
38 | #include <linux/bitops.h> | 37 | #include <linux/bitops.h> |
39 | #include <linux/random.h> | 38 | #include <linux/random.h> |
40 | 39 | ||
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index 9a7eaadb1688..6469406ea9d8 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <linux/random.h> | 40 | #include <linux/random.h> |
41 | #include <linux/spinlock.h> | 41 | #include <linux/spinlock.h> |
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | #include <linux/pci.h> | ||
44 | #include <linux/dma-mapping.h> | 43 | #include <linux/dma-mapping.h> |
45 | #include <linux/kref.h> | 44 | #include <linux/kref.h> |
46 | #include <linux/idr.h> | 45 | #include <linux/idr.h> |
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 8199b83052a9..d97ded25c4ff 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <linux/err.h> | 40 | #include <linux/err.h> |
41 | #include <linux/fs.h> | 41 | #include <linux/fs.h> |
42 | #include <linux/cdev.h> | 42 | #include <linux/cdev.h> |
43 | #include <linux/pci.h> | ||
44 | #include <linux/dma-mapping.h> | 43 | #include <linux/dma-mapping.h> |
45 | #include <linux/poll.h> | 44 | #include <linux/poll.h> |
46 | #include <linux/rwsem.h> | 45 | #include <linux/rwsem.h> |
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index ed55979bfd34..036ed1ef1796 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/pagemap.h> | 38 | #include <linux/pagemap.h> |
39 | #include <linux/init.h> | 39 | #include <linux/init.h> |
40 | #include <linux/namei.h> | 40 | #include <linux/namei.h> |
41 | #include <linux/pci.h> | ||
42 | 41 | ||
43 | #include "ipath_kernel.h" | 42 | #include "ipath_kernel.h" |
44 | 43 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.c b/drivers/infiniband/hw/ipath/ipath_layer.c index e46aa4ed2a7e..05a1d2b01d9d 100644 --- a/drivers/infiniband/hw/ipath/ipath_layer.c +++ b/drivers/infiniband/hw/ipath/ipath_layer.c | |||
@@ -37,7 +37,6 @@ | |||
37 | */ | 37 | */ |
38 | 38 | ||
39 | #include <linux/io.h> | 39 | #include <linux/io.h> |
40 | #include <linux/pci.h> | ||
41 | #include <asm/byteorder.h> | 40 | #include <asm/byteorder.h> |
42 | 41 | ||
43 | #include "ipath_kernel.h" | 42 | #include "ipath_kernel.h" |
diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c index 9307f7187ca5..d8b5e4cefe25 100644 --- a/drivers/infiniband/hw/ipath/ipath_stats.c +++ b/drivers/infiniband/hw/ipath/ipath_stats.c | |||
@@ -31,8 +31,6 @@ | |||
31 | * SOFTWARE. | 31 | * SOFTWARE. |
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include <linux/pci.h> | ||
35 | |||
36 | #include "ipath_kernel.h" | 34 | #include "ipath_kernel.h" |
37 | 35 | ||
38 | struct infinipath_stats ipath_stats; | 36 | struct infinipath_stats ipath_stats; |
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c index ffa6318ad0cc..4dc398d5e011 100644 --- a/drivers/infiniband/hw/ipath/ipath_sysfs.c +++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c | |||
@@ -32,7 +32,6 @@ | |||
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include <linux/ctype.h> | 34 | #include <linux/ctype.h> |
35 | #include <linux/pci.h> | ||
36 | 35 | ||
37 | #include "ipath_kernel.h" | 36 | #include "ipath_kernel.h" |
38 | #include "ipath_common.h" | 37 | #include "ipath_common.h" |
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.h b/drivers/infiniband/hw/mthca/mthca_memfree.h index 594144145f45..a1ab06847b75 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.h +++ b/drivers/infiniband/hw/mthca/mthca_memfree.h | |||
@@ -38,7 +38,6 @@ | |||
38 | #define MTHCA_MEMFREE_H | 38 | #define MTHCA_MEMFREE_H |
39 | 39 | ||
40 | #include <linux/list.h> | 40 | #include <linux/list.h> |
41 | #include <linux/pci.h> | ||
42 | #include <linux/mutex.h> | 41 | #include <linux/mutex.h> |
43 | 42 | ||
44 | #define MTHCA_ICM_CHUNK_LEN \ | 43 | #define MTHCA_ICM_CHUNK_LEN \ |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index fd558267d1cb..d8f6bb4f53fc 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <linux/skbuff.h> | 41 | #include <linux/skbuff.h> |
42 | #include <linux/netdevice.h> | 42 | #include <linux/netdevice.h> |
43 | #include <linux/workqueue.h> | 43 | #include <linux/workqueue.h> |
44 | #include <linux/pci.h> | ||
45 | #include <linux/kref.h> | 44 | #include <linux/kref.h> |
46 | #include <linux/if_infiniband.h> | 45 | #include <linux/if_infiniband.h> |
47 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index f17e9c7d4b36..c845d5c4cbba 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -164,6 +164,17 @@ config KEYBOARD_AMIGA | |||
164 | To compile this driver as a module, choose M here: the | 164 | To compile this driver as a module, choose M here: the |
165 | module will be called amikbd. | 165 | module will be called amikbd. |
166 | 166 | ||
167 | config KEYBOARD_ATARI | ||
168 | tristate "Atari keyboard" | ||
169 | depends on ATARI | ||
170 | select ATARI_KBD_CORE | ||
171 | help | ||
172 | Say Y here if you are running Linux on any Atari and have a keyboard | ||
173 | attached. | ||
174 | |||
175 | To compile this driver as a module, choose M here: the | ||
176 | module will be called atakbd. | ||
177 | |||
167 | config KEYBOARD_HIL_OLD | 178 | config KEYBOARD_HIL_OLD |
168 | tristate "HP HIL keyboard support (simple driver)" | 179 | tristate "HP HIL keyboard support (simple driver)" |
169 | depends on GSC || HP300 | 180 | depends on GSC || HP300 |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 586a0fe53be6..7aa59ee5a0b6 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | |||
9 | obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o | 9 | obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o |
10 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | 10 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o |
11 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | 11 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o |
12 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | ||
12 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o | 13 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o |
13 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o | 14 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o |
14 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 15 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
diff --git a/drivers/input/keyboard/atakbd.c b/drivers/input/keyboard/atakbd.c new file mode 100644 index 000000000000..ded1d6ac6ff3 --- /dev/null +++ b/drivers/input/keyboard/atakbd.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * atakbd.c | ||
3 | * | ||
4 | * Copyright (c) 2005 Michael Schmitz | ||
5 | * | ||
6 | * Based on amikbd.c, which is | ||
7 | * | ||
8 | * Copyright (c) 2000-2001 Vojtech Pavlik | ||
9 | * | ||
10 | * Based on the work of: | ||
11 | * Hamish Macdonald | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * Atari keyboard driver for Linux/m68k | ||
16 | * | ||
17 | * The low level init and interrupt stuff is handled in arch/mm68k/atari/atakeyb.c | ||
18 | * (the keyboard ACIA also handles the mouse and joystick data, and the keyboard | ||
19 | * interrupt is shared with the MIDI ACIA so MIDI data also get handled there). | ||
20 | * This driver only deals with handing key events off to the input layer. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * This program is free software; you can redistribute it and/or modify | ||
25 | * it under the terms of the GNU General Public License as published by | ||
26 | * the Free Software Foundation; either version 2 of the License, or | ||
27 | * (at your option) any later version. | ||
28 | * | ||
29 | * This program is distributed in the hope that it will be useful, | ||
30 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
31 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
32 | * GNU General Public License for more details. | ||
33 | * | ||
34 | * You should have received a copy of the GNU General Public License | ||
35 | * along with this program; if not, write to the Free Software | ||
36 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
37 | * | ||
38 | * Should you need to contact me, the author, you can do so either by | ||
39 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | ||
40 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | ||
41 | */ | ||
42 | |||
43 | #include <linux/module.h> | ||
44 | #include <linux/init.h> | ||
45 | #include <linux/input.h> | ||
46 | #include <linux/delay.h> | ||
47 | #include <linux/interrupt.h> | ||
48 | |||
49 | #include <asm/atariints.h> | ||
50 | #include <asm/atarihw.h> | ||
51 | #include <asm/atarikb.h> | ||
52 | #include <asm/irq.h> | ||
53 | |||
54 | MODULE_AUTHOR("Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>"); | ||
55 | MODULE_DESCRIPTION("Atari keyboard driver"); | ||
56 | MODULE_LICENSE("GPL"); | ||
57 | |||
58 | static unsigned char atakbd_keycode[0x72]; | ||
59 | |||
60 | static struct input_dev *atakbd_dev; | ||
61 | |||
62 | static void atakbd_interrupt(unsigned char scancode, char down) | ||
63 | { | ||
64 | |||
65 | if (scancode < 0x72) { /* scancodes < 0xf2 are keys */ | ||
66 | |||
67 | // report raw events here? | ||
68 | |||
69 | scancode = atakbd_keycode[scancode]; | ||
70 | |||
71 | if (scancode == KEY_CAPSLOCK) { /* CapsLock is a toggle switch key on Amiga */ | ||
72 | input_report_key(atakbd_dev, scancode, 1); | ||
73 | input_report_key(atakbd_dev, scancode, 0); | ||
74 | input_sync(atakbd_dev); | ||
75 | } else { | ||
76 | input_report_key(atakbd_dev, scancode, down); | ||
77 | input_sync(atakbd_dev); | ||
78 | } | ||
79 | } else /* scancodes >= 0xf2 are mouse data, most likely */ | ||
80 | printk(KERN_INFO "atakbd: unhandled scancode %x\n", scancode); | ||
81 | |||
82 | return; | ||
83 | } | ||
84 | |||
85 | static int __init atakbd_init(void) | ||
86 | { | ||
87 | int i; | ||
88 | |||
89 | if (!ATARIHW_PRESENT(ST_MFP)) | ||
90 | return -EIO; | ||
91 | |||
92 | // TODO: request_mem_region if not done in arch code | ||
93 | |||
94 | if (!(atakbd_dev = input_allocate_device())) | ||
95 | return -ENOMEM; | ||
96 | |||
97 | // need to init core driver if not already done so | ||
98 | if (atari_keyb_init()) | ||
99 | return -ENODEV; | ||
100 | |||
101 | atakbd_dev->name = "Atari Keyboard"; | ||
102 | atakbd_dev->phys = "atakbd/input0"; | ||
103 | atakbd_dev->id.bustype = BUS_ATARI; | ||
104 | atakbd_dev->id.vendor = 0x0001; | ||
105 | atakbd_dev->id.product = 0x0001; | ||
106 | atakbd_dev->id.version = 0x0100; | ||
107 | |||
108 | atakbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
109 | atakbd_dev->keycode = atakbd_keycode; | ||
110 | atakbd_dev->keycodesize = sizeof(unsigned char); | ||
111 | atakbd_dev->keycodemax = ARRAY_SIZE(atakbd_keycode); | ||
112 | |||
113 | for (i = 1; i < 0x72; i++) { | ||
114 | atakbd_keycode[i] = i; | ||
115 | set_bit(atakbd_keycode[i], atakbd_dev->keybit); | ||
116 | } | ||
117 | |||
118 | input_register_device(atakbd_dev); | ||
119 | |||
120 | atari_input_keyboard_interrupt_hook = atakbd_interrupt; | ||
121 | |||
122 | printk(KERN_INFO "input: %s at IKBD ACIA\n", atakbd_dev->name); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static void __exit atakbd_exit(void) | ||
128 | { | ||
129 | atari_input_keyboard_interrupt_hook = NULL; | ||
130 | input_unregister_device(atakbd_dev); | ||
131 | } | ||
132 | |||
133 | module_init(atakbd_init); | ||
134 | module_exit(atakbd_exit); | ||
diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index 4de4dc297d50..56277fb291cd 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c | |||
@@ -52,7 +52,7 @@ MODULE_LICENSE("GPL v2"); | |||
52 | 52 | ||
53 | #elif defined(CONFIG_HP300) | 53 | #elif defined(CONFIG_HP300) |
54 | 54 | ||
55 | #define HILBASE 0xf0428000 /* HP300 (m86k) port address */ | 55 | #define HILBASE 0xf0428000UL /* HP300 (m68k) port address */ |
56 | #define HIL_DATA 0x1 | 56 | #define HIL_DATA 0x1 |
57 | #define HIL_CMD 0x3 | 57 | #define HIL_CMD 0x3 |
58 | #define HIL_IRQ 2 | 58 | #define HIL_IRQ 2 |
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 35d998c3e578..b40784a60aa1 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -96,6 +96,17 @@ config MOUSE_AMIGA | |||
96 | To compile this driver as a module, choose M here: the | 96 | To compile this driver as a module, choose M here: the |
97 | module will be called amimouse. | 97 | module will be called amimouse. |
98 | 98 | ||
99 | config MOUSE_ATARI | ||
100 | tristate "Atari mouse" | ||
101 | depends on ATARI | ||
102 | select ATARI_KBD_CORE | ||
103 | help | ||
104 | Say Y here if you have an Atari and want its native mouse | ||
105 | supported by the kernel. | ||
106 | |||
107 | To compile this driver as a module, choose M here: the | ||
108 | module will be called atarimouse. | ||
109 | |||
99 | config MOUSE_RISCPC | 110 | config MOUSE_RISCPC |
100 | tristate "Acorn RiscPC mouse" | 111 | tristate "Acorn RiscPC mouse" |
101 | depends on ARCH_ACORN | 112 | depends on ARCH_ACORN |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 21a1de61a79b..700f61200dfc 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o | 7 | obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o |
8 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o | ||
8 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o | 9 | obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o |
9 | obj-$(CONFIG_MOUSE_INPORT) += inport.o | 10 | obj-$(CONFIG_MOUSE_INPORT) += inport.o |
10 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o | 11 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o |
diff --git a/drivers/input/mouse/atarimouse.c b/drivers/input/mouse/atarimouse.c new file mode 100644 index 000000000000..43ab6566fb65 --- /dev/null +++ b/drivers/input/mouse/atarimouse.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Atari mouse driver for Linux/m68k | ||
3 | * | ||
4 | * Copyright (c) 2005 Michael Schmitz | ||
5 | * | ||
6 | * Based on: | ||
7 | * Amiga mouse driver for Linux/m68k | ||
8 | * | ||
9 | * Copyright (c) 2000-2002 Vojtech Pavlik | ||
10 | * | ||
11 | */ | ||
12 | /* | ||
13 | * The low level init and interrupt stuff is handled in arch/mm68k/atari/atakeyb.c | ||
14 | * (the keyboard ACIA also handles the mouse and joystick data, and the keyboard | ||
15 | * interrupt is shared with the MIDI ACIA so MIDI data also get handled there). | ||
16 | * This driver only deals with handing key events off to the input layer. | ||
17 | * | ||
18 | * Largely based on the old: | ||
19 | * | ||
20 | * Atari Mouse Driver for Linux | ||
21 | * by Robert de Vries (robert@and.nl) 19Jul93 | ||
22 | * | ||
23 | * 16 Nov 1994 Andreas Schwab | ||
24 | * Compatibility with busmouse | ||
25 | * Support for three button mouse (shamelessly stolen from MiNT) | ||
26 | * third button wired to one of the joystick directions on joystick 1 | ||
27 | * | ||
28 | * 1996/02/11 Andreas Schwab | ||
29 | * Module support | ||
30 | * Allow multiple open's | ||
31 | * | ||
32 | * Converted to use new generic busmouse code. 5 Apr 1998 | ||
33 | * Russell King <rmk@arm.uk.linux.org> | ||
34 | */ | ||
35 | |||
36 | |||
37 | /* | ||
38 | * This program is free software; you can redistribute it and/or modify it | ||
39 | * under the terms of the GNU General Public License version 2 as published by | ||
40 | * the Free Software Foundation | ||
41 | */ | ||
42 | |||
43 | #include <linux/module.h> | ||
44 | #include <linux/init.h> | ||
45 | #include <linux/input.h> | ||
46 | #include <linux/interrupt.h> | ||
47 | |||
48 | #include <asm/irq.h> | ||
49 | #include <asm/setup.h> | ||
50 | #include <asm/system.h> | ||
51 | #include <asm/uaccess.h> | ||
52 | #include <asm/atarihw.h> | ||
53 | #include <asm/atarikb.h> | ||
54 | #include <asm/atariints.h> | ||
55 | |||
56 | MODULE_AUTHOR("Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>"); | ||
57 | MODULE_DESCRIPTION("Atari mouse driver"); | ||
58 | MODULE_LICENSE("GPL"); | ||
59 | |||
60 | static int mouse_threshold[2] = {2,2}; | ||
61 | |||
62 | #ifdef __MODULE__ | ||
63 | MODULE_PARM(mouse_threshold, "2i"); | ||
64 | #endif | ||
65 | #ifdef FIXED_ATARI_JOYSTICK | ||
66 | extern int atari_mouse_buttons; | ||
67 | #endif | ||
68 | static int atamouse_used = 0; | ||
69 | |||
70 | static struct input_dev *atamouse_dev; | ||
71 | |||
72 | static void atamouse_interrupt(char *buf) | ||
73 | { | ||
74 | int buttons, dx, dy; | ||
75 | |||
76 | /* ikbd_mouse_disable(); */ | ||
77 | |||
78 | buttons = (buf[0] & 1) | ((buf[0] & 2) << 1); | ||
79 | #ifdef FIXED_ATARI_JOYSTICK | ||
80 | buttons |= atari_mouse_buttons & 2; | ||
81 | atari_mouse_buttons = buttons; | ||
82 | #endif | ||
83 | /* ikbd_mouse_rel_pos(); */ | ||
84 | |||
85 | /* only relative events get here */ | ||
86 | dx = buf[1]; | ||
87 | dy = -buf[2]; | ||
88 | |||
89 | input_report_rel(atamouse_dev, REL_X, dx); | ||
90 | input_report_rel(atamouse_dev, REL_Y, dy); | ||
91 | |||
92 | input_report_key(atamouse_dev, BTN_LEFT, buttons & 0x1); | ||
93 | input_report_key(atamouse_dev, BTN_MIDDLE, buttons & 0x2); | ||
94 | input_report_key(atamouse_dev, BTN_RIGHT, buttons & 0x4); | ||
95 | |||
96 | input_sync(atamouse_dev); | ||
97 | |||
98 | return; | ||
99 | } | ||
100 | |||
101 | static int atamouse_open(struct input_dev *dev) | ||
102 | { | ||
103 | if (atamouse_used++) | ||
104 | return 0; | ||
105 | |||
106 | #ifdef FIXED_ATARI_JOYSTICK | ||
107 | atari_mouse_buttons = 0; | ||
108 | #endif | ||
109 | ikbd_mouse_y0_top(); | ||
110 | ikbd_mouse_thresh(mouse_threshold[0], mouse_threshold[1]); | ||
111 | ikbd_mouse_rel_pos(); | ||
112 | atari_input_mouse_interrupt_hook = atamouse_interrupt; | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static void atamouse_close(struct input_dev *dev) | ||
117 | { | ||
118 | if (!--atamouse_used) { | ||
119 | ikbd_mouse_disable(); | ||
120 | atari_mouse_interrupt_hook = NULL; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | static int __init atamouse_init(void) | ||
125 | { | ||
126 | if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ST_MFP)) | ||
127 | return -ENODEV; | ||
128 | |||
129 | if (!(atamouse_dev = input_allocate_device())) | ||
130 | return -ENOMEM; | ||
131 | |||
132 | if (!(atari_keyb_init())) | ||
133 | return -ENODEV; | ||
134 | |||
135 | atamouse_dev->name = "Atari mouse"; | ||
136 | atamouse_dev->phys = "atamouse/input0"; | ||
137 | atamouse_dev->id.bustype = BUS_ATARI; | ||
138 | atamouse_dev->id.vendor = 0x0001; | ||
139 | atamouse_dev->id.product = 0x0002; | ||
140 | atamouse_dev->id.version = 0x0100; | ||
141 | |||
142 | atamouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
143 | atamouse_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
144 | atamouse_dev->keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | ||
145 | atamouse_dev->open = atamouse_open; | ||
146 | atamouse_dev->close = atamouse_close; | ||
147 | |||
148 | input_register_device(atamouse_dev); | ||
149 | |||
150 | printk(KERN_INFO "input: %s at keyboard ACIA\n", atamouse_dev->name); | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static void __exit atamouse_exit(void) | ||
155 | { | ||
156 | input_unregister_device(atamouse_dev); | ||
157 | } | ||
158 | |||
159 | module_init(atamouse_init); | ||
160 | module_exit(atamouse_exit); | ||
diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c index 38f648f9b0ed..02c6fbaeccf8 100644 --- a/drivers/isdn/hisax/netjet.c +++ b/drivers/isdn/hisax/netjet.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include "isac.h" | 19 | #include "isac.h" |
20 | #include "hscx.h" | 20 | #include "hscx.h" |
21 | #include "isdnl1.h" | 21 | #include "isdnl1.h" |
22 | #include <linux/pci.h> | ||
23 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
24 | #include <linux/ppp_defs.h> | 23 | #include <linux/ppp_defs.h> |
25 | #include <asm/io.h> | 24 | #include <asm/io.h> |
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c index f7e83a86f444..4c7dedac0e51 100644 --- a/drivers/isdn/hysdn/hysdn_proclog.c +++ b/drivers/isdn/hysdn/hysdn_proclog.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/poll.h> | 14 | #include <linux/poll.h> |
15 | #include <linux/proc_fs.h> | 15 | #include <linux/proc_fs.h> |
16 | #include <linux/pci.h> | ||
17 | #include <linux/smp_lock.h> | 16 | #include <linux/smp_lock.h> |
18 | 17 | ||
19 | #include "hysdn_defs.h" | 18 | #include "hysdn_defs.h" |
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index 35233de460ad..3d0354e96a97 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c | |||
@@ -459,7 +459,8 @@ therm_of_probe( struct of_device *dev, const struct of_device_id *match ) | |||
459 | static int | 459 | static int |
460 | therm_of_remove( struct of_device *dev ) | 460 | therm_of_remove( struct of_device *dev ) |
461 | { | 461 | { |
462 | return i2c_del_driver( &g4fan_driver ); | 462 | i2c_del_driver( &g4fan_driver ); |
463 | return 0; | ||
463 | } | 464 | } |
464 | 465 | ||
465 | static struct of_device_id therm_of_match[] = {{ | 466 | static struct of_device_id therm_of_match[] = {{ |
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c index 76d21775fc35..741a93a3eb61 100644 --- a/drivers/macintosh/via-cuda.c +++ b/drivers/macintosh/via-cuda.c | |||
@@ -82,6 +82,7 @@ static unsigned char cuda_rbuf[16]; | |||
82 | static unsigned char *reply_ptr; | 82 | static unsigned char *reply_ptr; |
83 | static int reading_reply; | 83 | static int reading_reply; |
84 | static int data_index; | 84 | static int data_index; |
85 | static int cuda_irq; | ||
85 | #ifdef CONFIG_PPC | 86 | #ifdef CONFIG_PPC |
86 | static struct device_node *vias; | 87 | static struct device_node *vias; |
87 | #endif | 88 | #endif |
@@ -160,10 +161,8 @@ int __init find_via_cuda(void) | |||
160 | /* Clear and enable interrupts, but only on PPC. On 68K it's done */ | 161 | /* Clear and enable interrupts, but only on PPC. On 68K it's done */ |
161 | /* for us by the main VIA driver in arch/m68k/mac/via.c */ | 162 | /* for us by the main VIA driver in arch/m68k/mac/via.c */ |
162 | 163 | ||
163 | #ifndef CONFIG_MAC | ||
164 | out_8(&via[IFR], 0x7f); /* clear interrupts by writing 1s */ | 164 | out_8(&via[IFR], 0x7f); /* clear interrupts by writing 1s */ |
165 | out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */ | 165 | out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */ |
166 | #endif | ||
167 | 166 | ||
168 | /* enable autopoll */ | 167 | /* enable autopoll */ |
169 | cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1); | 168 | cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1); |
@@ -181,24 +180,22 @@ int __init find_via_cuda(void) | |||
181 | 180 | ||
182 | static int __init via_cuda_start(void) | 181 | static int __init via_cuda_start(void) |
183 | { | 182 | { |
184 | unsigned int irq; | ||
185 | |||
186 | if (via == NULL) | 183 | if (via == NULL) |
187 | return -ENODEV; | 184 | return -ENODEV; |
188 | 185 | ||
189 | #ifdef CONFIG_MAC | 186 | #ifdef CONFIG_MAC |
190 | irq = IRQ_MAC_ADB; | 187 | cuda_irq = IRQ_MAC_ADB; |
191 | #else /* CONFIG_MAC */ | 188 | #else /* CONFIG_MAC */ |
192 | irq = irq_of_parse_and_map(vias, 0); | 189 | cuda_irq = irq_of_parse_and_map(vias, 0); |
193 | if (irq == NO_IRQ) { | 190 | if (cuda_irq == NO_IRQ) { |
194 | printk(KERN_ERR "via-cuda: can't map interrupts for %s\n", | 191 | printk(KERN_ERR "via-cuda: can't map interrupts for %s\n", |
195 | vias->full_name); | 192 | vias->full_name); |
196 | return -ENODEV; | 193 | return -ENODEV; |
197 | } | 194 | } |
198 | #endif /* CONFIG_MAP */ | 195 | #endif /* CONFIG_MAC */ |
199 | 196 | ||
200 | if (request_irq(irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) { | 197 | if (request_irq(cuda_irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) { |
201 | printk(KERN_ERR "via-cuda: can't request irq %d\n", irq); | 198 | printk(KERN_ERR "via-cuda: can't request irq %d\n", cuda_irq); |
202 | return -EAGAIN; | 199 | return -EAGAIN; |
203 | } | 200 | } |
204 | 201 | ||
@@ -238,6 +235,7 @@ cuda_init(void) | |||
238 | printk(KERN_ERR "cuda_init_via() failed\n"); | 235 | printk(KERN_ERR "cuda_init_via() failed\n"); |
239 | return -ENODEV; | 236 | return -ENODEV; |
240 | } | 237 | } |
238 | out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */ | ||
241 | 239 | ||
242 | return via_cuda_start(); | 240 | return via_cuda_start(); |
243 | #endif | 241 | #endif |
@@ -263,15 +261,17 @@ cuda_init_via(void) | |||
263 | out_8(&via[B], in_8(&via[B]) | TACK | TIP); /* negate them */ | 261 | out_8(&via[B], in_8(&via[B]) | TACK | TIP); /* negate them */ |
264 | out_8(&via[ACR] ,(in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT); /* SR data in */ | 262 | out_8(&via[ACR] ,(in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT); /* SR data in */ |
265 | (void)in_8(&via[SR]); /* clear any left-over data */ | 263 | (void)in_8(&via[SR]); /* clear any left-over data */ |
266 | #ifndef CONFIG_MAC | 264 | #ifdef CONFIG_PPC |
267 | out_8(&via[IER], 0x7f); /* disable interrupts from VIA */ | 265 | out_8(&via[IER], 0x7f); /* disable interrupts from VIA */ |
268 | (void)in_8(&via[IER]); | 266 | (void)in_8(&via[IER]); |
267 | #else | ||
268 | out_8(&via[IER], SR_INT); /* disable SR interrupt from VIA */ | ||
269 | #endif | 269 | #endif |
270 | 270 | ||
271 | /* delay 4ms and then clear any pending interrupt */ | 271 | /* delay 4ms and then clear any pending interrupt */ |
272 | mdelay(4); | 272 | mdelay(4); |
273 | (void)in_8(&via[SR]); | 273 | (void)in_8(&via[SR]); |
274 | out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); | 274 | out_8(&via[IFR], SR_INT); |
275 | 275 | ||
276 | /* sync with the CUDA - assert TACK without TIP */ | 276 | /* sync with the CUDA - assert TACK without TIP */ |
277 | out_8(&via[B], in_8(&via[B]) & ~TACK); | 277 | out_8(&via[B], in_8(&via[B]) & ~TACK); |
@@ -282,7 +282,7 @@ cuda_init_via(void) | |||
282 | /* wait for the interrupt and then clear it */ | 282 | /* wait for the interrupt and then clear it */ |
283 | WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)"); | 283 | WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)"); |
284 | (void)in_8(&via[SR]); | 284 | (void)in_8(&via[SR]); |
285 | out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); | 285 | out_8(&via[IFR], SR_INT); |
286 | 286 | ||
287 | /* finish the sync by negating TACK */ | 287 | /* finish the sync by negating TACK */ |
288 | out_8(&via[B], in_8(&via[B]) | TACK); | 288 | out_8(&via[B], in_8(&via[B]) | TACK); |
@@ -291,7 +291,7 @@ cuda_init_via(void) | |||
291 | WAIT_FOR(in_8(&via[B]) & TREQ, "CUDA response to sync (3)"); | 291 | WAIT_FOR(in_8(&via[B]) & TREQ, "CUDA response to sync (3)"); |
292 | WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)"); | 292 | WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)"); |
293 | (void)in_8(&via[SR]); | 293 | (void)in_8(&via[SR]); |
294 | out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); | 294 | out_8(&via[IFR], SR_INT); |
295 | out_8(&via[B], in_8(&via[B]) | TIP); /* should be unnecessary */ | 295 | out_8(&via[B], in_8(&via[B]) | TIP); /* should be unnecessary */ |
296 | 296 | ||
297 | return 0; | 297 | return 0; |
@@ -428,16 +428,12 @@ cuda_start(void) | |||
428 | void | 428 | void |
429 | cuda_poll(void) | 429 | cuda_poll(void) |
430 | { | 430 | { |
431 | unsigned long flags; | ||
432 | |||
433 | /* cuda_interrupt only takes a normal lock, we disable | 431 | /* cuda_interrupt only takes a normal lock, we disable |
434 | * interrupts here to avoid re-entering and thus deadlocking. | 432 | * interrupts here to avoid re-entering and thus deadlocking. |
435 | * An option would be to disable only the IRQ source with | ||
436 | * disable_irq(), would that work on m68k ? --BenH | ||
437 | */ | 433 | */ |
438 | local_irq_save(flags); | 434 | disable_irq(cuda_irq); |
439 | cuda_interrupt(0, NULL); | 435 | cuda_interrupt(0, NULL); |
440 | local_irq_restore(flags); | 436 | enable_irq(cuda_irq); |
441 | } | 437 | } |
442 | 438 | ||
443 | static irqreturn_t | 439 | static irqreturn_t |
@@ -448,15 +444,25 @@ cuda_interrupt(int irq, void *arg) | |||
448 | unsigned char ibuf[16]; | 444 | unsigned char ibuf[16]; |
449 | int ibuf_len = 0; | 445 | int ibuf_len = 0; |
450 | int complete = 0; | 446 | int complete = 0; |
451 | unsigned char virq; | ||
452 | 447 | ||
453 | spin_lock(&cuda_lock); | 448 | spin_lock(&cuda_lock); |
454 | 449 | ||
455 | virq = in_8(&via[IFR]) & 0x7f; | 450 | /* On powermacs, this handler is registered for the VIA IRQ. But it uses |
456 | out_8(&via[IFR], virq); | 451 | * just the shift register IRQ -- other VIA interrupt sources are disabled. |
457 | if ((virq & SR_INT) == 0) { | 452 | * On m68k macs, the VIA IRQ sources are dispatched individually. Unless |
458 | spin_unlock(&cuda_lock); | 453 | * we are polling, the shift register IRQ flag has already been cleared. |
459 | return IRQ_NONE; | 454 | */ |
455 | |||
456 | #ifdef CONFIG_MAC | ||
457 | if (!arg) | ||
458 | #endif | ||
459 | { | ||
460 | if ((in_8(&via[IFR]) & SR_INT) == 0) { | ||
461 | spin_unlock(&cuda_lock); | ||
462 | return IRQ_NONE; | ||
463 | } else { | ||
464 | out_8(&via[IFR], SR_INT); | ||
465 | } | ||
460 | } | 466 | } |
461 | 467 | ||
462 | status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT); | 468 | status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT); |
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c index 1b3bad62a1be..01b8eca7ccd5 100644 --- a/drivers/macintosh/via-macii.c +++ b/drivers/macintosh/via-macii.c | |||
@@ -12,6 +12,15 @@ | |||
12 | * 1999-08-02 (jmt) - Initial rewrite for Unified ADB. | 12 | * 1999-08-02 (jmt) - Initial rewrite for Unified ADB. |
13 | * 2000-03-29 Tony Mantler <tonym@mac.linux-m68k.org> | 13 | * 2000-03-29 Tony Mantler <tonym@mac.linux-m68k.org> |
14 | * - Big overhaul, should actually work now. | 14 | * - Big overhaul, should actually work now. |
15 | * 2006-12-31 Finn Thain <fthain@telegraphics.com.au> - Another overhaul. | ||
16 | * | ||
17 | * Suggested reading: | ||
18 | * Inside Macintosh, ch. 5 ADB Manager | ||
19 | * Guide to the Macinstosh Family Hardware, ch. 8 Apple Desktop Bus | ||
20 | * Rockwell R6522 VIA datasheet | ||
21 | * | ||
22 | * Apple's "ADB Analyzer" bus sniffer is invaluable: | ||
23 | * ftp://ftp.apple.com/developer/Tool_Chest/Devices_-_Hardware/Apple_Desktop_Bus/ | ||
15 | */ | 24 | */ |
16 | 25 | ||
17 | #include <stdarg.h> | 26 | #include <stdarg.h> |
@@ -26,7 +35,6 @@ | |||
26 | #include <asm/macints.h> | 35 | #include <asm/macints.h> |
27 | #include <asm/machw.h> | 36 | #include <asm/machw.h> |
28 | #include <asm/mac_via.h> | 37 | #include <asm/mac_via.h> |
29 | #include <asm/io.h> | ||
30 | #include <asm/system.h> | 38 | #include <asm/system.h> |
31 | 39 | ||
32 | static volatile unsigned char *via; | 40 | static volatile unsigned char *via; |
@@ -51,9 +59,7 @@ static volatile unsigned char *via; | |||
51 | #define ANH (15*RS) /* A-side data, no handshake */ | 59 | #define ANH (15*RS) /* A-side data, no handshake */ |
52 | 60 | ||
53 | /* Bits in B data register: all active low */ | 61 | /* Bits in B data register: all active low */ |
54 | #define TREQ 0x08 /* Transfer request (input) */ | 62 | #define CTLR_IRQ 0x08 /* Controller rcv status (input) */ |
55 | #define TACK 0x10 /* Transfer acknowledge (output) */ | ||
56 | #define TIP 0x20 /* Transfer in progress (output) */ | ||
57 | #define ST_MASK 0x30 /* mask for selecting ADB state bits */ | 63 | #define ST_MASK 0x30 /* mask for selecting ADB state bits */ |
58 | 64 | ||
59 | /* Bits in ACR */ | 65 | /* Bits in ACR */ |
@@ -65,8 +71,6 @@ static volatile unsigned char *via; | |||
65 | #define IER_SET 0x80 /* set bits in IER */ | 71 | #define IER_SET 0x80 /* set bits in IER */ |
66 | #define IER_CLR 0 /* clear bits in IER */ | 72 | #define IER_CLR 0 /* clear bits in IER */ |
67 | #define SR_INT 0x04 /* Shift register full/empty */ | 73 | #define SR_INT 0x04 /* Shift register full/empty */ |
68 | #define SR_DATA 0x08 /* Shift register data */ | ||
69 | #define SR_CLOCK 0x10 /* Shift register clock */ | ||
70 | 74 | ||
71 | /* ADB transaction states according to GMHW */ | 75 | /* ADB transaction states according to GMHW */ |
72 | #define ST_CMD 0x00 /* ADB state: command byte */ | 76 | #define ST_CMD 0x00 /* ADB state: command byte */ |
@@ -77,7 +81,6 @@ static volatile unsigned char *via; | |||
77 | static int macii_init_via(void); | 81 | static int macii_init_via(void); |
78 | static void macii_start(void); | 82 | static void macii_start(void); |
79 | static irqreturn_t macii_interrupt(int irq, void *arg); | 83 | static irqreturn_t macii_interrupt(int irq, void *arg); |
80 | static void macii_retransmit(int); | ||
81 | static void macii_queue_poll(void); | 84 | static void macii_queue_poll(void); |
82 | 85 | ||
83 | static int macii_probe(void); | 86 | static int macii_probe(void); |
@@ -103,29 +106,37 @@ static enum macii_state { | |||
103 | sending, | 106 | sending, |
104 | reading, | 107 | reading, |
105 | read_done, | 108 | read_done, |
106 | awaiting_reply | ||
107 | } macii_state; | 109 | } macii_state; |
108 | 110 | ||
109 | static int need_poll; | 111 | static struct adb_request *current_req; /* first request struct in the queue */ |
110 | static int command_byte; | 112 | static struct adb_request *last_req; /* last request struct in the queue */ |
111 | static int last_reply; | 113 | static unsigned char reply_buf[16]; /* storage for autopolled replies */ |
112 | static int last_active; | 114 | static unsigned char *reply_ptr; /* next byte in req->data or reply_buf */ |
113 | 115 | static int reading_reply; /* store reply in reply_buf else req->reply */ | |
114 | static struct adb_request *current_req; | 116 | static int data_index; /* index of the next byte to send from req->data */ |
115 | static struct adb_request *last_req; | 117 | static int reply_len; /* number of bytes received in reply_buf or req->reply */ |
116 | static struct adb_request *retry_req; | 118 | static int status; /* VIA's ADB status bits captured upon interrupt */ |
117 | static unsigned char reply_buf[16]; | 119 | static int last_status; /* status bits as at previous interrupt */ |
118 | static unsigned char *reply_ptr; | 120 | static int srq_asserted; /* have to poll for the device that asserted it */ |
119 | static int reply_len; | 121 | static int command_byte; /* the most recent command byte transmitted */ |
120 | static int reading_reply; | 122 | static int autopoll_devs; /* bits set are device addresses to be polled */ |
121 | static int data_index; | 123 | |
122 | static int first_byte; | 124 | /* Sanity check for request queue. Doesn't check for cycles. */ |
123 | static int prefix_len; | 125 | static int request_is_queued(struct adb_request *req) { |
124 | static int status = ST_IDLE|TREQ; | 126 | struct adb_request *cur; |
125 | static int last_status; | 127 | unsigned long flags; |
126 | static int driver_running; | 128 | local_irq_save(flags); |
127 | 129 | cur = current_req; | |
128 | /* debug level 10 required for ADB logging (should be && debug_adb, ideally) */ | 130 | while (cur) { |
131 | if (cur == req) { | ||
132 | local_irq_restore(flags); | ||
133 | return 1; | ||
134 | } | ||
135 | cur = cur->next; | ||
136 | } | ||
137 | local_irq_restore(flags); | ||
138 | return 0; | ||
139 | } | ||
129 | 140 | ||
130 | /* Check for MacII style ADB */ | 141 | /* Check for MacII style ADB */ |
131 | static int macii_probe(void) | 142 | static int macii_probe(void) |
@@ -147,15 +158,16 @@ int macii_init(void) | |||
147 | local_irq_save(flags); | 158 | local_irq_save(flags); |
148 | 159 | ||
149 | err = macii_init_via(); | 160 | err = macii_init_via(); |
150 | if (err) return err; | 161 | if (err) goto out; |
151 | 162 | ||
152 | err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB", | 163 | err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB", |
153 | macii_interrupt); | 164 | macii_interrupt); |
154 | if (err) return err; | 165 | if (err) goto out; |
155 | 166 | ||
156 | macii_state = idle; | 167 | macii_state = idle; |
168 | out: | ||
157 | local_irq_restore(flags); | 169 | local_irq_restore(flags); |
158 | return 0; | 170 | return err; |
159 | } | 171 | } |
160 | 172 | ||
161 | /* initialize the hardware */ | 173 | /* initialize the hardware */ |
@@ -163,12 +175,12 @@ static int macii_init_via(void) | |||
163 | { | 175 | { |
164 | unsigned char x; | 176 | unsigned char x; |
165 | 177 | ||
166 | /* Set the lines up. We want TREQ as input TACK|TIP as output */ | 178 | /* We want CTLR_IRQ as input and ST_EVEN | ST_ODD as output lines. */ |
167 | via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ; | 179 | via[DIRB] = (via[DIRB] | ST_EVEN | ST_ODD) & ~CTLR_IRQ; |
168 | 180 | ||
169 | /* Set up state: idle */ | 181 | /* Set up state: idle */ |
170 | via[B] |= ST_IDLE; | 182 | via[B] |= ST_IDLE; |
171 | last_status = via[B] & (ST_MASK|TREQ); | 183 | last_status = via[B] & (ST_MASK|CTLR_IRQ); |
172 | 184 | ||
173 | /* Shift register on input */ | 185 | /* Shift register on input */ |
174 | via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT; | 186 | via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT; |
@@ -179,81 +191,72 @@ static int macii_init_via(void) | |||
179 | return 0; | 191 | return 0; |
180 | } | 192 | } |
181 | 193 | ||
182 | /* Send an ADB poll (Talk Register 0 command, tagged on the front of the request queue) */ | 194 | /* Send an ADB poll (Talk Register 0 command prepended to the request queue) */ |
183 | static void macii_queue_poll(void) | 195 | static void macii_queue_poll(void) |
184 | { | 196 | { |
185 | static int device = 0; | 197 | /* No point polling the active device as it will never assert SRQ, so |
186 | static int in_poll=0; | 198 | * poll the next device in the autopoll list. This could leave us |
199 | * stuck in a polling loop if an unprobed device is asserting SRQ. | ||
200 | * In theory, that could only happen if a device was plugged in after | ||
201 | * probing started. Unplugging it again will break the cycle. | ||
202 | * (Simply polling the next higher device often ends up polling almost | ||
203 | * every device (after wrapping around), which takes too long.) | ||
204 | */ | ||
205 | int device_mask; | ||
206 | int next_device; | ||
187 | static struct adb_request req; | 207 | static struct adb_request req; |
188 | unsigned long flags; | ||
189 | |||
190 | if (in_poll) printk("macii_queue_poll: double poll!\n"); | ||
191 | |||
192 | in_poll++; | ||
193 | if (++device > 15) device = 1; | ||
194 | |||
195 | adb_request(&req, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1, | ||
196 | ADB_READREG(device, 0)); | ||
197 | |||
198 | local_irq_save(flags); | ||
199 | |||
200 | req.next = current_req; | ||
201 | current_req = &req; | ||
202 | 208 | ||
203 | local_irq_restore(flags); | 209 | if (!autopoll_devs) return; |
204 | macii_start(); | ||
205 | in_poll--; | ||
206 | } | ||
207 | 210 | ||
208 | /* Send an ADB retransmit (Talk, appended to the request queue) */ | 211 | device_mask = (1 << (((command_byte & 0xF0) >> 4) + 1)) - 1; |
209 | static void macii_retransmit(int device) | 212 | if (autopoll_devs & ~device_mask) |
210 | { | 213 | next_device = ffs(autopoll_devs & ~device_mask) - 1; |
211 | static int in_retransmit = 0; | 214 | else |
212 | static struct adb_request rt; | 215 | next_device = ffs(autopoll_devs) - 1; |
213 | unsigned long flags; | ||
214 | |||
215 | if (in_retransmit) printk("macii_retransmit: double retransmit!\n"); | ||
216 | 216 | ||
217 | in_retransmit++; | 217 | BUG_ON(request_is_queued(&req)); |
218 | 218 | ||
219 | adb_request(&rt, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1, | 219 | adb_request(&req, NULL, ADBREQ_NOSEND, 1, |
220 | ADB_READREG(device, 0)); | 220 | ADB_READREG(next_device, 0)); |
221 | 221 | ||
222 | local_irq_save(flags); | 222 | req.sent = 0; |
223 | req.complete = 0; | ||
224 | req.reply_len = 0; | ||
225 | req.next = current_req; | ||
223 | 226 | ||
224 | if (current_req != NULL) { | 227 | if (current_req != NULL) { |
225 | last_req->next = &rt; | 228 | current_req = &req; |
226 | last_req = &rt; | ||
227 | } else { | 229 | } else { |
228 | current_req = &rt; | 230 | current_req = &req; |
229 | last_req = &rt; | 231 | last_req = &req; |
230 | } | 232 | } |
231 | |||
232 | if (macii_state == idle) macii_start(); | ||
233 | |||
234 | local_irq_restore(flags); | ||
235 | in_retransmit--; | ||
236 | } | 233 | } |
237 | 234 | ||
238 | /* Send an ADB request; if sync, poll out the reply 'till it's done */ | 235 | /* Send an ADB request; if sync, poll out the reply 'till it's done */ |
239 | static int macii_send_request(struct adb_request *req, int sync) | 236 | static int macii_send_request(struct adb_request *req, int sync) |
240 | { | 237 | { |
241 | int i; | 238 | int err; |
239 | unsigned long flags; | ||
242 | 240 | ||
243 | i = macii_write(req); | 241 | BUG_ON(request_is_queued(req)); |
244 | if (i) return i; | ||
245 | 242 | ||
246 | if (sync) { | 243 | local_irq_save(flags); |
247 | while (!req->complete) macii_poll(); | 244 | err = macii_write(req); |
245 | local_irq_restore(flags); | ||
246 | |||
247 | if (!err && sync) { | ||
248 | while (!req->complete) { | ||
249 | macii_poll(); | ||
250 | } | ||
251 | BUG_ON(request_is_queued(req)); | ||
248 | } | 252 | } |
249 | return 0; | 253 | |
254 | return err; | ||
250 | } | 255 | } |
251 | 256 | ||
252 | /* Send an ADB request */ | 257 | /* Send an ADB request (append to request queue) */ |
253 | static int macii_write(struct adb_request *req) | 258 | static int macii_write(struct adb_request *req) |
254 | { | 259 | { |
255 | unsigned long flags; | ||
256 | |||
257 | if (req->nbytes < 2 || req->data[0] != ADB_PACKET || req->nbytes > 15) { | 260 | if (req->nbytes < 2 || req->data[0] != ADB_PACKET || req->nbytes > 15) { |
258 | req->complete = 1; | 261 | req->complete = 1; |
259 | return -EINVAL; | 262 | return -EINVAL; |
@@ -264,8 +267,6 @@ static int macii_write(struct adb_request *req) | |||
264 | req->complete = 0; | 267 | req->complete = 0; |
265 | req->reply_len = 0; | 268 | req->reply_len = 0; |
266 | 269 | ||
267 | local_irq_save(flags); | ||
268 | |||
269 | if (current_req != NULL) { | 270 | if (current_req != NULL) { |
270 | last_req->next = req; | 271 | last_req->next = req; |
271 | last_req = req; | 272 | last_req = req; |
@@ -274,28 +275,52 @@ static int macii_write(struct adb_request *req) | |||
274 | last_req = req; | 275 | last_req = req; |
275 | if (macii_state == idle) macii_start(); | 276 | if (macii_state == idle) macii_start(); |
276 | } | 277 | } |
277 | |||
278 | local_irq_restore(flags); | ||
279 | return 0; | 278 | return 0; |
280 | } | 279 | } |
281 | 280 | ||
282 | /* Start auto-polling */ | 281 | /* Start auto-polling */ |
283 | static int macii_autopoll(int devs) | 282 | static int macii_autopoll(int devs) |
284 | { | 283 | { |
285 | /* Just ping a random default address */ | 284 | static struct adb_request req; |
286 | if (!(current_req || retry_req)) | 285 | unsigned long flags; |
287 | macii_retransmit( (last_active < 16 && last_active > 0) ? last_active : 3); | 286 | int err = 0; |
288 | return 0; | 287 | |
288 | /* bit 1 == device 1, and so on. */ | ||
289 | autopoll_devs = devs & 0xFFFE; | ||
290 | |||
291 | if (!autopoll_devs) return 0; | ||
292 | |||
293 | local_irq_save(flags); | ||
294 | |||
295 | if (current_req == NULL) { | ||
296 | /* Send a Talk Reg 0. The controller will repeatedly transmit | ||
297 | * this as long as it is idle. | ||
298 | */ | ||
299 | adb_request(&req, NULL, ADBREQ_NOSEND, 1, | ||
300 | ADB_READREG(ffs(autopoll_devs) - 1, 0)); | ||
301 | err = macii_write(&req); | ||
302 | } | ||
303 | |||
304 | local_irq_restore(flags); | ||
305 | return err; | ||
306 | } | ||
307 | |||
308 | static inline int need_autopoll(void) { | ||
309 | /* Was the last command Talk Reg 0 | ||
310 | * and is the target on the autopoll list? | ||
311 | */ | ||
312 | if ((command_byte & 0x0F) == 0x0C && | ||
313 | ((1 << ((command_byte & 0xF0) >> 4)) & autopoll_devs)) | ||
314 | return 0; | ||
315 | return 1; | ||
289 | } | 316 | } |
290 | 317 | ||
291 | /* Prod the chip without interrupts */ | 318 | /* Prod the chip without interrupts */ |
292 | static void macii_poll(void) | 319 | static void macii_poll(void) |
293 | { | 320 | { |
294 | unsigned long flags; | 321 | disable_irq(IRQ_MAC_ADB); |
295 | 322 | macii_interrupt(0, NULL); | |
296 | local_irq_save(flags); | 323 | enable_irq(IRQ_MAC_ADB); |
297 | if (via[IFR] & SR_INT) macii_interrupt(0, NULL); | ||
298 | local_irq_restore(flags); | ||
299 | } | 324 | } |
300 | 325 | ||
301 | /* Reset the bus */ | 326 | /* Reset the bus */ |
@@ -303,73 +328,34 @@ static int macii_reset_bus(void) | |||
303 | { | 328 | { |
304 | static struct adb_request req; | 329 | static struct adb_request req; |
305 | 330 | ||
331 | if (request_is_queued(&req)) | ||
332 | return 0; | ||
333 | |||
306 | /* Command = 0, Address = ignored */ | 334 | /* Command = 0, Address = ignored */ |
307 | adb_request(&req, NULL, 0, 1, ADB_BUSRESET); | 335 | adb_request(&req, NULL, 0, 1, ADB_BUSRESET); |
308 | 336 | ||
337 | /* Don't want any more requests during the Global Reset low time. */ | ||
338 | udelay(3000); | ||
339 | |||
309 | return 0; | 340 | return 0; |
310 | } | 341 | } |
311 | 342 | ||
312 | /* Start sending ADB packet */ | 343 | /* Start sending ADB packet */ |
313 | static void macii_start(void) | 344 | static void macii_start(void) |
314 | { | 345 | { |
315 | unsigned long flags; | ||
316 | struct adb_request *req; | 346 | struct adb_request *req; |
317 | 347 | ||
318 | req = current_req; | 348 | req = current_req; |
319 | if (!req) return; | ||
320 | |||
321 | /* assert macii_state == idle */ | ||
322 | if (macii_state != idle) { | ||
323 | printk("macii_start: called while driver busy (%p %x %x)!\n", | ||
324 | req, macii_state, (uint) via1[B] & (ST_MASK|TREQ)); | ||
325 | return; | ||
326 | } | ||
327 | 349 | ||
328 | local_irq_save(flags); | 350 | BUG_ON(req == NULL); |
329 | 351 | ||
330 | /* | 352 | BUG_ON(macii_state != idle); |
331 | * IRQ signaled ?? (means ADB controller wants to send, or might | 353 | |
332 | * be end of packet if we were reading) | 354 | /* Now send it. Be careful though, that first byte of the request |
333 | */ | 355 | * is actually ADB_PACKET; the real data begins at index 1! |
334 | #if 0 /* FIXME: This is broke broke broke, for some reason */ | 356 | * And req->nbytes is the number of bytes of real data plus one. |
335 | if ((via[B] & TREQ) == 0) { | ||
336 | printk("macii_start: weird poll stuff. huh?\n"); | ||
337 | /* | ||
338 | * FIXME - we need to restart this on a timer | ||
339 | * or a collision at boot hangs us. | ||
340 | * Never set macii_state to idle here, or macii_start | ||
341 | * won't be called again from send_request! | ||
342 | * (need to re-check other cases ...) | ||
343 | */ | ||
344 | /* | ||
345 | * if the interrupt handler set the need_poll | ||
346 | * flag, it's hopefully a SRQ poll or re-Talk | ||
347 | * so we try to send here anyway | ||
348 | */ | ||
349 | if (!need_poll) { | ||
350 | if (console_loglevel == 10) | ||
351 | printk("macii_start: device busy - retry %p state %d status %x!\n", | ||
352 | req, macii_state, | ||
353 | (uint) via[B] & (ST_MASK|TREQ)); | ||
354 | retry_req = req; | ||
355 | /* set ADB status here ? */ | ||
356 | local_irq_restore(flags); | ||
357 | return; | ||
358 | } else { | ||
359 | need_poll = 0; | ||
360 | } | ||
361 | } | ||
362 | #endif | ||
363 | /* | ||
364 | * Another retry pending? (sanity check) | ||
365 | */ | 357 | */ |
366 | if (retry_req) { | ||
367 | retry_req = NULL; | ||
368 | } | ||
369 | 358 | ||
370 | /* Now send it. Be careful though, that first byte of the request */ | ||
371 | /* is actually ADB_PACKET; the real data begins at index 1! */ | ||
372 | |||
373 | /* store command byte */ | 359 | /* store command byte */ |
374 | command_byte = req->data[1]; | 360 | command_byte = req->data[1]; |
375 | /* Output mode */ | 361 | /* Output mode */ |
@@ -381,115 +367,97 @@ static void macii_start(void) | |||
381 | 367 | ||
382 | macii_state = sending; | 368 | macii_state = sending; |
383 | data_index = 2; | 369 | data_index = 2; |
384 | |||
385 | local_irq_restore(flags); | ||
386 | } | 370 | } |
387 | 371 | ||
388 | /* | 372 | /* |
389 | * The notorious ADB interrupt handler - does all of the protocol handling, | 373 | * The notorious ADB interrupt handler - does all of the protocol handling. |
390 | * except for starting new send operations. Relies heavily on the ADB | 374 | * Relies on the ADB controller sending and receiving data, thereby |
391 | * controller sending and receiving data, thereby generating SR interrupts | 375 | * generating shift register interrupts (SR_INT) for us. This means there has |
392 | * for us. This means there has to be always activity on the ADB bus, otherwise | 376 | * to be activity on the ADB bus. The chip will poll to achieve this. |
393 | * the whole process dies and has to be re-kicked by sending TALK requests ... | ||
394 | * CUDA-based Macs seem to solve this with the autopoll option, for MacII-type | ||
395 | * ADB the problem isn't solved yet (retransmit of the latest active TALK seems | ||
396 | * a good choice; either on timeout or on a timer interrupt). | ||
397 | * | 377 | * |
398 | * The basic ADB state machine was left unchanged from the original MacII code | 378 | * The basic ADB state machine was left unchanged from the original MacII code |
399 | * by Alan Cox, which was based on the CUDA driver for PowerMac. | 379 | * by Alan Cox, which was based on the CUDA driver for PowerMac. |
400 | * The syntax of the ADB status lines seems to be totally different on MacII, | 380 | * The syntax of the ADB status lines is totally different on MacII, |
401 | * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle for | 381 | * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle |
402 | * sending, and Idle -> Even -> Odd -> Even ->...-> Idle for receiving. Start | 382 | * for sending and Idle -> Even -> Odd -> Even ->...-> Idle for receiving. |
403 | * and end of a receive packet are signaled by asserting /IRQ on the interrupt | 383 | * Start and end of a receive packet are signalled by asserting /IRQ on the |
404 | * line. Timeouts are signaled by a sequence of 4 0xFF, with /IRQ asserted on | 384 | * interrupt line (/IRQ means the CTLR_IRQ bit in port B; not to be confused |
405 | * every other byte. SRQ is probably signaled by 3 or more 0xFF tacked on the | 385 | * with the VIA shift register interrupt. /IRQ never actually interrupts the |
406 | * end of a packet. (Thanks to Guido Koerber for eavesdropping on the ADB | 386 | * processor, it's just an ordinary input.) |
407 | * protocol with a logic analyzer!!) | ||
408 | * | ||
409 | * Note: As of 21/10/97, the MacII ADB part works including timeout detection | ||
410 | * and retransmit (Talk to the last active device). | ||
411 | */ | 387 | */ |
412 | static irqreturn_t macii_interrupt(int irq, void *arg) | 388 | static irqreturn_t macii_interrupt(int irq, void *arg) |
413 | { | 389 | { |
414 | int x, adbdir; | 390 | int x; |
415 | unsigned long flags; | 391 | static int entered; |
416 | struct adb_request *req; | 392 | struct adb_request *req; |
417 | 393 | ||
418 | last_status = status; | 394 | if (!arg) { |
419 | 395 | /* Clear the SR IRQ flag when polling. */ | |
420 | /* prevent races due to SCSI enabling ints */ | 396 | if (via[IFR] & SR_INT) |
421 | local_irq_save(flags); | 397 | via[IFR] = SR_INT; |
422 | 398 | else | |
423 | if (driver_running) { | 399 | return IRQ_NONE; |
424 | local_irq_restore(flags); | ||
425 | return IRQ_NONE; | ||
426 | } | 400 | } |
427 | 401 | ||
428 | driver_running = 1; | 402 | BUG_ON(entered++); |
429 | 403 | ||
430 | status = via[B] & (ST_MASK|TREQ); | 404 | last_status = status; |
431 | adbdir = via[ACR] & SR_OUT; | 405 | status = via[B] & (ST_MASK|CTLR_IRQ); |
432 | 406 | ||
433 | switch (macii_state) { | 407 | switch (macii_state) { |
434 | case idle: | 408 | case idle: |
409 | if (reading_reply) { | ||
410 | reply_ptr = current_req->reply; | ||
411 | } else { | ||
412 | BUG_ON(current_req != NULL); | ||
413 | reply_ptr = reply_buf; | ||
414 | } | ||
415 | |||
435 | x = via[SR]; | 416 | x = via[SR]; |
436 | first_byte = x; | ||
437 | /* set ADB state = even for first data byte */ | ||
438 | via[B] = (via[B] & ~ST_MASK) | ST_EVEN; | ||
439 | 417 | ||
440 | reply_buf[0] = first_byte; /* was command_byte?? */ | 418 | if ((status & CTLR_IRQ) && (x == 0xFF)) { |
441 | reply_ptr = reply_buf + 1; | 419 | /* Bus timeout without SRQ sequence: |
442 | reply_len = 1; | 420 | * data is "FF" while CTLR_IRQ is "H" |
443 | prefix_len = 1; | 421 | */ |
444 | reading_reply = 0; | 422 | reply_len = 0; |
445 | 423 | srq_asserted = 0; | |
446 | macii_state = reading; | 424 | macii_state = read_done; |
447 | break; | 425 | } else { |
426 | macii_state = reading; | ||
427 | *reply_ptr = x; | ||
428 | reply_len = 1; | ||
429 | } | ||
448 | 430 | ||
449 | case awaiting_reply: | ||
450 | /* handshake etc. for II ?? */ | ||
451 | x = via[SR]; | ||
452 | first_byte = x; | ||
453 | /* set ADB state = even for first data byte */ | 431 | /* set ADB state = even for first data byte */ |
454 | via[B] = (via[B] & ~ST_MASK) | ST_EVEN; | 432 | via[B] = (via[B] & ~ST_MASK) | ST_EVEN; |
455 | |||
456 | current_req->reply[0] = first_byte; | ||
457 | reply_ptr = current_req->reply + 1; | ||
458 | reply_len = 1; | ||
459 | prefix_len = 1; | ||
460 | reading_reply = 1; | ||
461 | |||
462 | macii_state = reading; | ||
463 | break; | 433 | break; |
464 | 434 | ||
465 | case sending: | 435 | case sending: |
466 | req = current_req; | 436 | req = current_req; |
467 | if (data_index >= req->nbytes) { | 437 | if (data_index >= req->nbytes) { |
468 | /* print an error message if a listen command has no data */ | ||
469 | if (((command_byte & 0x0C) == 0x08) | ||
470 | /* && (console_loglevel == 10) */ | ||
471 | && (data_index == 2)) | ||
472 | printk("MacII ADB: listen command with no data: %x!\n", | ||
473 | command_byte); | ||
474 | /* reset to shift in */ | ||
475 | via[ACR] &= ~SR_OUT; | ||
476 | x = via[SR]; | ||
477 | /* set ADB state idle - might get SRQ */ | ||
478 | via[B] = (via[B] & ~ST_MASK) | ST_IDLE; | ||
479 | |||
480 | req->sent = 1; | 438 | req->sent = 1; |
439 | macii_state = idle; | ||
481 | 440 | ||
482 | if (req->reply_expected) { | 441 | if (req->reply_expected) { |
483 | macii_state = awaiting_reply; | 442 | reading_reply = 1; |
484 | } else { | 443 | } else { |
485 | req->complete = 1; | 444 | req->complete = 1; |
486 | current_req = req->next; | 445 | current_req = req->next; |
487 | if (req->done) (*req->done)(req); | 446 | if (req->done) (*req->done)(req); |
488 | macii_state = idle; | 447 | |
489 | if (current_req || retry_req) | 448 | if (current_req) |
490 | macii_start(); | 449 | macii_start(); |
491 | else | 450 | else |
492 | macii_retransmit((command_byte & 0xF0) >> 4); | 451 | if (need_autopoll()) |
452 | macii_autopoll(autopoll_devs); | ||
453 | } | ||
454 | |||
455 | if (macii_state == idle) { | ||
456 | /* reset to shift in */ | ||
457 | via[ACR] &= ~SR_OUT; | ||
458 | x = via[SR]; | ||
459 | /* set ADB state idle - might get SRQ */ | ||
460 | via[B] = (via[B] & ~ST_MASK) | ST_IDLE; | ||
493 | } | 461 | } |
494 | } else { | 462 | } else { |
495 | via[SR] = req->data[data_index++]; | 463 | via[SR] = req->data[data_index++]; |
@@ -505,147 +473,79 @@ static irqreturn_t macii_interrupt(int irq, void *arg) | |||
505 | break; | 473 | break; |
506 | 474 | ||
507 | case reading: | 475 | case reading: |
476 | x = via[SR]; | ||
477 | BUG_ON((status & ST_MASK) == ST_CMD || | ||
478 | (status & ST_MASK) == ST_IDLE); | ||
479 | |||
480 | /* Bus timeout with SRQ sequence: | ||
481 | * data is "XX FF" while CTLR_IRQ is "L L" | ||
482 | * End of packet without SRQ sequence: | ||
483 | * data is "XX...YY 00" while CTLR_IRQ is "L...H L" | ||
484 | * End of packet SRQ sequence: | ||
485 | * data is "XX...YY 00" while CTLR_IRQ is "L...L L" | ||
486 | * (where XX is the first response byte and | ||
487 | * YY is the last byte of valid response data.) | ||
488 | */ | ||
508 | 489 | ||
509 | /* timeout / SRQ handling for II hw */ | 490 | srq_asserted = 0; |
510 | if( (first_byte == 0xFF && (reply_len-prefix_len)==2 | 491 | if (!(status & CTLR_IRQ)) { |
511 | && memcmp(reply_ptr-2,"\xFF\xFF",2)==0) || | 492 | if (x == 0xFF) { |
512 | ((reply_len-prefix_len)==3 | 493 | if (!(last_status & CTLR_IRQ)) { |
513 | && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)) | 494 | macii_state = read_done; |
514 | { | 495 | reply_len = 0; |
515 | /* | 496 | srq_asserted = 1; |
516 | * possible timeout (in fact, most probably a | 497 | } |
517 | * timeout, since SRQ can't be signaled without | 498 | } else if (x == 0x00) { |
518 | * transfer on the bus). | 499 | macii_state = read_done; |
519 | * The last three bytes seen were FF, together | 500 | if (!(last_status & CTLR_IRQ)) |
520 | * with the starting byte (in case we started | 501 | srq_asserted = 1; |
521 | * on 'idle' or 'awaiting_reply') this probably | ||
522 | * makes four. So this is mostl likely #5! | ||
523 | * The timeout signal is a pattern 1 0 1 0 0.. | ||
524 | * on /INT, meaning we missed it :-( | ||
525 | */ | ||
526 | x = via[SR]; | ||
527 | if (x != 0xFF) printk("MacII ADB: mistaken timeout/SRQ!\n"); | ||
528 | |||
529 | if ((status & TREQ) == (last_status & TREQ)) { | ||
530 | /* Not a timeout. Unsolicited SRQ? weird. */ | ||
531 | /* Terminate the SRQ packet and poll */ | ||
532 | need_poll = 1; | ||
533 | } | 502 | } |
534 | /* There's no packet to get, so reply is blank */ | 503 | } |
535 | via[B] ^= ST_MASK; | 504 | |
536 | reply_ptr -= (reply_len-prefix_len); | 505 | if (macii_state == reading) { |
537 | reply_len = prefix_len; | 506 | BUG_ON(reply_len > 15); |
538 | macii_state = read_done; | ||
539 | break; | ||
540 | } /* end timeout / SRQ handling for II hw. */ | ||
541 | |||
542 | if((reply_len-prefix_len)>3 | ||
543 | && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0) | ||
544 | { | ||
545 | /* SRQ tacked on data packet */ | ||
546 | /* Terminate the packet (SRQ never ends) */ | ||
547 | x = via[SR]; | ||
548 | macii_state = read_done; | ||
549 | reply_len -= 3; | ||
550 | reply_ptr -= 3; | ||
551 | need_poll = 1; | ||
552 | /* need to continue; next byte not seen else */ | ||
553 | } else { | ||
554 | /* Sanity check */ | ||
555 | if (reply_len > 15) reply_len = 0; | ||
556 | /* read byte */ | ||
557 | x = via[SR]; | ||
558 | *reply_ptr = x; | ||
559 | reply_ptr++; | 507 | reply_ptr++; |
508 | *reply_ptr = x; | ||
560 | reply_len++; | 509 | reply_len++; |
561 | } | 510 | } |
562 | /* The usual handshake ... */ | ||
563 | |||
564 | /* | ||
565 | * NetBSD hints that the next to last byte | ||
566 | * is sent with IRQ !! | ||
567 | * Guido found out it's the last one (0x0), | ||
568 | * but IRQ should be asserted already. | ||
569 | * Problem with timeout detection: First | ||
570 | * transition to /IRQ might be second | ||
571 | * byte of timeout packet! | ||
572 | * Timeouts are signaled by 4x FF. | ||
573 | */ | ||
574 | if (((status & TREQ) == 0) && (x == 0x00)) { /* != 0xFF */ | ||
575 | /* invert state bits, toggle ODD/EVEN */ | ||
576 | via[B] ^= ST_MASK; | ||
577 | 511 | ||
578 | /* adjust packet length */ | 512 | /* invert state bits, toggle ODD/EVEN */ |
579 | reply_len--; | 513 | via[B] ^= ST_MASK; |
580 | reply_ptr--; | ||
581 | macii_state = read_done; | ||
582 | } else { | ||
583 | /* not caught: ST_CMD */ | ||
584 | /* required for re-entry 'reading'! */ | ||
585 | if ((status & ST_MASK) == ST_IDLE) { | ||
586 | /* (in)sanity check - set even */ | ||
587 | via[B] = (via[B] & ~ST_MASK) | ST_EVEN; | ||
588 | } else { | ||
589 | /* invert state bits */ | ||
590 | via[B] ^= ST_MASK; | ||
591 | } | ||
592 | } | ||
593 | break; | 514 | break; |
594 | 515 | ||
595 | case read_done: | 516 | case read_done: |
596 | x = via[SR]; | 517 | x = via[SR]; |
518 | |||
597 | if (reading_reply) { | 519 | if (reading_reply) { |
520 | reading_reply = 0; | ||
598 | req = current_req; | 521 | req = current_req; |
599 | req->reply_len = reply_ptr - req->reply; | 522 | req->reply_len = reply_len; |
600 | req->complete = 1; | 523 | req->complete = 1; |
601 | current_req = req->next; | 524 | current_req = req->next; |
602 | if (req->done) (*req->done)(req); | 525 | if (req->done) (*req->done)(req); |
603 | } else { | 526 | } else if (reply_len && autopoll_devs) |
604 | adb_input(reply_buf, reply_ptr - reply_buf, 0); | 527 | adb_input(reply_buf, reply_len, 0); |
605 | } | ||
606 | 528 | ||
607 | /* | 529 | macii_state = idle; |
608 | * remember this device ID; it's the latest we got a | ||
609 | * reply from! | ||
610 | */ | ||
611 | last_reply = command_byte; | ||
612 | last_active = (command_byte & 0xF0) >> 4; | ||
613 | 530 | ||
614 | /* SRQ seen before, initiate poll now */ | 531 | /* SRQ seen before, initiate poll now */ |
615 | if (need_poll) { | 532 | if (srq_asserted) |
616 | macii_state = idle; | ||
617 | macii_queue_poll(); | 533 | macii_queue_poll(); |
618 | need_poll = 0; | ||
619 | break; | ||
620 | } | ||
621 | |||
622 | /* set ADB state to idle */ | ||
623 | via[B] = (via[B] & ~ST_MASK) | ST_IDLE; | ||
624 | |||
625 | /* /IRQ seen, so the ADB controller has data for us */ | ||
626 | if ((via[B] & TREQ) != 0) { | ||
627 | macii_state = reading; | ||
628 | 534 | ||
629 | reply_buf[0] = command_byte; | 535 | if (current_req) |
630 | reply_ptr = reply_buf + 1; | 536 | macii_start(); |
631 | reply_len = 1; | 537 | else |
632 | prefix_len = 1; | 538 | if (need_autopoll()) |
633 | reading_reply = 0; | 539 | macii_autopoll(autopoll_devs); |
634 | } else { | 540 | |
635 | /* no IRQ, send next packet or wait */ | 541 | if (macii_state == idle) |
636 | macii_state = idle; | 542 | via[B] = (via[B] & ~ST_MASK) | ST_IDLE; |
637 | if (current_req) | ||
638 | macii_start(); | ||
639 | else | ||
640 | macii_retransmit(last_active); | ||
641 | } | ||
642 | break; | 543 | break; |
643 | 544 | ||
644 | default: | 545 | default: |
645 | break; | 546 | break; |
646 | } | 547 | } |
647 | /* reset mutex and interrupts */ | 548 | |
648 | driver_running = 0; | 549 | entered--; |
649 | local_irq_restore(flags); | ||
650 | return IRQ_HANDLED; | 550 | return IRQ_HANDLED; |
651 | } | 551 | } |
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c index 356c7216a179..dfdf11c1eec4 100644 --- a/drivers/macintosh/via-pmu68k.c +++ b/drivers/macintosh/via-pmu68k.c | |||
@@ -111,7 +111,6 @@ static int pmu_send_request(struct adb_request *req, int sync); | |||
111 | static int pmu_autopoll(int devs); | 111 | static int pmu_autopoll(int devs); |
112 | void pmu_poll(void); | 112 | void pmu_poll(void); |
113 | static int pmu_reset_bus(void); | 113 | static int pmu_reset_bus(void); |
114 | static int pmu_queue_request(struct adb_request *req); | ||
115 | 114 | ||
116 | static void pmu_start(void); | 115 | static void pmu_start(void); |
117 | static void send_byte(int x); | 116 | static void send_byte(int x); |
@@ -475,7 +474,7 @@ pmu_request(struct adb_request *req, void (*done)(struct adb_request *), | |||
475 | return pmu_queue_request(req); | 474 | return pmu_queue_request(req); |
476 | } | 475 | } |
477 | 476 | ||
478 | static int | 477 | int |
479 | pmu_queue_request(struct adb_request *req) | 478 | pmu_queue_request(struct adb_request *req) |
480 | { | 479 | { |
481 | unsigned long flags; | 480 | unsigned long flags; |
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c index 5347a406fff7..02a0ea6e1c17 100644 --- a/drivers/media/dvb/b2c2/flexcop-i2c.c +++ b/drivers/media/dvb/b2c2/flexcop-i2c.c | |||
@@ -183,7 +183,8 @@ int flexcop_i2c_init(struct flexcop_device *fc) | |||
183 | mutex_init(&fc->i2c_mutex); | 183 | mutex_init(&fc->i2c_mutex); |
184 | 184 | ||
185 | memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter)); | 185 | memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter)); |
186 | strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",I2C_NAME_SIZE); | 186 | strncpy(fc->i2c_adap.name, "B2C2 FlexCop device", |
187 | sizeof(fc->i2c_adap.name)); | ||
187 | 188 | ||
188 | i2c_set_adapdata(&fc->i2c_adap,fc); | 189 | i2c_set_adapdata(&fc->i2c_adap,fc); |
189 | 190 | ||
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index a6cbbdd262d6..34d7abc900d7 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c | |||
@@ -26,11 +26,11 @@ | |||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/usb.h> | 28 | #include <linux/usb.h> |
29 | #include <linux/pci.h> | ||
30 | #include <linux/input.h> | 29 | #include <linux/input.h> |
31 | #include <linux/dvb/frontend.h> | 30 | #include <linux/dvb/frontend.h> |
32 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
33 | #include <linux/mm.h> | 32 | #include <linux/mm.h> |
33 | #include <asm/io.h> | ||
34 | 34 | ||
35 | #include "dmxdev.h" | 35 | #include "dmxdev.h" |
36 | #include "dvb_demux.h" | 36 | #include "dvb_demux.h" |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c index 70df31b0a8a9..088b6dee3a7f 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c | |||
@@ -19,7 +19,7 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d) | |||
19 | return -EINVAL; | 19 | return -EINVAL; |
20 | } | 20 | } |
21 | 21 | ||
22 | strncpy(d->i2c_adap.name,d->desc->name,I2C_NAME_SIZE); | 22 | strncpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name)); |
23 | #ifdef I2C_ADAP_CLASS_TV_DIGITAL | 23 | #ifdef I2C_ADAP_CLASS_TV_DIGITAL |
24 | d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL, | 24 | d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL, |
25 | #else | 25 | #else |
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c index a18c8f45a2ee..315e09e95b0c 100644 --- a/drivers/media/dvb/frontends/dibx000_common.c +++ b/drivers/media/dvb/frontends/dibx000_common.c | |||
@@ -105,9 +105,9 @@ struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enu | |||
105 | } | 105 | } |
106 | EXPORT_SYMBOL(dibx000_get_i2c_adapter); | 106 | EXPORT_SYMBOL(dibx000_get_i2c_adapter); |
107 | 107 | ||
108 | static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char name[I2C_NAME_SIZE], struct dibx000_i2c_master *mst) | 108 | static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char *name, struct dibx000_i2c_master *mst) |
109 | { | 109 | { |
110 | strncpy(i2c_adap->name, name, I2C_NAME_SIZE); | 110 | strncpy(i2c_adap->name, name, sizeof(i2c_adap->name)); |
111 | i2c_adap->class = I2C_CLASS_TV_DIGITAL, | 111 | i2c_adap->class = I2C_CLASS_TV_DIGITAL, |
112 | i2c_adap->algo = algo; | 112 | i2c_adap->algo = algo; |
113 | i2c_adap->algo_data = NULL; | 113 | i2c_adap->algo_data = NULL; |
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index 2aa9ce920607..823cd6cc471e 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/major.h> | 37 | #include <linux/major.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/mm.h> | 39 | #include <linux/mm.h> |
40 | #include <linux/pci.h> | ||
41 | #include <linux/signal.h> | 40 | #include <linux/signal.h> |
42 | #include <asm/io.h> | 41 | #include <asm/io.h> |
43 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index a3246a283aa4..05c7820fe53e 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/major.h> | 33 | #include <linux/major.h> |
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <linux/mm.h> | 35 | #include <linux/mm.h> |
36 | #include <linux/pci.h> | ||
37 | #include <linux/signal.h> | 36 | #include <linux/signal.h> |
38 | #include <asm/io.h> | 37 | #include <asm/io.h> |
39 | #include <asm/pgtable.h> | 38 | #include <asm/pgtable.h> |
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index 68673863d5c9..59a43603b5cb 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/major.h> | 37 | #include <linux/major.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/mm.h> | 39 | #include <linux/mm.h> |
40 | #include <linux/pci.h> | ||
41 | #include <linux/signal.h> | 40 | #include <linux/signal.h> |
42 | #include <asm/io.h> | 41 | #include <asm/io.h> |
43 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index 42e2299dcb22..853b1a3d6a1d 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/major.h> | 37 | #include <linux/major.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/mm.h> | 39 | #include <linux/mm.h> |
40 | #include <linux/pci.h> | ||
41 | #include <linux/signal.h> | 40 | #include <linux/signal.h> |
42 | #include <asm/io.h> | 41 | #include <asm/io.h> |
43 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c index 772fd52d551a..2e4cf1efdd21 100644 --- a/drivers/media/video/bt866.c +++ b/drivers/media/video/bt866.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/major.h> | 37 | #include <linux/major.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/mm.h> | 39 | #include <linux/mm.h> |
40 | #include <linux/pci.h> | ||
41 | #include <linux/signal.h> | 40 | #include <linux/signal.h> |
42 | #include <asm/io.h> | 41 | #include <asm/io.h> |
43 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index 88dbdddeec42..d73c86aeeaac 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/videodev2.h> | 28 | #include <linux/videodev2.h> |
29 | #include <linux/i2c.h> | ||
30 | 29 | ||
31 | #include <media/tuner.h> | 30 | #include <media/tuner.h> |
32 | #include <media/cx2341x.h> | 31 | #include <media/cx2341x.h> |
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 97ef421dd093..e627062fde3a 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <linux/slab.h> | 43 | #include <linux/slab.h> |
44 | #include <linux/mm.h> | 44 | #include <linux/mm.h> |
45 | #include <linux/poll.h> | 45 | #include <linux/poll.h> |
46 | #include <linux/pci.h> | ||
47 | #include <linux/signal.h> | 46 | #include <linux/signal.h> |
48 | #include <linux/ioport.h> | 47 | #include <linux/ioport.h> |
49 | #include <linux/types.h> | 48 | #include <linux/types.h> |
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index ed882ebc7b95..418ea8b7f85a 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -23,7 +23,6 @@ | |||
23 | 23 | ||
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/pci.h> | ||
27 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
28 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
29 | #include <linux/usb.h> | 28 | #include <linux/usb.h> |
diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h index 1231335a9f4a..50c7763d44b3 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_priv.h +++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #ifndef __LINUX_OVCAMCHIP_PRIV_H | 15 | #ifndef __LINUX_OVCAMCHIP_PRIV_H |
16 | #define __LINUX_OVCAMCHIP_PRIV_H | 16 | #define __LINUX_OVCAMCHIP_PRIV_H |
17 | 17 | ||
18 | #include <linux/i2c.h> | ||
18 | #include <media/ovcamchip.h> | 19 | #include <media/ovcamchip.h> |
19 | 20 | ||
20 | #ifdef DEBUG | 21 | #ifdef DEBUG |
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index 44dc7479119c..74839f98b7c4 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <linux/major.h> | 36 | #include <linux/major.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/mm.h> | 38 | #include <linux/mm.h> |
39 | #include <linux/pci.h> | ||
40 | #include <linux/signal.h> | 39 | #include <linux/signal.h> |
41 | #include <asm/io.h> | 40 | #include <asm/io.h> |
42 | #include <asm/pgtable.h> | 41 | #include <asm/pgtable.h> |
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c index 2ce3321ab995..87c3144ec7fc 100644 --- a/drivers/media/video/saa7114.c +++ b/drivers/media/video/saa7114.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | 40 | ||
41 | #include <linux/mm.h> | 41 | #include <linux/mm.h> |
42 | #include <linux/pci.h> | ||
43 | #include <linux/signal.h> | 42 | #include <linux/signal.h> |
44 | #include <asm/io.h> | 43 | #include <asm/io.h> |
45 | #include <asm/pgtable.h> | 44 | #include <asm/pgtable.h> |
diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index 269d7114a93a..80bf91187856 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/major.h> | 30 | #include <linux/major.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/mm.h> | 32 | #include <linux/mm.h> |
33 | #include <linux/pci.h> | ||
34 | #include <linux/signal.h> | 33 | #include <linux/signal.h> |
35 | #include <asm/io.h> | 34 | #include <asm/io.h> |
36 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index e0fdb1ab7580..339592e7722d 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/major.h> | 33 | #include <linux/major.h> |
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <linux/mm.h> | 35 | #include <linux/mm.h> |
36 | #include <linux/pci.h> | ||
37 | #include <linux/signal.h> | 36 | #include <linux/signal.h> |
38 | #include <asm/io.h> | 37 | #include <asm/io.h> |
39 | #include <asm/pgtable.h> | 38 | #include <asm/pgtable.h> |
diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c index 13f69fe6360d..51ab265d566a 100644 --- a/drivers/media/video/usbvision/usbvision-cards.c +++ b/drivers/media/video/usbvision/usbvision-cards.c | |||
@@ -24,7 +24,6 @@ | |||
24 | 24 | ||
25 | 25 | ||
26 | #include <linux/list.h> | 26 | #include <linux/list.h> |
27 | #include <linux/i2c.h> | ||
28 | #include <media/v4l2-dev.h> | 27 | #include <media/v4l2-dev.h> |
29 | #include <media/tuner.h> | 28 | #include <media/tuner.h> |
30 | #include "usbvision.h" | 29 | #include "usbvision.h" |
diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c index ca86f113f36a..276ba3c5143f 100644 --- a/drivers/misc/hdpuftrs/hdpu_cpustate.c +++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
20 | #include <linux/miscdevice.h> | 20 | #include <linux/miscdevice.h> |
21 | #include <linux/pci.h> | ||
22 | #include <linux/proc_fs.h> | 21 | #include <linux/proc_fs.h> |
23 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
24 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c index 6a51e99a8079..60c8b26f0678 100644 --- a/drivers/misc/hdpuftrs/hdpu_nexus.c +++ b/drivers/misc/hdpuftrs/hdpu_nexus.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/proc_fs.h> | 19 | #include <linux/proc_fs.h> |
20 | #include <linux/hdpu_features.h> | 20 | #include <linux/hdpu_features.h> |
21 | #include <linux/pci.h> | ||
22 | 21 | ||
23 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
24 | 23 | ||
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index 8a0c4dec6351..c73e96bfafc6 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <asm/io.h> | 13 | #include <asm/io.h> |
14 | #include <asm/uaccess.h> | 14 | #include <asm/uaccess.h> |
15 | #include <linux/miscdevice.h> | 15 | #include <linux/miscdevice.h> |
16 | #include <linux/pci.h> | ||
17 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
18 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
19 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c index 6f368aec5d5d..6413efc045e0 100644 --- a/drivers/mtd/devices/doc2001.c +++ b/drivers/mtd/devices/doc2001.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <asm/io.h> | 13 | #include <asm/io.h> |
14 | #include <asm/uaccess.h> | 14 | #include <asm/uaccess.h> |
15 | #include <linux/miscdevice.h> | 15 | #include <linux/miscdevice.h> |
16 | #include <linux/pci.h> | ||
17 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
18 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
19 | #include <linux/init.h> | 18 | #include <linux/init.h> |
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c index 88ba82df0fbb..2b30b587c6e8 100644 --- a/drivers/mtd/devices/doc2001plus.c +++ b/drivers/mtd/devices/doc2001plus.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <asm/io.h> | 17 | #include <asm/io.h> |
18 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
19 | #include <linux/miscdevice.h> | 19 | #include <linux/miscdevice.h> |
20 | #include <linux/pci.h> | ||
21 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
22 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
23 | #include <linux/init.h> | 22 | #include <linux/init.h> |
diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c index 52b5d638077f..fd8a8daba3a8 100644 --- a/drivers/mtd/devices/docecc.c +++ b/drivers/mtd/devices/docecc.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <asm/io.h> | 29 | #include <asm/io.h> |
30 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
31 | #include <linux/miscdevice.h> | 31 | #include <linux/miscdevice.h> |
32 | #include <linux/pci.h> | ||
33 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
34 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
35 | #include <linux/init.h> | 34 | #include <linux/init.h> |
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index acf3ba223298..ecac0e438f49 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <asm/io.h> | 31 | #include <asm/io.h> |
32 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
33 | #include <linux/miscdevice.h> | 33 | #include <linux/miscdevice.h> |
34 | #include <linux/pci.h> | ||
35 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
36 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
37 | #include <linux/init.h> | 36 | #include <linux/init.h> |
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index 8296305c8297..89deff007116 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/pci.h> | ||
24 | #include <linux/mtd/mtd.h> | 23 | #include <linux/mtd/mtd.h> |
25 | #include <linux/mtd/nand.h> | 24 | #include <linux/mtd/nand.h> |
26 | #include <linux/mtd/nand_ecc.h> | 25 | #include <linux/mtd/nand_ecc.h> |
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index e6ef7d7f9f14..0c9ce19ea27a 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <asm/io.h> | 17 | #include <asm/io.h> |
18 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
19 | #include <linux/miscdevice.h> | 19 | #include <linux/miscdevice.h> |
20 | #include <linux/pci.h> | ||
21 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
22 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
23 | #include <linux/init.h> | 22 | #include <linux/init.h> |
diff --git a/drivers/net/7990.c b/drivers/net/7990.c index d396f996af57..0877fc372f4b 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c | |||
@@ -565,9 +565,9 @@ int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) | |||
565 | ib->btx_ring [entry].length = (-len) | 0xf000; | 565 | ib->btx_ring [entry].length = (-len) | 0xf000; |
566 | ib->btx_ring [entry].misc = 0; | 566 | ib->btx_ring [entry].misc = 0; |
567 | 567 | ||
568 | if (skb->len < ETH_ZLEN) | 568 | if (skb->len < ETH_ZLEN) |
569 | memset((char *)&ib->tx_buf[entry][0], 0, ETH_ZLEN); | 569 | memset((void *)&ib->tx_buf[entry][0], 0, ETH_ZLEN); |
570 | skb_copy_from_linear_data(skb, &ib->tx_buf[entry][0], skblen); | 570 | skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], skblen); |
571 | 571 | ||
572 | /* Now, give the packet to the lance */ | 572 | /* Now, give the packet to the lance */ |
573 | ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN); | 573 | ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN); |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index dcdad217df51..69dba62e0bad 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -311,7 +311,7 @@ config MAC8390 | |||
311 | 311 | ||
312 | config MAC89x0 | 312 | config MAC89x0 |
313 | tristate "Macintosh CS89x0 based ethernet cards" | 313 | tristate "Macintosh CS89x0 based ethernet cards" |
314 | depends on NET_ETHERNET && MAC && BROKEN | 314 | depends on NET_ETHERNET && MAC |
315 | ---help--- | 315 | ---help--- |
316 | Support for CS89x0 chipset based Ethernet cards. If you have a | 316 | Support for CS89x0 chipset based Ethernet cards. If you have a |
317 | Nubus or LC-PDS network (Ethernet) card of this type, say Y and | 317 | Nubus or LC-PDS network (Ethernet) card of this type, say Y and |
@@ -337,8 +337,8 @@ config MACSONIC | |||
337 | be called macsonic. | 337 | be called macsonic. |
338 | 338 | ||
339 | config MACMACE | 339 | config MACMACE |
340 | bool "Macintosh (AV) onboard MACE ethernet (EXPERIMENTAL)" | 340 | bool "Macintosh (AV) onboard MACE ethernet" |
341 | depends on NET_ETHERNET && MAC && EXPERIMENTAL | 341 | depends on NET_ETHERNET && MAC |
342 | select CRC32 | 342 | select CRC32 |
343 | help | 343 | help |
344 | Support for the onboard AMD 79C940 MACE Ethernet controller used in | 344 | Support for the onboard AMD 79C940 MACE Ethernet controller used in |
diff --git a/drivers/net/Space.c b/drivers/net/Space.c index dd8ed456c8b2..1c3e293fbaf7 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c | |||
@@ -83,7 +83,6 @@ extern struct net_device *bagetlance_probe(int unit); | |||
83 | extern struct net_device *mvme147lance_probe(int unit); | 83 | extern struct net_device *mvme147lance_probe(int unit); |
84 | extern struct net_device *tc515_probe(int unit); | 84 | extern struct net_device *tc515_probe(int unit); |
85 | extern struct net_device *lance_probe(int unit); | 85 | extern struct net_device *lance_probe(int unit); |
86 | extern struct net_device *mace_probe(int unit); | ||
87 | extern struct net_device *mac8390_probe(int unit); | 86 | extern struct net_device *mac8390_probe(int unit); |
88 | extern struct net_device *mac89x0_probe(int unit); | 87 | extern struct net_device *mac89x0_probe(int unit); |
89 | extern struct net_device *mc32_probe(int unit); | 88 | extern struct net_device *mc32_probe(int unit); |
@@ -274,9 +273,6 @@ static struct devprobe2 m68k_probes[] __initdata = { | |||
274 | #ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */ | 273 | #ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */ |
275 | {mvme147lance_probe, 0}, | 274 | {mvme147lance_probe, 0}, |
276 | #endif | 275 | #endif |
277 | #ifdef CONFIG_MACMACE /* Mac 68k Quadra AV builtin Ethernet */ | ||
278 | {mace_probe, 0}, | ||
279 | #endif | ||
280 | #ifdef CONFIG_MAC8390 /* NuBus NS8390-based cards */ | 276 | #ifdef CONFIG_MAC8390 /* NuBus NS8390-based cards */ |
281 | {mac8390_probe, 0}, | 277 | {mac8390_probe, 0}, |
282 | #endif | 278 | #endif |
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index 1226cbba0450..81d5a374042a 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c | |||
@@ -562,7 +562,6 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) | |||
562 | volatile struct lance_init_block *ib = lp->init_block; | 562 | volatile struct lance_init_block *ib = lp->init_block; |
563 | int entry, skblen, len; | 563 | int entry, skblen, len; |
564 | int status = 0; | 564 | int status = 0; |
565 | static int outs; | ||
566 | unsigned long flags; | 565 | unsigned long flags; |
567 | 566 | ||
568 | skblen = skb->len; | 567 | skblen = skb->len; |
@@ -598,17 +597,16 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) | |||
598 | ib->btx_ring [entry].length = (-len) | 0xf000; | 597 | ib->btx_ring [entry].length = (-len) | 0xf000; |
599 | ib->btx_ring [entry].misc = 0; | 598 | ib->btx_ring [entry].misc = 0; |
600 | 599 | ||
601 | skb_copy_from_linear_data(skb, &ib->tx_buf [entry][0], skblen); | 600 | skb_copy_from_linear_data(skb, (void *)&ib->tx_buf [entry][0], skblen); |
602 | 601 | ||
603 | /* Clear the slack of the packet, do I need this? */ | 602 | /* Clear the slack of the packet, do I need this? */ |
604 | if (len != skblen) | 603 | if (len != skblen) |
605 | memset ((char *) &ib->tx_buf [entry][skblen], 0, len - skblen); | 604 | memset ((void *) &ib->tx_buf [entry][skblen], 0, len - skblen); |
606 | 605 | ||
607 | /* Now, give the packet to the lance */ | 606 | /* Now, give the packet to the lance */ |
608 | ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN); | 607 | ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN); |
609 | lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask; | 608 | lp->tx_new = (lp->tx_new+1) & lp->tx_ring_mod_mask; |
610 | 609 | lp->stats.tx_bytes += skblen; | |
611 | outs++; | ||
612 | 610 | ||
613 | if (TX_BUFFS_AVAIL <= 0) | 611 | if (TX_BUFFS_AVAIL <= 0) |
614 | netif_stop_queue(dev); | 612 | netif_stop_queue(dev); |
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index a0e68e718531..a241ae7855a3 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c | |||
@@ -677,6 +677,7 @@ static int ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
677 | priv->cur_tx -= TX_RING_SIZE; | 677 | priv->cur_tx -= TX_RING_SIZE; |
678 | priv->dirty_tx -= TX_RING_SIZE; | 678 | priv->dirty_tx -= TX_RING_SIZE; |
679 | } | 679 | } |
680 | priv->stats.tx_bytes += len; | ||
680 | 681 | ||
681 | /* Trigger an immediate send poll. */ | 682 | /* Trigger an immediate send poll. */ |
682 | lance->RAP = CSR0; /* PCnet-ISA Controller Status */ | 683 | lance->RAP = CSR0; /* PCnet-ISA Controller Status */ |
diff --git a/drivers/net/atl1/atl1_param.c b/drivers/net/atl1/atl1_param.c index c407214339f6..bcd0bd891722 100644 --- a/drivers/net/atl1/atl1_param.c +++ b/drivers/net/atl1/atl1_param.c | |||
@@ -22,7 +22,6 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
25 | #include <linux/pci.h> | ||
26 | #include <linux/moduleparam.h> | 25 | #include <linux/moduleparam.h> |
27 | #include "atl1.h" | 26 | #include "atl1.h" |
28 | 27 | ||
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index d10fb80e9a63..c39ab803c5d8 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include <linux/bitops.h> | 45 | #include <linux/bitops.h> |
46 | #include <linux/slab.h> | 46 | #include <linux/slab.h> |
47 | #include <linux/interrupt.h> | 47 | #include <linux/interrupt.h> |
48 | #include <linux/pci.h> | ||
49 | #include <linux/init.h> | 48 | #include <linux/init.h> |
50 | #include <linux/netdevice.h> | 49 | #include <linux/netdevice.h> |
51 | #include <linux/etherdevice.h> | 50 | #include <linux/etherdevice.h> |
diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c index e824d5d231af..88efe9731bab 100644 --- a/drivers/net/fec_8xx/fec_main.c +++ b/drivers/net/fec_8xx/fec_main.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/ioport.h> | 19 | #include <linux/ioport.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/pci.h> | ||
23 | #include <linux/init.h> | 22 | #include <linux/init.h> |
24 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
25 | #include <linux/netdevice.h> | 24 | #include <linux/netdevice.h> |
diff --git a/drivers/net/fec_8xx/fec_mii.c b/drivers/net/fec_8xx/fec_mii.c index e79700abf7b6..b3fa0d6a159c 100644 --- a/drivers/net/fec_8xx/fec_mii.c +++ b/drivers/net/fec_8xx/fec_mii.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/ioport.h> | 19 | #include <linux/ioport.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/pci.h> | ||
23 | #include <linux/init.h> | 22 | #include <linux/init.h> |
24 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
25 | #include <linux/netdevice.h> | 24 | #include <linux/netdevice.h> |
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index e2ddd617493a..a4a2a0ea43d3 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/ioport.h> | 24 | #include <linux/ioport.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/pci.h> | ||
28 | #include <linux/init.h> | 27 | #include <linux/init.h> |
29 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
30 | #include <linux/netdevice.h> | 29 | #include <linux/netdevice.h> |
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c index 8545e84fc9a0..5603121132cd 100644 --- a/drivers/net/fs_enet/mac-fcc.c +++ b/drivers/net/fs_enet/mac-fcc.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/ioport.h> | 21 | #include <linux/ioport.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/pci.h> | ||
25 | #include <linux/init.h> | 24 | #include <linux/init.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/netdevice.h> | 26 | #include <linux/netdevice.h> |
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c index cdcfb96f360f..04b4f80a1cde 100644 --- a/drivers/net/fs_enet/mac-fec.c +++ b/drivers/net/fs_enet/mac-fec.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/ioport.h> | 21 | #include <linux/ioport.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/pci.h> | ||
25 | #include <linux/init.h> | 24 | #include <linux/init.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/netdevice.h> | 26 | #include <linux/netdevice.h> |
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index 65925b5a224f..d0f28981b55a 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/ioport.h> | 21 | #include <linux/ioport.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/pci.h> | ||
25 | #include <linux/init.h> | 24 | #include <linux/init.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/netdevice.h> | 26 | #include <linux/netdevice.h> |
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c index f91447837fd4..d3840108ffbd 100644 --- a/drivers/net/fs_enet/mii-bitbang.c +++ b/drivers/net/fs_enet/mii-bitbang.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/ioport.h> | 22 | #include <linux/ioport.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/pci.h> | ||
26 | #include <linux/init.h> | 25 | #include <linux/init.h> |
27 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
28 | #include <linux/netdevice.h> | 27 | #include <linux/netdevice.h> |
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c index 235b177fb9ac..0a563a83016f 100644 --- a/drivers/net/fs_enet/mii-fec.c +++ b/drivers/net/fs_enet/mii-fec.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/ioport.h> | 21 | #include <linux/ioport.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/pci.h> | ||
25 | #include <linux/init.h> | 24 | #include <linux/init.h> |
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/netdevice.h> | 26 | #include <linux/netdevice.h> |
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c index 3d82d46f4998..50035ebd4f52 100644 --- a/drivers/net/ibm_emac/ibm_emac_core.c +++ b/drivers/net/ibm_emac/ibm_emac_core.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/types.h> | 29 | #include <linux/types.h> |
30 | #include <linux/pci.h> | ||
31 | #include <linux/netdevice.h> | 30 | #include <linux/netdevice.h> |
32 | #include <linux/etherdevice.h> | 31 | #include <linux/etherdevice.h> |
33 | #include <linux/skbuff.h> | 32 | #include <linux/skbuff.h> |
diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h index 8434d752fd81..9e04a6b3ae0d 100644 --- a/drivers/net/ixgb/ixgb_osdep.h +++ b/drivers/net/ixgb/ixgb_osdep.h | |||
@@ -34,7 +34,6 @@ | |||
34 | #define _IXGB_OSDEP_H_ | 34 | #define _IXGB_OSDEP_H_ |
35 | 35 | ||
36 | #include <linux/types.h> | 36 | #include <linux/types.h> |
37 | #include <linux/pci.h> | ||
38 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
39 | #include <asm/io.h> | 38 | #include <asm/io.h> |
40 | #include <linux/interrupt.h> | 39 | #include <linux/interrupt.h> |
diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c index d34afb52ea7f..75f6f441e876 100644 --- a/drivers/net/jazzsonic.c +++ b/drivers/net/jazzsonic.c | |||
@@ -88,6 +88,23 @@ static unsigned short known_revisions[] = | |||
88 | 0xffff /* end of list */ | 88 | 0xffff /* end of list */ |
89 | }; | 89 | }; |
90 | 90 | ||
91 | static int jazzsonic_open(struct net_device* dev) | ||
92 | { | ||
93 | if (request_irq(dev->irq, &sonic_interrupt, IRQF_DISABLED, "sonic", dev)) { | ||
94 | printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq); | ||
95 | return -EAGAIN; | ||
96 | } | ||
97 | return sonic_open(dev); | ||
98 | } | ||
99 | |||
100 | static int jazzsonic_close(struct net_device* dev) | ||
101 | { | ||
102 | int err; | ||
103 | err = sonic_close(dev); | ||
104 | free_irq(dev->irq, dev); | ||
105 | return err; | ||
106 | } | ||
107 | |||
91 | static int __init sonic_probe1(struct net_device *dev) | 108 | static int __init sonic_probe1(struct net_device *dev) |
92 | { | 109 | { |
93 | static unsigned version_printed; | 110 | static unsigned version_printed; |
@@ -169,8 +186,8 @@ static int __init sonic_probe1(struct net_device *dev) | |||
169 | lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS | 186 | lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS |
170 | * SONIC_BUS_SCALE(lp->dma_bitmode)); | 187 | * SONIC_BUS_SCALE(lp->dma_bitmode)); |
171 | 188 | ||
172 | dev->open = sonic_open; | 189 | dev->open = jazzsonic_open; |
173 | dev->stop = sonic_close; | 190 | dev->stop = jazzsonic_close; |
174 | dev->hard_start_xmit = sonic_send_packet; | 191 | dev->hard_start_xmit = sonic_send_packet; |
175 | dev->get_stats = sonic_get_stats; | 192 | dev->get_stats = sonic_get_stats; |
176 | dev->set_multicast_list = &sonic_multicast_list; | 193 | dev->set_multicast_list = &sonic_multicast_list; |
@@ -260,8 +277,6 @@ MODULE_DESCRIPTION("Jazz SONIC ethernet driver"); | |||
260 | module_param(sonic_debug, int, 0); | 277 | module_param(sonic_debug, int, 0); |
261 | MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)"); | 278 | MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)"); |
262 | 279 | ||
263 | #define SONIC_IRQ_FLAG IRQF_DISABLED | ||
264 | |||
265 | #include "sonic.c" | 280 | #include "sonic.c" |
266 | 281 | ||
267 | static int __devexit jazz_sonic_device_remove (struct platform_device *pdev) | 282 | static int __devexit jazz_sonic_device_remove (struct platform_device *pdev) |
@@ -269,11 +284,11 @@ static int __devexit jazz_sonic_device_remove (struct platform_device *pdev) | |||
269 | struct net_device *dev = platform_get_drvdata(pdev); | 284 | struct net_device *dev = platform_get_drvdata(pdev); |
270 | struct sonic_local* lp = netdev_priv(dev); | 285 | struct sonic_local* lp = netdev_priv(dev); |
271 | 286 | ||
272 | unregister_netdev (dev); | 287 | unregister_netdev(dev); |
273 | dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), | 288 | dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), |
274 | lp->descriptors, lp->descriptors_laddr); | 289 | lp->descriptors, lp->descriptors_laddr); |
275 | release_region (dev->base_addr, SONIC_MEM_SIZE); | 290 | release_region (dev->base_addr, SONIC_MEM_SIZE); |
276 | free_netdev (dev); | 291 | free_netdev(dev); |
277 | 292 | ||
278 | return 0; | 293 | return 0; |
279 | } | 294 | } |
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c index 0edcd125fd61..6b49fc4bd1a1 100644 --- a/drivers/net/lasi_82596.c +++ b/drivers/net/lasi_82596.c | |||
@@ -81,7 +81,6 @@ | |||
81 | #include <linux/etherdevice.h> | 81 | #include <linux/etherdevice.h> |
82 | #include <linux/skbuff.h> | 82 | #include <linux/skbuff.h> |
83 | #include <linux/init.h> | 83 | #include <linux/init.h> |
84 | #include <linux/pci.h> | ||
85 | #include <linux/types.h> | 84 | #include <linux/types.h> |
86 | #include <linux/bitops.h> | 85 | #include <linux/bitops.h> |
87 | 86 | ||
diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index a12bb64e3694..90b0c3ed4bb6 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c | |||
@@ -14,6 +14,8 @@ | |||
14 | /* 2001-05-15: support for Cabletron ported from old daynaport driver | 14 | /* 2001-05-15: support for Cabletron ported from old daynaport driver |
15 | * and fixed access to Sonic Sys card which masquerades as a Farallon | 15 | * and fixed access to Sonic Sys card which masquerades as a Farallon |
16 | * by rayk@knightsmanor.org */ | 16 | * by rayk@knightsmanor.org */ |
17 | /* 2002-12-30: Try to support more cards, some clues from NetBSD driver */ | ||
18 | /* 2003-12-26: Make sure Asante cards always work. */ | ||
17 | 19 | ||
18 | #include <linux/module.h> | 20 | #include <linux/module.h> |
19 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
@@ -61,25 +63,21 @@ static char version[] = | |||
61 | #define DAYNA_8390_BASE 0x80000 | 63 | #define DAYNA_8390_BASE 0x80000 |
62 | #define DAYNA_8390_MEM 0x00000 | 64 | #define DAYNA_8390_MEM 0x00000 |
63 | 65 | ||
64 | #define KINETICS_8390_BASE 0x80000 | ||
65 | #define KINETICS_8390_MEM 0x00000 | ||
66 | |||
67 | #define CABLETRON_8390_BASE 0x90000 | 66 | #define CABLETRON_8390_BASE 0x90000 |
68 | #define CABLETRON_8390_MEM 0x00000 | 67 | #define CABLETRON_8390_MEM 0x00000 |
69 | 68 | ||
69 | #define INTERLAN_8390_BASE 0xE0000 | ||
70 | #define INTERLAN_8390_MEM 0xD0000 | ||
71 | |||
70 | enum mac8390_type { | 72 | enum mac8390_type { |
71 | MAC8390_NONE = -1, | 73 | MAC8390_NONE = -1, |
72 | MAC8390_APPLE, | 74 | MAC8390_APPLE, |
73 | MAC8390_ASANTE, | 75 | MAC8390_ASANTE, |
74 | MAC8390_FARALLON, /* Apple, Asante, and Farallon are all compatible */ | 76 | MAC8390_FARALLON, |
75 | MAC8390_CABLETRON, | 77 | MAC8390_CABLETRON, |
76 | MAC8390_DAYNA, | 78 | MAC8390_DAYNA, |
77 | MAC8390_INTERLAN, | 79 | MAC8390_INTERLAN, |
78 | MAC8390_KINETICS, | 80 | MAC8390_KINETICS, |
79 | MAC8390_FOCUS, | ||
80 | MAC8390_SONICSYS, | ||
81 | MAC8390_DAYNA2, | ||
82 | MAC8390_DAYNA3, | ||
83 | }; | 81 | }; |
84 | 82 | ||
85 | static const char * cardname[] = { | 83 | static const char * cardname[] = { |
@@ -90,10 +88,6 @@ static const char * cardname[] = { | |||
90 | "dayna", | 88 | "dayna", |
91 | "interlan", | 89 | "interlan", |
92 | "kinetics", | 90 | "kinetics", |
93 | "focus", | ||
94 | "sonic systems", | ||
95 | "dayna2", | ||
96 | "dayna_lc", | ||
97 | }; | 91 | }; |
98 | 92 | ||
99 | static int word16[] = { | 93 | static int word16[] = { |
@@ -104,10 +98,6 @@ static int word16[] = { | |||
104 | 0, /* dayna */ | 98 | 0, /* dayna */ |
105 | 1, /* interlan */ | 99 | 1, /* interlan */ |
106 | 0, /* kinetics */ | 100 | 0, /* kinetics */ |
107 | 1, /* focus (??) */ | ||
108 | 1, /* sonic systems */ | ||
109 | 1, /* dayna2 */ | ||
110 | 1, /* dayna-lc */ | ||
111 | }; | 101 | }; |
112 | 102 | ||
113 | /* on which cards do we use NuBus resources? */ | 103 | /* on which cards do we use NuBus resources? */ |
@@ -119,10 +109,12 @@ static int useresources[] = { | |||
119 | 0, /* dayna */ | 109 | 0, /* dayna */ |
120 | 0, /* interlan */ | 110 | 0, /* interlan */ |
121 | 0, /* kinetics */ | 111 | 0, /* kinetics */ |
122 | 0, /* focus (??) */ | 112 | }; |
123 | 1, /* sonic systems */ | 113 | |
124 | 1, /* dayna2 */ | 114 | enum mac8390_access { |
125 | 1, /* dayna-lc */ | 115 | ACCESS_UNKNOWN = 0, |
116 | ACCESS_32, | ||
117 | ACCESS_16, | ||
126 | }; | 118 | }; |
127 | 119 | ||
128 | extern enum mac8390_type mac8390_ident(struct nubus_dev * dev); | 120 | extern enum mac8390_type mac8390_ident(struct nubus_dev * dev); |
@@ -134,8 +126,9 @@ static int mac8390_initdev(struct net_device * dev, struct nubus_dev * ndev, | |||
134 | static int mac8390_open(struct net_device * dev); | 126 | static int mac8390_open(struct net_device * dev); |
135 | static int mac8390_close(struct net_device * dev); | 127 | static int mac8390_close(struct net_device * dev); |
136 | static void mac8390_no_reset(struct net_device *dev); | 128 | static void mac8390_no_reset(struct net_device *dev); |
129 | static void interlan_reset(struct net_device *dev); | ||
137 | 130 | ||
138 | /* Sane (32-bit chunk memory read/write) - Apple/Asante/Farallon do this*/ | 131 | /* Sane (32-bit chunk memory read/write) - Some Farallon and Apple do this*/ |
139 | static void sane_get_8390_hdr(struct net_device *dev, | 132 | static void sane_get_8390_hdr(struct net_device *dev, |
140 | struct e8390_pkt_hdr *hdr, int ring_page); | 133 | struct e8390_pkt_hdr *hdr, int ring_page); |
141 | static void sane_block_input(struct net_device * dev, int count, | 134 | static void sane_block_input(struct net_device * dev, int count, |
@@ -172,23 +165,93 @@ static void word_memcpy_fromcard(void *tp, const void *fp, int count); | |||
172 | 165 | ||
173 | enum mac8390_type __init mac8390_ident(struct nubus_dev * dev) | 166 | enum mac8390_type __init mac8390_ident(struct nubus_dev * dev) |
174 | { | 167 | { |
175 | if (dev->dr_sw == NUBUS_DRSW_ASANTE) | 168 | switch (dev->dr_sw) { |
176 | return MAC8390_ASANTE; | 169 | case NUBUS_DRSW_3COM: |
177 | if (dev->dr_sw == NUBUS_DRSW_FARALLON) | 170 | switch (dev->dr_hw) { |
178 | return MAC8390_FARALLON; | 171 | case NUBUS_DRHW_APPLE_SONIC_NB: |
179 | if (dev->dr_sw == NUBUS_DRSW_KINETICS) | 172 | case NUBUS_DRHW_APPLE_SONIC_LC: |
180 | return MAC8390_KINETICS; | 173 | case NUBUS_DRHW_SONNET: |
181 | if (dev->dr_sw == NUBUS_DRSW_DAYNA) | 174 | return MAC8390_NONE; |
182 | return MAC8390_DAYNA; | 175 | break; |
183 | if (dev->dr_sw == NUBUS_DRSW_DAYNA2) | 176 | default: |
184 | return MAC8390_DAYNA2; | 177 | return MAC8390_APPLE; |
185 | if (dev->dr_sw == NUBUS_DRSW_DAYNA_LC) | 178 | break; |
186 | return MAC8390_DAYNA3; | 179 | } |
187 | if (dev->dr_hw == NUBUS_DRHW_CABLETRON) | 180 | break; |
188 | return MAC8390_CABLETRON; | 181 | |
182 | case NUBUS_DRSW_APPLE: | ||
183 | switch (dev->dr_hw) { | ||
184 | case NUBUS_DRHW_ASANTE_LC: | ||
185 | return MAC8390_NONE; | ||
186 | break; | ||
187 | case NUBUS_DRHW_CABLETRON: | ||
188 | return MAC8390_CABLETRON; | ||
189 | break; | ||
190 | default: | ||
191 | return MAC8390_APPLE; | ||
192 | break; | ||
193 | } | ||
194 | break; | ||
195 | |||
196 | case NUBUS_DRSW_ASANTE: | ||
197 | return MAC8390_ASANTE; | ||
198 | break; | ||
199 | |||
200 | case NUBUS_DRSW_TECHWORKS: | ||
201 | case NUBUS_DRSW_DAYNA2: | ||
202 | case NUBUS_DRSW_DAYNA_LC: | ||
203 | if (dev->dr_hw == NUBUS_DRHW_CABLETRON) | ||
204 | return MAC8390_CABLETRON; | ||
205 | else | ||
206 | return MAC8390_APPLE; | ||
207 | break; | ||
208 | |||
209 | case NUBUS_DRSW_FARALLON: | ||
210 | return MAC8390_FARALLON; | ||
211 | break; | ||
212 | |||
213 | case NUBUS_DRSW_KINETICS: | ||
214 | switch (dev->dr_hw) { | ||
215 | case NUBUS_DRHW_INTERLAN: | ||
216 | return MAC8390_INTERLAN; | ||
217 | break; | ||
218 | default: | ||
219 | return MAC8390_KINETICS; | ||
220 | break; | ||
221 | } | ||
222 | break; | ||
223 | |||
224 | case NUBUS_DRSW_DAYNA: | ||
225 | // These correspond to Dayna Sonic cards | ||
226 | // which use the macsonic driver | ||
227 | if (dev->dr_hw == NUBUS_DRHW_SMC9194 || | ||
228 | dev->dr_hw == NUBUS_DRHW_INTERLAN ) | ||
229 | return MAC8390_NONE; | ||
230 | else | ||
231 | return MAC8390_DAYNA; | ||
232 | break; | ||
233 | } | ||
189 | return MAC8390_NONE; | 234 | return MAC8390_NONE; |
190 | } | 235 | } |
191 | 236 | ||
237 | enum mac8390_access __init mac8390_testio(volatile unsigned long membase) | ||
238 | { | ||
239 | unsigned long outdata = 0xA5A0B5B0; | ||
240 | unsigned long indata = 0x00000000; | ||
241 | /* Try writing 32 bits */ | ||
242 | memcpy((char *)membase, (char *)&outdata, 4); | ||
243 | /* Now compare them */ | ||
244 | if (memcmp((char *)&outdata, (char *)membase, 4) == 0) | ||
245 | return ACCESS_32; | ||
246 | /* Write 16 bit output */ | ||
247 | word_memcpy_tocard((char *)membase, (char *)&outdata, 4); | ||
248 | /* Now read it back */ | ||
249 | word_memcpy_fromcard((char *)&indata, (char *)membase, 4); | ||
250 | if (outdata == indata) | ||
251 | return ACCESS_16; | ||
252 | return ACCESS_UNKNOWN; | ||
253 | } | ||
254 | |||
192 | int __init mac8390_memsize(unsigned long membase) | 255 | int __init mac8390_memsize(unsigned long membase) |
193 | { | 256 | { |
194 | unsigned long flags; | 257 | unsigned long flags; |
@@ -287,14 +350,6 @@ struct net_device * __init mac8390_probe(int unit) | |||
287 | continue; | 350 | continue; |
288 | } else { | 351 | } else { |
289 | nubus_get_rsrc_mem(dev->dev_addr, &ent, 6); | 352 | nubus_get_rsrc_mem(dev->dev_addr, &ent, 6); |
290 | /* Some Sonic Sys cards masquerade as Farallon */ | ||
291 | if (cardtype == MAC8390_FARALLON && | ||
292 | dev->dev_addr[0] == 0x0 && | ||
293 | dev->dev_addr[1] == 0x40 && | ||
294 | dev->dev_addr[2] == 0x10) { | ||
295 | /* This is really Sonic Sys card */ | ||
296 | cardtype = MAC8390_SONICSYS; | ||
297 | } | ||
298 | } | 353 | } |
299 | 354 | ||
300 | if (useresources[cardtype] == 1) { | 355 | if (useresources[cardtype] == 1) { |
@@ -334,6 +389,17 @@ struct net_device * __init mac8390_probe(int unit) | |||
334 | dev->mem_start + | 389 | dev->mem_start + |
335 | mac8390_memsize(dev->mem_start); | 390 | mac8390_memsize(dev->mem_start); |
336 | break; | 391 | break; |
392 | case MAC8390_INTERLAN: | ||
393 | dev->base_addr = | ||
394 | (int)(ndev->board->slot_addr + | ||
395 | INTERLAN_8390_BASE); | ||
396 | dev->mem_start = | ||
397 | (int)(ndev->board->slot_addr + | ||
398 | INTERLAN_8390_MEM); | ||
399 | dev->mem_end = | ||
400 | dev->mem_start + | ||
401 | mac8390_memsize(dev->mem_start); | ||
402 | break; | ||
337 | case MAC8390_CABLETRON: | 403 | case MAC8390_CABLETRON: |
338 | dev->base_addr = | 404 | dev->base_addr = |
339 | (int)(ndev->board->slot_addr + | 405 | (int)(ndev->board->slot_addr + |
@@ -356,8 +422,8 @@ struct net_device * __init mac8390_probe(int unit) | |||
356 | 422 | ||
357 | default: | 423 | default: |
358 | printk(KERN_ERR "Card type %s is" | 424 | printk(KERN_ERR "Card type %s is" |
359 | " unsupported, sorry\n", | 425 | " unsupported, sorry\n", |
360 | cardname[cardtype]); | 426 | ndev->board->name); |
361 | continue; | 427 | continue; |
362 | } | 428 | } |
363 | } | 429 | } |
@@ -438,7 +504,7 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd | |||
438 | 24, 26, 28, 30 | 504 | 24, 26, 28, 30 |
439 | }; | 505 | }; |
440 | 506 | ||
441 | int access_bitmode; | 507 | int access_bitmode = 0; |
442 | 508 | ||
443 | /* Now fill in our stuff */ | 509 | /* Now fill in our stuff */ |
444 | dev->open = &mac8390_open; | 510 | dev->open = &mac8390_open; |
@@ -468,29 +534,47 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd | |||
468 | 534 | ||
469 | /* Fill in model-specific information and functions */ | 535 | /* Fill in model-specific information and functions */ |
470 | switch(type) { | 536 | switch(type) { |
471 | case MAC8390_SONICSYS: | ||
472 | /* 16 bit card, register map is reversed */ | ||
473 | ei_status.reset_8390 = &mac8390_no_reset; | ||
474 | ei_status.block_input = &slow_sane_block_input; | ||
475 | ei_status.block_output = &slow_sane_block_output; | ||
476 | ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; | ||
477 | ei_status.reg_offset = back4_offsets; | ||
478 | access_bitmode = 0; | ||
479 | break; | ||
480 | case MAC8390_FARALLON: | 537 | case MAC8390_FARALLON: |
481 | case MAC8390_APPLE: | 538 | case MAC8390_APPLE: |
539 | switch(mac8390_testio(dev->mem_start)) { | ||
540 | case ACCESS_UNKNOWN: | ||
541 | printk("Don't know how to access card memory!\n"); | ||
542 | return -ENODEV; | ||
543 | break; | ||
544 | |||
545 | case ACCESS_16: | ||
546 | /* 16 bit card, register map is reversed */ | ||
547 | ei_status.reset_8390 = &mac8390_no_reset; | ||
548 | ei_status.block_input = &slow_sane_block_input; | ||
549 | ei_status.block_output = &slow_sane_block_output; | ||
550 | ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; | ||
551 | ei_status.reg_offset = back4_offsets; | ||
552 | break; | ||
553 | |||
554 | case ACCESS_32: | ||
555 | /* 32 bit card, register map is reversed */ | ||
556 | ei_status.reset_8390 = &mac8390_no_reset; | ||
557 | ei_status.block_input = &sane_block_input; | ||
558 | ei_status.block_output = &sane_block_output; | ||
559 | ei_status.get_8390_hdr = &sane_get_8390_hdr; | ||
560 | ei_status.reg_offset = back4_offsets; | ||
561 | access_bitmode = 1; | ||
562 | break; | ||
563 | } | ||
564 | break; | ||
565 | |||
482 | case MAC8390_ASANTE: | 566 | case MAC8390_ASANTE: |
483 | case MAC8390_DAYNA2: | 567 | /* Some Asante cards pass the 32 bit test |
484 | case MAC8390_DAYNA3: | 568 | * but overwrite system memory when run at 32 bit. |
485 | /* 32 bit card, register map is reversed */ | 569 | * so we run them all at 16 bit. |
486 | /* sane */ | 570 | */ |
487 | ei_status.reset_8390 = &mac8390_no_reset; | 571 | ei_status.reset_8390 = &mac8390_no_reset; |
488 | ei_status.block_input = &sane_block_input; | 572 | ei_status.block_input = &slow_sane_block_input; |
489 | ei_status.block_output = &sane_block_output; | 573 | ei_status.block_output = &slow_sane_block_output; |
490 | ei_status.get_8390_hdr = &sane_get_8390_hdr; | 574 | ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; |
491 | ei_status.reg_offset = back4_offsets; | 575 | ei_status.reg_offset = back4_offsets; |
492 | access_bitmode = 1; | ||
493 | break; | 576 | break; |
577 | |||
494 | case MAC8390_CABLETRON: | 578 | case MAC8390_CABLETRON: |
495 | /* 16 bit card, register map is short forward */ | 579 | /* 16 bit card, register map is short forward */ |
496 | ei_status.reset_8390 = &mac8390_no_reset; | 580 | ei_status.reset_8390 = &mac8390_no_reset; |
@@ -498,21 +582,30 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd | |||
498 | ei_status.block_output = &slow_sane_block_output; | 582 | ei_status.block_output = &slow_sane_block_output; |
499 | ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; | 583 | ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; |
500 | ei_status.reg_offset = fwrd2_offsets; | 584 | ei_status.reg_offset = fwrd2_offsets; |
501 | access_bitmode = 0; | ||
502 | break; | 585 | break; |
586 | |||
503 | case MAC8390_DAYNA: | 587 | case MAC8390_DAYNA: |
504 | case MAC8390_KINETICS: | 588 | case MAC8390_KINETICS: |
505 | /* 16 bit memory */ | 589 | /* 16 bit memory, register map is forward */ |
506 | /* dayna and similar */ | 590 | /* dayna and similar */ |
507 | ei_status.reset_8390 = &mac8390_no_reset; | 591 | ei_status.reset_8390 = &mac8390_no_reset; |
508 | ei_status.block_input = &dayna_block_input; | 592 | ei_status.block_input = &dayna_block_input; |
509 | ei_status.block_output = &dayna_block_output; | 593 | ei_status.block_output = &dayna_block_output; |
510 | ei_status.get_8390_hdr = &dayna_get_8390_hdr; | 594 | ei_status.get_8390_hdr = &dayna_get_8390_hdr; |
511 | ei_status.reg_offset = fwrd4_offsets; | 595 | ei_status.reg_offset = fwrd4_offsets; |
512 | access_bitmode = 0; | ||
513 | break; | 596 | break; |
597 | |||
598 | case MAC8390_INTERLAN: | ||
599 | /* 16 bit memory, register map is forward */ | ||
600 | ei_status.reset_8390 = &interlan_reset; | ||
601 | ei_status.block_input = &slow_sane_block_input; | ||
602 | ei_status.block_output = &slow_sane_block_output; | ||
603 | ei_status.get_8390_hdr = &slow_sane_get_8390_hdr; | ||
604 | ei_status.reg_offset = fwrd4_offsets; | ||
605 | break; | ||
606 | |||
514 | default: | 607 | default: |
515 | printk(KERN_ERR "Card type %s is unsupported, sorry\n", cardname[type]); | 608 | printk(KERN_ERR "Card type %s is unsupported, sorry\n", ndev->board->name); |
516 | return -ENODEV; | 609 | return -ENODEV; |
517 | } | 610 | } |
518 | 611 | ||
@@ -530,9 +623,9 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd | |||
530 | printk(":"); | 623 | printk(":"); |
531 | } | 624 | } |
532 | } | 625 | } |
533 | printk(" IRQ %d, shared memory at %#lx-%#lx, %d-bit access.\n", | 626 | printk(" IRQ %d, %d KB shared memory at %#lx, %d-bit access.\n", |
534 | dev->irq, dev->mem_start, dev->mem_end-1, | 627 | dev->irq, (int)((dev->mem_end - dev->mem_start)/0x1000) * 4, |
535 | access_bitmode?32:16); | 628 | dev->mem_start, access_bitmode?32:16); |
536 | return 0; | 629 | return 0; |
537 | } | 630 | } |
538 | 631 | ||
@@ -561,6 +654,18 @@ static void mac8390_no_reset(struct net_device *dev) | |||
561 | return; | 654 | return; |
562 | } | 655 | } |
563 | 656 | ||
657 | static void interlan_reset(struct net_device *dev) | ||
658 | { | ||
659 | unsigned char *target=nubus_slot_addr(IRQ2SLOT(dev->irq)); | ||
660 | if (ei_debug > 1) | ||
661 | printk("Need to reset the NS8390 t=%lu...", jiffies); | ||
662 | ei_status.txing = 0; | ||
663 | target[0xC0000] = 0; | ||
664 | if (ei_debug > 1) | ||
665 | printk("reset complete\n"); | ||
666 | return; | ||
667 | } | ||
668 | |||
564 | /* dayna_memcpy_fromio/dayna_memcpy_toio */ | 669 | /* dayna_memcpy_fromio/dayna_memcpy_toio */ |
565 | /* directly from daynaport.c by Alan Cox */ | 670 | /* directly from daynaport.c by Alan Cox */ |
566 | static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count) | 671 | static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count) |
diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c index 90e695d53266..26a3b45a4a34 100644 --- a/drivers/net/mac89x0.c +++ b/drivers/net/mac89x0.c | |||
@@ -128,7 +128,7 @@ struct net_local { | |||
128 | extern void reset_chip(struct net_device *dev); | 128 | extern void reset_chip(struct net_device *dev); |
129 | #endif | 129 | #endif |
130 | static int net_open(struct net_device *dev); | 130 | static int net_open(struct net_device *dev); |
131 | static int net_send_packet(struct sk_buff *skb, struct net_device *dev); | 131 | static int net_send_packet(struct sk_buff *skb, struct net_device *dev); |
132 | static irqreturn_t net_interrupt(int irq, void *dev_id); | 132 | static irqreturn_t net_interrupt(int irq, void *dev_id); |
133 | static void set_multicast_list(struct net_device *dev); | 133 | static void set_multicast_list(struct net_device *dev); |
134 | static void net_rx(struct net_device *dev); | 134 | static void net_rx(struct net_device *dev); |
@@ -374,56 +374,39 @@ net_open(struct net_device *dev) | |||
374 | static int | 374 | static int |
375 | net_send_packet(struct sk_buff *skb, struct net_device *dev) | 375 | net_send_packet(struct sk_buff *skb, struct net_device *dev) |
376 | { | 376 | { |
377 | if (dev->tbusy) { | 377 | struct net_local *lp = netdev_priv(dev); |
378 | /* If we get here, some higher level has decided we are broken. | 378 | unsigned long flags; |
379 | There should really be a "kick me" function call instead. */ | ||
380 | int tickssofar = jiffies - dev->trans_start; | ||
381 | if (tickssofar < 5) | ||
382 | return 1; | ||
383 | if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name, | ||
384 | tx_done(dev) ? "IRQ conflict" : "network cable problem"); | ||
385 | /* Try to restart the adaptor. */ | ||
386 | dev->tbusy=0; | ||
387 | dev->trans_start = jiffies; | ||
388 | } | ||
389 | |||
390 | /* Block a timer-based transmit from overlapping. This could better be | ||
391 | done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ | ||
392 | if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) | ||
393 | printk("%s: Transmitter access conflict.\n", dev->name); | ||
394 | else { | ||
395 | struct net_local *lp = netdev_priv(dev); | ||
396 | unsigned long flags; | ||
397 | |||
398 | if (net_debug > 3) | ||
399 | printk("%s: sent %d byte packet of type %x\n", | ||
400 | dev->name, skb->len, | ||
401 | (skb->data[ETH_ALEN+ETH_ALEN] << 8) | ||
402 | | skb->data[ETH_ALEN+ETH_ALEN+1]); | ||
403 | |||
404 | /* keep the upload from being interrupted, since we | ||
405 | ask the chip to start transmitting before the | ||
406 | whole packet has been completely uploaded. */ | ||
407 | local_irq_save(flags); | ||
408 | 379 | ||
409 | /* initiate a transmit sequence */ | 380 | if (net_debug > 3) |
410 | writereg(dev, PP_TxCMD, lp->send_cmd); | 381 | printk("%s: sent %d byte packet of type %x\n", |
411 | writereg(dev, PP_TxLength, skb->len); | 382 | dev->name, skb->len, |
383 | (skb->data[ETH_ALEN+ETH_ALEN] << 8) | ||
384 | | skb->data[ETH_ALEN+ETH_ALEN+1]); | ||
412 | 385 | ||
413 | /* Test to see if the chip has allocated memory for the packet */ | 386 | /* keep the upload from being interrupted, since we |
414 | if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) { | 387 | ask the chip to start transmitting before the |
415 | /* Gasp! It hasn't. But that shouldn't happen since | 388 | whole packet has been completely uploaded. */ |
416 | we're waiting for TxOk, so return 1 and requeue this packet. */ | 389 | local_irq_save(flags); |
417 | local_irq_restore(flags); | 390 | netif_stop_queue(dev); |
418 | return 1; | ||
419 | } | ||
420 | 391 | ||
421 | /* Write the contents of the packet */ | 392 | /* initiate a transmit sequence */ |
422 | memcpy_toio(dev->mem_start + PP_TxFrame, skb->data, skb->len+1); | 393 | writereg(dev, PP_TxCMD, lp->send_cmd); |
394 | writereg(dev, PP_TxLength, skb->len); | ||
423 | 395 | ||
396 | /* Test to see if the chip has allocated memory for the packet */ | ||
397 | if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) { | ||
398 | /* Gasp! It hasn't. But that shouldn't happen since | ||
399 | we're waiting for TxOk, so return 1 and requeue this packet. */ | ||
424 | local_irq_restore(flags); | 400 | local_irq_restore(flags); |
425 | dev->trans_start = jiffies; | 401 | return 1; |
426 | } | 402 | } |
403 | |||
404 | /* Write the contents of the packet */ | ||
405 | skb_copy_from_linear_data(skb, (void *)(dev->mem_start + PP_TxFrame), | ||
406 | skb->len+1); | ||
407 | |||
408 | local_irq_restore(flags); | ||
409 | dev->trans_start = jiffies; | ||
427 | dev_kfree_skb (skb); | 410 | dev_kfree_skb (skb); |
428 | 411 | ||
429 | return 0; | 412 | return 0; |
@@ -441,9 +424,6 @@ static irqreturn_t net_interrupt(int irq, void *dev_id) | |||
441 | printk ("net_interrupt(): irq %d for unknown device.\n", irq); | 424 | printk ("net_interrupt(): irq %d for unknown device.\n", irq); |
442 | return IRQ_NONE; | 425 | return IRQ_NONE; |
443 | } | 426 | } |
444 | if (dev->interrupt) | ||
445 | printk("%s: Re-entering the interrupt handler.\n", dev->name); | ||
446 | dev->interrupt = 1; | ||
447 | 427 | ||
448 | ioaddr = dev->base_addr; | 428 | ioaddr = dev->base_addr; |
449 | lp = netdev_priv(dev); | 429 | lp = netdev_priv(dev); |
@@ -464,8 +444,7 @@ static irqreturn_t net_interrupt(int irq, void *dev_id) | |||
464 | break; | 444 | break; |
465 | case ISQ_TRANSMITTER_EVENT: | 445 | case ISQ_TRANSMITTER_EVENT: |
466 | lp->stats.tx_packets++; | 446 | lp->stats.tx_packets++; |
467 | dev->tbusy = 0; | 447 | netif_wake_queue(dev); |
468 | mark_bh(NET_BH); /* Inform upper layers. */ | ||
469 | if ((status & TX_OK) == 0) lp->stats.tx_errors++; | 448 | if ((status & TX_OK) == 0) lp->stats.tx_errors++; |
470 | if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++; | 449 | if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++; |
471 | if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++; | 450 | if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++; |
@@ -479,8 +458,7 @@ static irqreturn_t net_interrupt(int irq, void *dev_id) | |||
479 | That shouldn't happen since we only ever | 458 | That shouldn't happen since we only ever |
480 | load one packet. Shrug. Do the right | 459 | load one packet. Shrug. Do the right |
481 | thing anyway. */ | 460 | thing anyway. */ |
482 | dev->tbusy = 0; | 461 | netif_wake_queue(dev); |
483 | mark_bh(NET_BH); /* Inform upper layers. */ | ||
484 | } | 462 | } |
485 | if (status & TX_UNDERRUN) { | 463 | if (status & TX_UNDERRUN) { |
486 | if (net_debug > 0) printk("%s: transmit underrun\n", dev->name); | 464 | if (net_debug > 0) printk("%s: transmit underrun\n", dev->name); |
@@ -497,7 +475,6 @@ static irqreturn_t net_interrupt(int irq, void *dev_id) | |||
497 | break; | 475 | break; |
498 | } | 476 | } |
499 | } | 477 | } |
500 | dev->interrupt = 0; | ||
501 | return IRQ_HANDLED; | 478 | return IRQ_HANDLED; |
502 | } | 479 | } |
503 | 480 | ||
@@ -531,7 +508,8 @@ net_rx(struct net_device *dev) | |||
531 | } | 508 | } |
532 | skb_put(skb, length); | 509 | skb_put(skb, length); |
533 | 510 | ||
534 | memcpy_fromio(skb->data, dev->mem_start + PP_RxFrame, length); | 511 | skb_copy_to_linear_data(skb, (void *)(dev->mem_start + PP_RxFrame), |
512 | length); | ||
535 | 513 | ||
536 | if (net_debug > 3)printk("%s: received %d byte packet of type %x\n", | 514 | if (net_debug > 3)printk("%s: received %d byte packet of type %x\n", |
537 | dev->name, length, | 515 | dev->name, length, |
@@ -610,8 +588,6 @@ static void set_multicast_list(struct net_device *dev) | |||
610 | static int set_mac_address(struct net_device *dev, void *addr) | 588 | static int set_mac_address(struct net_device *dev, void *addr) |
611 | { | 589 | { |
612 | int i; | 590 | int i; |
613 | if (dev->start) | ||
614 | return -EBUSY; | ||
615 | printk("%s: Setting MAC address to ", dev->name); | 591 | printk("%s: Setting MAC address to ", dev->name); |
616 | for (i = 0; i < 6; i++) | 592 | for (i = 0; i < 6; i++) |
617 | printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]); | 593 | printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]); |
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c index 27911c07558d..fef3193121f9 100644 --- a/drivers/net/macmace.c +++ b/drivers/net/macmace.c | |||
@@ -12,6 +12,11 @@ | |||
12 | * Copyright (C) 1998 Alan Cox <alan@redhat.com> | 12 | * Copyright (C) 1998 Alan Cox <alan@redhat.com> |
13 | * | 13 | * |
14 | * Modified heavily by Joshua M. Thompson based on Dave Huang's NetBSD driver | 14 | * Modified heavily by Joshua M. Thompson based on Dave Huang's NetBSD driver |
15 | * | ||
16 | * Copyright (C) 2007 Finn Thain | ||
17 | * | ||
18 | * Converted to DMA API, converted to unified driver model, | ||
19 | * sync'd some routines with mace.c and fixed various bugs. | ||
15 | */ | 20 | */ |
16 | 21 | ||
17 | 22 | ||
@@ -23,8 +28,9 @@ | |||
23 | #include <linux/string.h> | 28 | #include <linux/string.h> |
24 | #include <linux/crc32.h> | 29 | #include <linux/crc32.h> |
25 | #include <linux/bitrev.h> | 30 | #include <linux/bitrev.h> |
31 | #include <linux/dma-mapping.h> | ||
32 | #include <linux/platform_device.h> | ||
26 | #include <asm/io.h> | 33 | #include <asm/io.h> |
27 | #include <asm/pgtable.h> | ||
28 | #include <asm/irq.h> | 34 | #include <asm/irq.h> |
29 | #include <asm/macintosh.h> | 35 | #include <asm/macintosh.h> |
30 | #include <asm/macints.h> | 36 | #include <asm/macints.h> |
@@ -32,13 +38,20 @@ | |||
32 | #include <asm/page.h> | 38 | #include <asm/page.h> |
33 | #include "mace.h" | 39 | #include "mace.h" |
34 | 40 | ||
35 | #define N_TX_RING 1 | 41 | static char mac_mace_string[] = "macmace"; |
36 | #define N_RX_RING 8 | 42 | static struct platform_device *mac_mace_device; |
37 | #define N_RX_PAGES ((N_RX_RING * 0x0800 + PAGE_SIZE - 1) / PAGE_SIZE) | 43 | |
44 | #define N_TX_BUFF_ORDER 0 | ||
45 | #define N_TX_RING (1 << N_TX_BUFF_ORDER) | ||
46 | #define N_RX_BUFF_ORDER 3 | ||
47 | #define N_RX_RING (1 << N_RX_BUFF_ORDER) | ||
48 | |||
38 | #define TX_TIMEOUT HZ | 49 | #define TX_TIMEOUT HZ |
39 | 50 | ||
40 | /* Bits in transmit DMA status */ | 51 | #define MACE_BUFF_SIZE 0x800 |
41 | #define TX_DMA_ERR 0x80 | 52 | |
53 | /* Chip rev needs workaround on HW & multicast addr change */ | ||
54 | #define BROKEN_ADDRCHG_REV 0x0941 | ||
42 | 55 | ||
43 | /* The MACE is simply wired down on a Mac68K box */ | 56 | /* The MACE is simply wired down on a Mac68K box */ |
44 | 57 | ||
@@ -47,40 +60,46 @@ | |||
47 | 60 | ||
48 | struct mace_data { | 61 | struct mace_data { |
49 | volatile struct mace *mace; | 62 | volatile struct mace *mace; |
50 | volatile unsigned char *tx_ring; | 63 | unsigned char *tx_ring; |
51 | volatile unsigned char *tx_ring_phys; | 64 | dma_addr_t tx_ring_phys; |
52 | volatile unsigned char *rx_ring; | 65 | unsigned char *rx_ring; |
53 | volatile unsigned char *rx_ring_phys; | 66 | dma_addr_t rx_ring_phys; |
54 | int dma_intr; | 67 | int dma_intr; |
55 | struct net_device_stats stats; | 68 | struct net_device_stats stats; |
56 | int rx_slot, rx_tail; | 69 | int rx_slot, rx_tail; |
57 | int tx_slot, tx_sloti, tx_count; | 70 | int tx_slot, tx_sloti, tx_count; |
71 | int chipid; | ||
72 | struct device *device; | ||
58 | }; | 73 | }; |
59 | 74 | ||
60 | struct mace_frame { | 75 | struct mace_frame { |
61 | u16 len; | 76 | u8 rcvcnt; |
62 | u16 status; | 77 | u8 pad1; |
63 | u16 rntpc; | 78 | u8 rcvsts; |
64 | u16 rcvcc; | 79 | u8 pad2; |
65 | u32 pad1; | 80 | u8 rntpc; |
66 | u32 pad2; | 81 | u8 pad3; |
82 | u8 rcvcc; | ||
83 | u8 pad4; | ||
84 | u32 pad5; | ||
85 | u32 pad6; | ||
67 | u8 data[1]; | 86 | u8 data[1]; |
68 | /* And frame continues.. */ | 87 | /* And frame continues.. */ |
69 | }; | 88 | }; |
70 | 89 | ||
71 | #define PRIV_BYTES sizeof(struct mace_data) | 90 | #define PRIV_BYTES sizeof(struct mace_data) |
72 | 91 | ||
73 | extern void psc_debug_dump(void); | ||
74 | |||
75 | static int mace_open(struct net_device *dev); | 92 | static int mace_open(struct net_device *dev); |
76 | static int mace_close(struct net_device *dev); | 93 | static int mace_close(struct net_device *dev); |
77 | static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev); | 94 | static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev); |
78 | static struct net_device_stats *mace_stats(struct net_device *dev); | 95 | static struct net_device_stats *mace_stats(struct net_device *dev); |
79 | static void mace_set_multicast(struct net_device *dev); | 96 | static void mace_set_multicast(struct net_device *dev); |
80 | static int mace_set_address(struct net_device *dev, void *addr); | 97 | static int mace_set_address(struct net_device *dev, void *addr); |
98 | static void mace_reset(struct net_device *dev); | ||
81 | static irqreturn_t mace_interrupt(int irq, void *dev_id); | 99 | static irqreturn_t mace_interrupt(int irq, void *dev_id); |
82 | static irqreturn_t mace_dma_intr(int irq, void *dev_id); | 100 | static irqreturn_t mace_dma_intr(int irq, void *dev_id); |
83 | static void mace_tx_timeout(struct net_device *dev); | 101 | static void mace_tx_timeout(struct net_device *dev); |
102 | static void __mace_set_address(struct net_device *dev, void *addr); | ||
84 | 103 | ||
85 | /* | 104 | /* |
86 | * Load a receive DMA channel with a base address and ring length | 105 | * Load a receive DMA channel with a base address and ring length |
@@ -88,7 +107,7 @@ static void mace_tx_timeout(struct net_device *dev); | |||
88 | 107 | ||
89 | static void mace_load_rxdma_base(struct net_device *dev, int set) | 108 | static void mace_load_rxdma_base(struct net_device *dev, int set) |
90 | { | 109 | { |
91 | struct mace_data *mp = (struct mace_data *) dev->priv; | 110 | struct mace_data *mp = netdev_priv(dev); |
92 | 111 | ||
93 | psc_write_word(PSC_ENETRD_CMD + set, 0x0100); | 112 | psc_write_word(PSC_ENETRD_CMD + set, 0x0100); |
94 | psc_write_long(PSC_ENETRD_ADDR + set, (u32) mp->rx_ring_phys); | 113 | psc_write_long(PSC_ENETRD_ADDR + set, (u32) mp->rx_ring_phys); |
@@ -103,7 +122,7 @@ static void mace_load_rxdma_base(struct net_device *dev, int set) | |||
103 | 122 | ||
104 | static void mace_rxdma_reset(struct net_device *dev) | 123 | static void mace_rxdma_reset(struct net_device *dev) |
105 | { | 124 | { |
106 | struct mace_data *mp = (struct mace_data *) dev->priv; | 125 | struct mace_data *mp = netdev_priv(dev); |
107 | volatile struct mace *mace = mp->mace; | 126 | volatile struct mace *mace = mp->mace; |
108 | u8 maccc = mace->maccc; | 127 | u8 maccc = mace->maccc; |
109 | 128 | ||
@@ -130,7 +149,7 @@ static void mace_rxdma_reset(struct net_device *dev) | |||
130 | 149 | ||
131 | static void mace_txdma_reset(struct net_device *dev) | 150 | static void mace_txdma_reset(struct net_device *dev) |
132 | { | 151 | { |
133 | struct mace_data *mp = (struct mace_data *) dev->priv; | 152 | struct mace_data *mp = netdev_priv(dev); |
134 | volatile struct mace *mace = mp->mace; | 153 | volatile struct mace *mace = mp->mace; |
135 | u8 maccc; | 154 | u8 maccc; |
136 | 155 | ||
@@ -168,7 +187,7 @@ static void mace_dma_off(struct net_device *dev) | |||
168 | * model of Macintrash has a MACE (AV macintoshes) | 187 | * model of Macintrash has a MACE (AV macintoshes) |
169 | */ | 188 | */ |
170 | 189 | ||
171 | struct net_device *mace_probe(int unit) | 190 | static int __devinit mace_probe(struct platform_device *pdev) |
172 | { | 191 | { |
173 | int j; | 192 | int j; |
174 | struct mace_data *mp; | 193 | struct mace_data *mp; |
@@ -179,24 +198,28 @@ struct net_device *mace_probe(int unit) | |||
179 | int err; | 198 | int err; |
180 | 199 | ||
181 | if (found || macintosh_config->ether_type != MAC_ETHER_MACE) | 200 | if (found || macintosh_config->ether_type != MAC_ETHER_MACE) |
182 | return ERR_PTR(-ENODEV); | 201 | return -ENODEV; |
183 | 202 | ||
184 | found = 1; /* prevent 'finding' one on every device probe */ | 203 | found = 1; /* prevent 'finding' one on every device probe */ |
185 | 204 | ||
186 | dev = alloc_etherdev(PRIV_BYTES); | 205 | dev = alloc_etherdev(PRIV_BYTES); |
187 | if (!dev) | 206 | if (!dev) |
188 | return ERR_PTR(-ENOMEM); | 207 | return -ENOMEM; |
189 | 208 | ||
190 | if (unit >= 0) | 209 | mp = netdev_priv(dev); |
191 | sprintf(dev->name, "eth%d", unit); | 210 | |
211 | mp->device = &pdev->dev; | ||
212 | SET_NETDEV_DEV(dev, &pdev->dev); | ||
213 | SET_MODULE_OWNER(dev); | ||
192 | 214 | ||
193 | mp = (struct mace_data *) dev->priv; | ||
194 | dev->base_addr = (u32)MACE_BASE; | 215 | dev->base_addr = (u32)MACE_BASE; |
195 | mp->mace = (volatile struct mace *) MACE_BASE; | 216 | mp->mace = (volatile struct mace *) MACE_BASE; |
196 | 217 | ||
197 | dev->irq = IRQ_MAC_MACE; | 218 | dev->irq = IRQ_MAC_MACE; |
198 | mp->dma_intr = IRQ_MAC_MACE_DMA; | 219 | mp->dma_intr = IRQ_MAC_MACE_DMA; |
199 | 220 | ||
221 | mp->chipid = mp->mace->chipid_hi << 8 | mp->mace->chipid_lo; | ||
222 | |||
200 | /* | 223 | /* |
201 | * The PROM contains 8 bytes which total 0xFF when XOR'd | 224 | * The PROM contains 8 bytes which total 0xFF when XOR'd |
202 | * together. Due to the usual peculiar apple brain damage | 225 | * together. Due to the usual peculiar apple brain damage |
@@ -217,7 +240,7 @@ struct net_device *mace_probe(int unit) | |||
217 | 240 | ||
218 | if (checksum != 0xFF) { | 241 | if (checksum != 0xFF) { |
219 | free_netdev(dev); | 242 | free_netdev(dev); |
220 | return ERR_PTR(-ENODEV); | 243 | return -ENODEV; |
221 | } | 244 | } |
222 | 245 | ||
223 | memset(&mp->stats, 0, sizeof(mp->stats)); | 246 | memset(&mp->stats, 0, sizeof(mp->stats)); |
@@ -237,22 +260,98 @@ struct net_device *mace_probe(int unit) | |||
237 | 260 | ||
238 | err = register_netdev(dev); | 261 | err = register_netdev(dev); |
239 | if (!err) | 262 | if (!err) |
240 | return dev; | 263 | return 0; |
241 | 264 | ||
242 | free_netdev(dev); | 265 | free_netdev(dev); |
243 | return ERR_PTR(err); | 266 | return err; |
267 | } | ||
268 | |||
269 | /* | ||
270 | * Reset the chip. | ||
271 | */ | ||
272 | |||
273 | static void mace_reset(struct net_device *dev) | ||
274 | { | ||
275 | struct mace_data *mp = netdev_priv(dev); | ||
276 | volatile struct mace *mb = mp->mace; | ||
277 | int i; | ||
278 | |||
279 | /* soft-reset the chip */ | ||
280 | i = 200; | ||
281 | while (--i) { | ||
282 | mb->biucc = SWRST; | ||
283 | if (mb->biucc & SWRST) { | ||
284 | udelay(10); | ||
285 | continue; | ||
286 | } | ||
287 | break; | ||
288 | } | ||
289 | if (!i) { | ||
290 | printk(KERN_ERR "macmace: cannot reset chip!\n"); | ||
291 | return; | ||
292 | } | ||
293 | |||
294 | mb->maccc = 0; /* turn off tx, rx */ | ||
295 | mb->imr = 0xFF; /* disable all intrs for now */ | ||
296 | i = mb->ir; | ||
297 | |||
298 | mb->biucc = XMTSP_64; | ||
299 | mb->utr = RTRD; | ||
300 | mb->fifocc = XMTFW_8 | RCVFW_64 | XMTFWU | RCVFWU; | ||
301 | |||
302 | mb->xmtfc = AUTO_PAD_XMIT; /* auto-pad short frames */ | ||
303 | mb->rcvfc = 0; | ||
304 | |||
305 | /* load up the hardware address */ | ||
306 | __mace_set_address(dev, dev->dev_addr); | ||
307 | |||
308 | /* clear the multicast filter */ | ||
309 | if (mp->chipid == BROKEN_ADDRCHG_REV) | ||
310 | mb->iac = LOGADDR; | ||
311 | else { | ||
312 | mb->iac = ADDRCHG | LOGADDR; | ||
313 | while ((mb->iac & ADDRCHG) != 0) | ||
314 | ; | ||
315 | } | ||
316 | for (i = 0; i < 8; ++i) | ||
317 | mb->ladrf = 0; | ||
318 | |||
319 | /* done changing address */ | ||
320 | if (mp->chipid != BROKEN_ADDRCHG_REV) | ||
321 | mb->iac = 0; | ||
322 | |||
323 | mb->plscc = PORTSEL_AUI; | ||
244 | } | 324 | } |
245 | 325 | ||
246 | /* | 326 | /* |
247 | * Load the address on a mace controller. | 327 | * Load the address on a mace controller. |
248 | */ | 328 | */ |
249 | 329 | ||
250 | static int mace_set_address(struct net_device *dev, void *addr) | 330 | static void __mace_set_address(struct net_device *dev, void *addr) |
251 | { | 331 | { |
252 | unsigned char *p = addr; | 332 | struct mace_data *mp = netdev_priv(dev); |
253 | struct mace_data *mp = (struct mace_data *) dev->priv; | ||
254 | volatile struct mace *mb = mp->mace; | 333 | volatile struct mace *mb = mp->mace; |
334 | unsigned char *p = addr; | ||
255 | int i; | 335 | int i; |
336 | |||
337 | /* load up the hardware address */ | ||
338 | if (mp->chipid == BROKEN_ADDRCHG_REV) | ||
339 | mb->iac = PHYADDR; | ||
340 | else { | ||
341 | mb->iac = ADDRCHG | PHYADDR; | ||
342 | while ((mb->iac & ADDRCHG) != 0) | ||
343 | ; | ||
344 | } | ||
345 | for (i = 0; i < 6; ++i) | ||
346 | mb->padr = dev->dev_addr[i] = p[i]; | ||
347 | if (mp->chipid != BROKEN_ADDRCHG_REV) | ||
348 | mb->iac = 0; | ||
349 | } | ||
350 | |||
351 | static int mace_set_address(struct net_device *dev, void *addr) | ||
352 | { | ||
353 | struct mace_data *mp = netdev_priv(dev); | ||
354 | volatile struct mace *mb = mp->mace; | ||
256 | unsigned long flags; | 355 | unsigned long flags; |
257 | u8 maccc; | 356 | u8 maccc; |
258 | 357 | ||
@@ -260,15 +359,10 @@ static int mace_set_address(struct net_device *dev, void *addr) | |||
260 | 359 | ||
261 | maccc = mb->maccc; | 360 | maccc = mb->maccc; |
262 | 361 | ||
263 | /* load up the hardware address */ | 362 | __mace_set_address(dev, addr); |
264 | mb->iac = ADDRCHG | PHYADDR; | ||
265 | while ((mb->iac & ADDRCHG) != 0); | ||
266 | |||
267 | for (i = 0; i < 6; ++i) { | ||
268 | mb->padr = dev->dev_addr[i] = p[i]; | ||
269 | } | ||
270 | 363 | ||
271 | mb->maccc = maccc; | 364 | mb->maccc = maccc; |
365 | |||
272 | local_irq_restore(flags); | 366 | local_irq_restore(flags); |
273 | 367 | ||
274 | return 0; | 368 | return 0; |
@@ -281,31 +375,11 @@ static int mace_set_address(struct net_device *dev, void *addr) | |||
281 | 375 | ||
282 | static int mace_open(struct net_device *dev) | 376 | static int mace_open(struct net_device *dev) |
283 | { | 377 | { |
284 | struct mace_data *mp = (struct mace_data *) dev->priv; | 378 | struct mace_data *mp = netdev_priv(dev); |
285 | volatile struct mace *mb = mp->mace; | 379 | volatile struct mace *mb = mp->mace; |
286 | #if 0 | ||
287 | int i; | ||
288 | 380 | ||
289 | i = 200; | 381 | /* reset the chip */ |
290 | while (--i) { | 382 | mace_reset(dev); |
291 | mb->biucc = SWRST; | ||
292 | if (mb->biucc & SWRST) { | ||
293 | udelay(10); | ||
294 | continue; | ||
295 | } | ||
296 | break; | ||
297 | } | ||
298 | if (!i) { | ||
299 | printk(KERN_ERR "%s: software reset failed!!\n", dev->name); | ||
300 | return -EAGAIN; | ||
301 | } | ||
302 | #endif | ||
303 | |||
304 | mb->biucc = XMTSP_64; | ||
305 | mb->fifocc = XMTFW_16 | RCVFW_64 | XMTFWU | RCVFWU | XMTBRST | RCVBRST; | ||
306 | mb->xmtfc = AUTO_PAD_XMIT; | ||
307 | mb->plscc = PORTSEL_AUI; | ||
308 | /* mb->utr = RTRD; */ | ||
309 | 383 | ||
310 | if (request_irq(dev->irq, mace_interrupt, 0, dev->name, dev)) { | 384 | if (request_irq(dev->irq, mace_interrupt, 0, dev->name, dev)) { |
311 | printk(KERN_ERR "%s: can't get irq %d\n", dev->name, dev->irq); | 385 | printk(KERN_ERR "%s: can't get irq %d\n", dev->name, dev->irq); |
@@ -319,25 +393,21 @@ static int mace_open(struct net_device *dev) | |||
319 | 393 | ||
320 | /* Allocate the DMA ring buffers */ | 394 | /* Allocate the DMA ring buffers */ |
321 | 395 | ||
322 | mp->rx_ring = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, N_RX_PAGES); | 396 | mp->tx_ring = dma_alloc_coherent(mp->device, |
323 | mp->tx_ring = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, 0); | 397 | N_TX_RING * MACE_BUFF_SIZE, |
324 | 398 | &mp->tx_ring_phys, GFP_KERNEL); | |
325 | if (mp->tx_ring==NULL || mp->rx_ring==NULL) { | 399 | if (mp->tx_ring == NULL) { |
326 | if (mp->rx_ring) free_pages((u32) mp->rx_ring, N_RX_PAGES); | 400 | printk(KERN_ERR "%s: unable to allocate DMA tx buffers\n", dev->name); |
327 | if (mp->tx_ring) free_pages((u32) mp->tx_ring, 0); | 401 | goto out1; |
328 | free_irq(dev->irq, dev); | ||
329 | free_irq(mp->dma_intr, dev); | ||
330 | printk(KERN_ERR "%s: unable to allocate DMA buffers\n", dev->name); | ||
331 | return -ENOMEM; | ||
332 | } | 402 | } |
333 | 403 | ||
334 | mp->rx_ring_phys = (unsigned char *) virt_to_bus((void *)mp->rx_ring); | 404 | mp->rx_ring = dma_alloc_coherent(mp->device, |
335 | mp->tx_ring_phys = (unsigned char *) virt_to_bus((void *)mp->tx_ring); | 405 | N_RX_RING * MACE_BUFF_SIZE, |
336 | 406 | &mp->rx_ring_phys, GFP_KERNEL); | |
337 | /* We want the Rx buffer to be uncached and the Tx buffer to be writethrough */ | 407 | if (mp->rx_ring == NULL) { |
338 | 408 | printk(KERN_ERR "%s: unable to allocate DMA rx buffers\n", dev->name); | |
339 | kernel_set_cachemode((void *)mp->rx_ring, N_RX_PAGES * PAGE_SIZE, IOMAP_NOCACHE_NONSER); | 409 | goto out2; |
340 | kernel_set_cachemode((void *)mp->tx_ring, PAGE_SIZE, IOMAP_WRITETHROUGH); | 410 | } |
341 | 411 | ||
342 | mace_dma_off(dev); | 412 | mace_dma_off(dev); |
343 | 413 | ||
@@ -348,34 +418,22 @@ static int mace_open(struct net_device *dev) | |||
348 | psc_write_word(PSC_ENETWR_CTL, 0x0400); | 418 | psc_write_word(PSC_ENETWR_CTL, 0x0400); |
349 | psc_write_word(PSC_ENETRD_CTL, 0x0400); | 419 | psc_write_word(PSC_ENETRD_CTL, 0x0400); |
350 | 420 | ||
351 | #if 0 | ||
352 | /* load up the hardware address */ | ||
353 | |||
354 | mb->iac = ADDRCHG | PHYADDR; | ||
355 | |||
356 | while ((mb->iac & ADDRCHG) != 0); | ||
357 | |||
358 | for (i = 0; i < 6; ++i) | ||
359 | mb->padr = dev->dev_addr[i]; | ||
360 | |||
361 | /* clear the multicast filter */ | ||
362 | mb->iac = ADDRCHG | LOGADDR; | ||
363 | |||
364 | while ((mb->iac & ADDRCHG) != 0); | ||
365 | |||
366 | for (i = 0; i < 8; ++i) | ||
367 | mb->ladrf = 0; | ||
368 | |||
369 | mb->plscc = PORTSEL_GPSI + ENPLSIO; | ||
370 | |||
371 | mb->maccc = ENXMT | ENRCV; | ||
372 | mb->imr = RCVINT; | ||
373 | #endif | ||
374 | |||
375 | mace_rxdma_reset(dev); | 421 | mace_rxdma_reset(dev); |
376 | mace_txdma_reset(dev); | 422 | mace_txdma_reset(dev); |
377 | 423 | ||
424 | /* turn it on! */ | ||
425 | mb->maccc = ENXMT | ENRCV; | ||
426 | /* enable all interrupts except receive interrupts */ | ||
427 | mb->imr = RCVINT; | ||
378 | return 0; | 428 | return 0; |
429 | |||
430 | out2: | ||
431 | dma_free_coherent(mp->device, N_TX_RING * MACE_BUFF_SIZE, | ||
432 | mp->tx_ring, mp->tx_ring_phys); | ||
433 | out1: | ||
434 | free_irq(dev->irq, dev); | ||
435 | free_irq(mp->dma_intr, dev); | ||
436 | return -ENOMEM; | ||
379 | } | 437 | } |
380 | 438 | ||
381 | /* | 439 | /* |
@@ -384,19 +442,13 @@ static int mace_open(struct net_device *dev) | |||
384 | 442 | ||
385 | static int mace_close(struct net_device *dev) | 443 | static int mace_close(struct net_device *dev) |
386 | { | 444 | { |
387 | struct mace_data *mp = (struct mace_data *) dev->priv; | 445 | struct mace_data *mp = netdev_priv(dev); |
388 | volatile struct mace *mb = mp->mace; | 446 | volatile struct mace *mb = mp->mace; |
389 | 447 | ||
390 | mb->maccc = 0; /* disable rx and tx */ | 448 | mb->maccc = 0; /* disable rx and tx */ |
391 | mb->imr = 0xFF; /* disable all irqs */ | 449 | mb->imr = 0xFF; /* disable all irqs */ |
392 | mace_dma_off(dev); /* disable rx and tx dma */ | 450 | mace_dma_off(dev); /* disable rx and tx dma */ |
393 | 451 | ||
394 | free_irq(dev->irq, dev); | ||
395 | free_irq(IRQ_MAC_MACE_DMA, dev); | ||
396 | |||
397 | free_pages((u32) mp->rx_ring, N_RX_PAGES); | ||
398 | free_pages((u32) mp->tx_ring, 0); | ||
399 | |||
400 | return 0; | 452 | return 0; |
401 | } | 453 | } |
402 | 454 | ||
@@ -406,15 +458,20 @@ static int mace_close(struct net_device *dev) | |||
406 | 458 | ||
407 | static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev) | 459 | static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev) |
408 | { | 460 | { |
409 | struct mace_data *mp = (struct mace_data *) dev->priv; | 461 | struct mace_data *mp = netdev_priv(dev); |
462 | unsigned long flags; | ||
410 | 463 | ||
411 | /* Stop the queue if the buffer is full */ | 464 | /* Stop the queue since there's only the one buffer */ |
412 | 465 | ||
466 | local_irq_save(flags); | ||
467 | netif_stop_queue(dev); | ||
413 | if (!mp->tx_count) { | 468 | if (!mp->tx_count) { |
414 | netif_stop_queue(dev); | 469 | printk(KERN_ERR "macmace: tx queue running but no free buffers.\n"); |
415 | return 1; | 470 | local_irq_restore(flags); |
471 | return NETDEV_TX_BUSY; | ||
416 | } | 472 | } |
417 | mp->tx_count--; | 473 | mp->tx_count--; |
474 | local_irq_restore(flags); | ||
418 | 475 | ||
419 | mp->stats.tx_packets++; | 476 | mp->stats.tx_packets++; |
420 | mp->stats.tx_bytes += skb->len; | 477 | mp->stats.tx_bytes += skb->len; |
@@ -432,23 +489,26 @@ static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev) | |||
432 | 489 | ||
433 | dev_kfree_skb(skb); | 490 | dev_kfree_skb(skb); |
434 | 491 | ||
435 | return 0; | 492 | dev->trans_start = jiffies; |
493 | return NETDEV_TX_OK; | ||
436 | } | 494 | } |
437 | 495 | ||
438 | static struct net_device_stats *mace_stats(struct net_device *dev) | 496 | static struct net_device_stats *mace_stats(struct net_device *dev) |
439 | { | 497 | { |
440 | struct mace_data *p = (struct mace_data *) dev->priv; | 498 | struct mace_data *mp = netdev_priv(dev); |
441 | return &p->stats; | 499 | return &mp->stats; |
442 | } | 500 | } |
443 | 501 | ||
444 | static void mace_set_multicast(struct net_device *dev) | 502 | static void mace_set_multicast(struct net_device *dev) |
445 | { | 503 | { |
446 | struct mace_data *mp = (struct mace_data *) dev->priv; | 504 | struct mace_data *mp = netdev_priv(dev); |
447 | volatile struct mace *mb = mp->mace; | 505 | volatile struct mace *mb = mp->mace; |
448 | int i, j; | 506 | int i, j; |
449 | u32 crc; | 507 | u32 crc; |
450 | u8 maccc; | 508 | u8 maccc; |
509 | unsigned long flags; | ||
451 | 510 | ||
511 | local_irq_save(flags); | ||
452 | maccc = mb->maccc; | 512 | maccc = mb->maccc; |
453 | mb->maccc &= ~PROM; | 513 | mb->maccc &= ~PROM; |
454 | 514 | ||
@@ -473,116 +533,122 @@ static void mace_set_multicast(struct net_device *dev) | |||
473 | } | 533 | } |
474 | } | 534 | } |
475 | 535 | ||
476 | mb->iac = ADDRCHG | LOGADDR; | 536 | if (mp->chipid == BROKEN_ADDRCHG_REV) |
477 | while (mb->iac & ADDRCHG); | 537 | mb->iac = LOGADDR; |
478 | 538 | else { | |
479 | for (i = 0; i < 8; ++i) { | 539 | mb->iac = ADDRCHG | LOGADDR; |
480 | mb->ladrf = multicast_filter[i]; | 540 | while ((mb->iac & ADDRCHG) != 0) |
541 | ; | ||
481 | } | 542 | } |
543 | for (i = 0; i < 8; ++i) | ||
544 | mb->ladrf = multicast_filter[i]; | ||
545 | if (mp->chipid != BROKEN_ADDRCHG_REV) | ||
546 | mb->iac = 0; | ||
482 | } | 547 | } |
483 | 548 | ||
484 | mb->maccc = maccc; | 549 | mb->maccc = maccc; |
550 | local_irq_restore(flags); | ||
485 | } | 551 | } |
486 | 552 | ||
487 | /* | ||
488 | * Miscellaneous interrupts are handled here. We may end up | ||
489 | * having to bash the chip on the head for bad errors | ||
490 | */ | ||
491 | |||
492 | static void mace_handle_misc_intrs(struct mace_data *mp, int intr) | 553 | static void mace_handle_misc_intrs(struct mace_data *mp, int intr) |
493 | { | 554 | { |
494 | volatile struct mace *mb = mp->mace; | 555 | volatile struct mace *mb = mp->mace; |
495 | static int mace_babbles, mace_jabbers; | 556 | static int mace_babbles, mace_jabbers; |
496 | 557 | ||
497 | if (intr & MPCO) { | 558 | if (intr & MPCO) |
498 | mp->stats.rx_missed_errors += 256; | 559 | mp->stats.rx_missed_errors += 256; |
499 | } | 560 | mp->stats.rx_missed_errors += mb->mpc; /* reading clears it */ |
500 | mp->stats.rx_missed_errors += mb->mpc; /* reading clears it */ | 561 | if (intr & RNTPCO) |
501 | |||
502 | if (intr & RNTPCO) { | ||
503 | mp->stats.rx_length_errors += 256; | 562 | mp->stats.rx_length_errors += 256; |
504 | } | 563 | mp->stats.rx_length_errors += mb->rntpc; /* reading clears it */ |
505 | mp->stats.rx_length_errors += mb->rntpc; /* reading clears it */ | 564 | if (intr & CERR) |
506 | |||
507 | if (intr & CERR) { | ||
508 | ++mp->stats.tx_heartbeat_errors; | 565 | ++mp->stats.tx_heartbeat_errors; |
509 | } | 566 | if (intr & BABBLE) |
510 | if (intr & BABBLE) { | 567 | if (mace_babbles++ < 4) |
511 | if (mace_babbles++ < 4) { | 568 | printk(KERN_DEBUG "macmace: babbling transmitter\n"); |
512 | printk(KERN_DEBUG "mace: babbling transmitter\n"); | 569 | if (intr & JABBER) |
513 | } | 570 | if (mace_jabbers++ < 4) |
514 | } | 571 | printk(KERN_DEBUG "macmace: jabbering transceiver\n"); |
515 | if (intr & JABBER) { | ||
516 | if (mace_jabbers++ < 4) { | ||
517 | printk(KERN_DEBUG "mace: jabbering transceiver\n"); | ||
518 | } | ||
519 | } | ||
520 | } | 572 | } |
521 | 573 | ||
522 | /* | 574 | static irqreturn_t mace_interrupt(int irq, void *dev_id) |
523 | * A transmit error has occurred. (We kick the transmit side from | ||
524 | * the DMA completion) | ||
525 | */ | ||
526 | |||
527 | static void mace_xmit_error(struct net_device *dev) | ||
528 | { | 575 | { |
529 | struct mace_data *mp = (struct mace_data *) dev->priv; | 576 | struct net_device *dev = (struct net_device *) dev_id; |
577 | struct mace_data *mp = netdev_priv(dev); | ||
530 | volatile struct mace *mb = mp->mace; | 578 | volatile struct mace *mb = mp->mace; |
531 | u8 xmtfs, xmtrc; | 579 | int intr, fs; |
580 | unsigned int flags; | ||
532 | 581 | ||
533 | xmtfs = mb->xmtfs; | 582 | /* don't want the dma interrupt handler to fire */ |
534 | xmtrc = mb->xmtrc; | 583 | local_irq_save(flags); |
535 | 584 | ||
536 | if (xmtfs & XMTSV) { | 585 | intr = mb->ir; /* read interrupt register */ |
537 | if (xmtfs & UFLO) { | 586 | mace_handle_misc_intrs(mp, intr); |
538 | printk("%s: DMA underrun.\n", dev->name); | 587 | |
539 | mp->stats.tx_errors++; | 588 | if (intr & XMTINT) { |
540 | mp->stats.tx_fifo_errors++; | 589 | fs = mb->xmtfs; |
541 | mace_txdma_reset(dev); | 590 | if ((fs & XMTSV) == 0) { |
591 | printk(KERN_ERR "macmace: xmtfs not valid! (fs=%x)\n", fs); | ||
592 | mace_reset(dev); | ||
593 | /* | ||
594 | * XXX mace likes to hang the machine after a xmtfs error. | ||
595 | * This is hard to reproduce, reseting *may* help | ||
596 | */ | ||
542 | } | 597 | } |
543 | if (xmtfs & RTRY) { | 598 | /* dma should have finished */ |
544 | mp->stats.collisions++; | 599 | if (!mp->tx_count) { |
600 | printk(KERN_DEBUG "macmace: tx ring ran out? (fs=%x)\n", fs); | ||
601 | } | ||
602 | /* Update stats */ | ||
603 | if (fs & (UFLO|LCOL|LCAR|RTRY)) { | ||
604 | ++mp->stats.tx_errors; | ||
605 | if (fs & LCAR) | ||
606 | ++mp->stats.tx_carrier_errors; | ||
607 | else if (fs & (UFLO|LCOL|RTRY)) { | ||
608 | ++mp->stats.tx_aborted_errors; | ||
609 | if (mb->xmtfs & UFLO) { | ||
610 | printk(KERN_ERR "%s: DMA underrun.\n", dev->name); | ||
611 | mp->stats.tx_fifo_errors++; | ||
612 | mace_txdma_reset(dev); | ||
613 | } | ||
614 | } | ||
545 | } | 615 | } |
546 | } | 616 | } |
547 | } | ||
548 | 617 | ||
549 | /* | 618 | if (mp->tx_count) |
550 | * A receive interrupt occurred. | 619 | netif_wake_queue(dev); |
551 | */ | ||
552 | 620 | ||
553 | static void mace_recv_interrupt(struct net_device *dev) | 621 | local_irq_restore(flags); |
554 | { | ||
555 | /* struct mace_data *mp = (struct mace_data *) dev->priv; */ | ||
556 | // volatile struct mace *mb = mp->mace; | ||
557 | } | ||
558 | 622 | ||
559 | /* | 623 | return IRQ_HANDLED; |
560 | * Process the chip interrupt | 624 | } |
561 | */ | ||
562 | 625 | ||
563 | static irqreturn_t mace_interrupt(int irq, void *dev_id) | 626 | static void mace_tx_timeout(struct net_device *dev) |
564 | { | 627 | { |
565 | struct net_device *dev = (struct net_device *) dev_id; | 628 | struct mace_data *mp = netdev_priv(dev); |
566 | struct mace_data *mp = (struct mace_data *) dev->priv; | ||
567 | volatile struct mace *mb = mp->mace; | 629 | volatile struct mace *mb = mp->mace; |
568 | u8 ir; | 630 | unsigned long flags; |
569 | 631 | ||
570 | ir = mb->ir; | 632 | local_irq_save(flags); |
571 | mace_handle_misc_intrs(mp, ir); | ||
572 | 633 | ||
573 | if (ir & XMTINT) { | 634 | /* turn off both tx and rx and reset the chip */ |
574 | mace_xmit_error(dev); | 635 | mb->maccc = 0; |
575 | } | 636 | printk(KERN_ERR "macmace: transmit timeout - resetting\n"); |
576 | if (ir & RCVINT) { | 637 | mace_txdma_reset(dev); |
577 | mace_recv_interrupt(dev); | 638 | mace_reset(dev); |
578 | } | ||
579 | return IRQ_HANDLED; | ||
580 | } | ||
581 | 639 | ||
582 | static void mace_tx_timeout(struct net_device *dev) | 640 | /* restart rx dma */ |
583 | { | 641 | mace_rxdma_reset(dev); |
584 | /* struct mace_data *mp = (struct mace_data *) dev->priv; */ | 642 | |
585 | // volatile struct mace *mb = mp->mace; | 643 | mp->tx_count = N_TX_RING; |
644 | netif_wake_queue(dev); | ||
645 | |||
646 | /* turn it on! */ | ||
647 | mb->maccc = ENXMT | ENRCV; | ||
648 | /* enable all interrupts except receive interrupts */ | ||
649 | mb->imr = RCVINT; | ||
650 | |||
651 | local_irq_restore(flags); | ||
586 | } | 652 | } |
587 | 653 | ||
588 | /* | 654 | /* |
@@ -591,40 +657,39 @@ static void mace_tx_timeout(struct net_device *dev) | |||
591 | 657 | ||
592 | static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf) | 658 | static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf) |
593 | { | 659 | { |
594 | struct mace_data *mp = (struct mace_data *) dev->priv; | 660 | struct mace_data *mp = netdev_priv(dev); |
595 | struct sk_buff *skb; | 661 | struct sk_buff *skb; |
662 | unsigned int frame_status = mf->rcvsts; | ||
596 | 663 | ||
597 | if (mf->status & RS_OFLO) { | 664 | if (frame_status & (RS_OFLO | RS_CLSN | RS_FRAMERR | RS_FCSERR)) { |
598 | printk("%s: fifo overflow.\n", dev->name); | ||
599 | mp->stats.rx_errors++; | ||
600 | mp->stats.rx_fifo_errors++; | ||
601 | } | ||
602 | if (mf->status&(RS_CLSN|RS_FRAMERR|RS_FCSERR)) | ||
603 | mp->stats.rx_errors++; | 665 | mp->stats.rx_errors++; |
666 | if (frame_status & RS_OFLO) { | ||
667 | printk(KERN_DEBUG "%s: fifo overflow.\n", dev->name); | ||
668 | mp->stats.rx_fifo_errors++; | ||
669 | } | ||
670 | if (frame_status & RS_CLSN) | ||
671 | mp->stats.collisions++; | ||
672 | if (frame_status & RS_FRAMERR) | ||
673 | mp->stats.rx_frame_errors++; | ||
674 | if (frame_status & RS_FCSERR) | ||
675 | mp->stats.rx_crc_errors++; | ||
676 | } else { | ||
677 | unsigned int frame_length = mf->rcvcnt + ((frame_status & 0x0F) << 8 ); | ||
604 | 678 | ||
605 | if (mf->status&RS_CLSN) { | 679 | skb = dev_alloc_skb(frame_length + 2); |
606 | mp->stats.collisions++; | 680 | if (!skb) { |
607 | } | 681 | mp->stats.rx_dropped++; |
608 | if (mf->status&RS_FRAMERR) { | 682 | return; |
609 | mp->stats.rx_frame_errors++; | 683 | } |
610 | } | 684 | skb_reserve(skb, 2); |
611 | if (mf->status&RS_FCSERR) { | 685 | memcpy(skb_put(skb, frame_length), mf->data, frame_length); |
612 | mp->stats.rx_crc_errors++; | 686 | |
613 | } | 687 | skb->protocol = eth_type_trans(skb, dev); |
614 | 688 | netif_rx(skb); | |
615 | skb = dev_alloc_skb(mf->len+2); | 689 | dev->last_rx = jiffies; |
616 | if (!skb) { | 690 | mp->stats.rx_packets++; |
617 | mp->stats.rx_dropped++; | 691 | mp->stats.rx_bytes += frame_length; |
618 | return; | ||
619 | } | 692 | } |
620 | skb_reserve(skb,2); | ||
621 | memcpy(skb_put(skb, mf->len), mf->data, mf->len); | ||
622 | |||
623 | skb->protocol = eth_type_trans(skb, dev); | ||
624 | netif_rx(skb); | ||
625 | dev->last_rx = jiffies; | ||
626 | mp->stats.rx_packets++; | ||
627 | mp->stats.rx_bytes += mf->len; | ||
628 | } | 693 | } |
629 | 694 | ||
630 | /* | 695 | /* |
@@ -634,7 +699,7 @@ static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf) | |||
634 | static irqreturn_t mace_dma_intr(int irq, void *dev_id) | 699 | static irqreturn_t mace_dma_intr(int irq, void *dev_id) |
635 | { | 700 | { |
636 | struct net_device *dev = (struct net_device *) dev_id; | 701 | struct net_device *dev = (struct net_device *) dev_id; |
637 | struct mace_data *mp = (struct mace_data *) dev->priv; | 702 | struct mace_data *mp = netdev_priv(dev); |
638 | int left, head; | 703 | int left, head; |
639 | u16 status; | 704 | u16 status; |
640 | u32 baka; | 705 | u32 baka; |
@@ -661,7 +726,8 @@ static irqreturn_t mace_dma_intr(int irq, void *dev_id) | |||
661 | /* Loop through the ring buffer and process new packages */ | 726 | /* Loop through the ring buffer and process new packages */ |
662 | 727 | ||
663 | while (mp->rx_tail < head) { | 728 | while (mp->rx_tail < head) { |
664 | mace_dma_rx_frame(dev, (struct mace_frame *) (mp->rx_ring + (mp->rx_tail * 0x0800))); | 729 | mace_dma_rx_frame(dev, (struct mace_frame*) (mp->rx_ring |
730 | + (mp->rx_tail * MACE_BUFF_SIZE))); | ||
665 | mp->rx_tail++; | 731 | mp->rx_tail++; |
666 | } | 732 | } |
667 | 733 | ||
@@ -688,9 +754,76 @@ static irqreturn_t mace_dma_intr(int irq, void *dev_id) | |||
688 | psc_write_word(PSC_ENETWR_CMD + mp->tx_sloti, 0x0100); | 754 | psc_write_word(PSC_ENETWR_CMD + mp->tx_sloti, 0x0100); |
689 | mp->tx_sloti ^= 0x10; | 755 | mp->tx_sloti ^= 0x10; |
690 | mp->tx_count++; | 756 | mp->tx_count++; |
691 | netif_wake_queue(dev); | ||
692 | } | 757 | } |
693 | return IRQ_HANDLED; | 758 | return IRQ_HANDLED; |
694 | } | 759 | } |
695 | 760 | ||
696 | MODULE_LICENSE("GPL"); | 761 | MODULE_LICENSE("GPL"); |
762 | MODULE_DESCRIPTION("Macintosh MACE ethernet driver"); | ||
763 | |||
764 | static int __devexit mac_mace_device_remove (struct platform_device *pdev) | ||
765 | { | ||
766 | struct net_device *dev = platform_get_drvdata(pdev); | ||
767 | struct mace_data *mp = netdev_priv(dev); | ||
768 | |||
769 | unregister_netdev(dev); | ||
770 | |||
771 | free_irq(dev->irq, dev); | ||
772 | free_irq(IRQ_MAC_MACE_DMA, dev); | ||
773 | |||
774 | dma_free_coherent(mp->device, N_RX_RING * MACE_BUFF_SIZE, | ||
775 | mp->rx_ring, mp->rx_ring_phys); | ||
776 | dma_free_coherent(mp->device, N_TX_RING * MACE_BUFF_SIZE, | ||
777 | mp->tx_ring, mp->tx_ring_phys); | ||
778 | |||
779 | free_netdev(dev); | ||
780 | |||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | static struct platform_driver mac_mace_driver = { | ||
785 | .probe = mace_probe, | ||
786 | .remove = __devexit_p(mac_mace_device_remove), | ||
787 | .driver = { | ||
788 | .name = mac_mace_string, | ||
789 | }, | ||
790 | }; | ||
791 | |||
792 | static int __init mac_mace_init_module(void) | ||
793 | { | ||
794 | int err; | ||
795 | |||
796 | if ((err = platform_driver_register(&mac_mace_driver))) { | ||
797 | printk(KERN_ERR "Driver registration failed\n"); | ||
798 | return err; | ||
799 | } | ||
800 | |||
801 | mac_mace_device = platform_device_alloc(mac_mace_string, 0); | ||
802 | if (!mac_mace_device) | ||
803 | goto out_unregister; | ||
804 | |||
805 | if (platform_device_add(mac_mace_device)) { | ||
806 | platform_device_put(mac_mace_device); | ||
807 | mac_mace_device = NULL; | ||
808 | } | ||
809 | |||
810 | return 0; | ||
811 | |||
812 | out_unregister: | ||
813 | platform_driver_unregister(&mac_mace_driver); | ||
814 | |||
815 | return -ENOMEM; | ||
816 | } | ||
817 | |||
818 | static void __exit mac_mace_cleanup_module(void) | ||
819 | { | ||
820 | platform_driver_unregister(&mac_mace_driver); | ||
821 | |||
822 | if (mac_mace_device) { | ||
823 | platform_device_unregister(mac_mace_device); | ||
824 | mac_mace_device = NULL; | ||
825 | } | ||
826 | } | ||
827 | |||
828 | module_init(mac_mace_init_module); | ||
829 | module_exit(mac_mace_cleanup_module); | ||
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c index 8ca57a0a4c11..e9ecdbf352ae 100644 --- a/drivers/net/macsonic.c +++ b/drivers/net/macsonic.c | |||
@@ -130,6 +130,46 @@ static inline void bit_reverse_addr(unsigned char addr[6]) | |||
130 | addr[i] = bitrev8(addr[i]); | 130 | addr[i] = bitrev8(addr[i]); |
131 | } | 131 | } |
132 | 132 | ||
133 | static irqreturn_t macsonic_interrupt(int irq, void *dev_id) | ||
134 | { | ||
135 | irqreturn_t result; | ||
136 | unsigned long flags; | ||
137 | |||
138 | local_irq_save(flags); | ||
139 | result = sonic_interrupt(irq, dev_id); | ||
140 | local_irq_restore(flags); | ||
141 | return result; | ||
142 | } | ||
143 | |||
144 | static int macsonic_open(struct net_device* dev) | ||
145 | { | ||
146 | if (request_irq(dev->irq, &sonic_interrupt, IRQ_FLG_FAST, "sonic", dev)) { | ||
147 | printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq); | ||
148 | return -EAGAIN; | ||
149 | } | ||
150 | /* Under the A/UX interrupt scheme, the onboard SONIC interrupt comes | ||
151 | * in at priority level 3. However, we sometimes get the level 2 inter- | ||
152 | * rupt as well, which must prevent re-entrance of the sonic handler. | ||
153 | */ | ||
154 | if (dev->irq == IRQ_AUTO_3) | ||
155 | if (request_irq(IRQ_NUBUS_9, &macsonic_interrupt, IRQ_FLG_FAST, "sonic", dev)) { | ||
156 | printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, IRQ_NUBUS_9); | ||
157 | free_irq(dev->irq, dev); | ||
158 | return -EAGAIN; | ||
159 | } | ||
160 | return sonic_open(dev); | ||
161 | } | ||
162 | |||
163 | static int macsonic_close(struct net_device* dev) | ||
164 | { | ||
165 | int err; | ||
166 | err = sonic_close(dev); | ||
167 | free_irq(dev->irq, dev); | ||
168 | if (dev->irq == IRQ_AUTO_3) | ||
169 | free_irq(IRQ_NUBUS_9, dev); | ||
170 | return err; | ||
171 | } | ||
172 | |||
133 | int __init macsonic_init(struct net_device* dev) | 173 | int __init macsonic_init(struct net_device* dev) |
134 | { | 174 | { |
135 | struct sonic_local* lp = netdev_priv(dev); | 175 | struct sonic_local* lp = netdev_priv(dev); |
@@ -160,8 +200,8 @@ int __init macsonic_init(struct net_device* dev) | |||
160 | lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS | 200 | lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS |
161 | * SONIC_BUS_SCALE(lp->dma_bitmode)); | 201 | * SONIC_BUS_SCALE(lp->dma_bitmode)); |
162 | 202 | ||
163 | dev->open = sonic_open; | 203 | dev->open = macsonic_open; |
164 | dev->stop = sonic_close; | 204 | dev->stop = macsonic_close; |
165 | dev->hard_start_xmit = sonic_send_packet; | 205 | dev->hard_start_xmit = sonic_send_packet; |
166 | dev->get_stats = sonic_get_stats; | 206 | dev->get_stats = sonic_get_stats; |
167 | dev->set_multicast_list = &sonic_multicast_list; | 207 | dev->set_multicast_list = &sonic_multicast_list; |
@@ -402,7 +442,7 @@ int __init macsonic_ident(struct nubus_dev* ndev) | |||
402 | ndev->dr_sw == NUBUS_DRSW_DAYNA) | 442 | ndev->dr_sw == NUBUS_DRSW_DAYNA) |
403 | return MACSONIC_DAYNA; | 443 | return MACSONIC_DAYNA; |
404 | 444 | ||
405 | if (ndev->dr_hw == NUBUS_DRHW_SONIC_LC && | 445 | if (ndev->dr_hw == NUBUS_DRHW_APPLE_SONIC_LC && |
406 | ndev->dr_sw == 0) { /* huh? */ | 446 | ndev->dr_sw == 0) { /* huh? */ |
407 | return MACSONIC_APPLE16; | 447 | return MACSONIC_APPLE16; |
408 | } | 448 | } |
@@ -522,7 +562,7 @@ int __init mac_nubus_sonic_probe(struct net_device* dev) | |||
522 | return macsonic_init(dev); | 562 | return macsonic_init(dev); |
523 | } | 563 | } |
524 | 564 | ||
525 | static int __init mac_sonic_probe(struct platform_device *device) | 565 | static int __init mac_sonic_probe(struct platform_device *pdev) |
526 | { | 566 | { |
527 | struct net_device *dev; | 567 | struct net_device *dev; |
528 | struct sonic_local *lp; | 568 | struct sonic_local *lp; |
@@ -534,8 +574,8 @@ static int __init mac_sonic_probe(struct platform_device *device) | |||
534 | return -ENOMEM; | 574 | return -ENOMEM; |
535 | 575 | ||
536 | lp = netdev_priv(dev); | 576 | lp = netdev_priv(dev); |
537 | lp->device = &device->dev; | 577 | lp->device = &pdev->dev; |
538 | SET_NETDEV_DEV(dev, &device->dev); | 578 | SET_NETDEV_DEV(dev, &pdev->dev); |
539 | SET_MODULE_OWNER(dev); | 579 | SET_MODULE_OWNER(dev); |
540 | 580 | ||
541 | /* This will catch fatal stuff like -ENOMEM as well as success */ | 581 | /* This will catch fatal stuff like -ENOMEM as well as success */ |
@@ -572,19 +612,17 @@ MODULE_DESCRIPTION("Macintosh SONIC ethernet driver"); | |||
572 | module_param(sonic_debug, int, 0); | 612 | module_param(sonic_debug, int, 0); |
573 | MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)"); | 613 | MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)"); |
574 | 614 | ||
575 | #define SONIC_IRQ_FLAG IRQ_FLG_FAST | ||
576 | |||
577 | #include "sonic.c" | 615 | #include "sonic.c" |
578 | 616 | ||
579 | static int __devexit mac_sonic_device_remove (struct platform_device *device) | 617 | static int __devexit mac_sonic_device_remove (struct platform_device *pdev) |
580 | { | 618 | { |
581 | struct net_device *dev = platform_get_drvdata(device); | 619 | struct net_device *dev = platform_get_drvdata(pdev); |
582 | struct sonic_local* lp = netdev_priv(dev); | 620 | struct sonic_local* lp = netdev_priv(dev); |
583 | 621 | ||
584 | unregister_netdev (dev); | 622 | unregister_netdev(dev); |
585 | dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), | 623 | dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), |
586 | lp->descriptors, lp->descriptors_laddr); | 624 | lp->descriptors, lp->descriptors_laddr); |
587 | free_netdev (dev); | 625 | free_netdev(dev); |
588 | 626 | ||
589 | return 0; | 627 | return 0; |
590 | } | 628 | } |
@@ -607,9 +645,8 @@ static int __init mac_sonic_init_module(void) | |||
607 | } | 645 | } |
608 | 646 | ||
609 | mac_sonic_device = platform_device_alloc(mac_sonic_string, 0); | 647 | mac_sonic_device = platform_device_alloc(mac_sonic_string, 0); |
610 | if (!mac_sonic_device) { | 648 | if (!mac_sonic_device) |
611 | goto out_unregister; | 649 | goto out_unregister; |
612 | } | ||
613 | 650 | ||
614 | if (platform_device_add(mac_sonic_device)) { | 651 | if (platform_device_add(mac_sonic_device)) { |
615 | platform_device_put(mac_sonic_device); | 652 | platform_device_put(mac_sonic_device); |
diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c index c6320c719931..8069f3e32d83 100644 --- a/drivers/net/sonic.c +++ b/drivers/net/sonic.c | |||
@@ -50,29 +50,6 @@ static int sonic_open(struct net_device *dev) | |||
50 | if (sonic_debug > 2) | 50 | if (sonic_debug > 2) |
51 | printk("sonic_open: initializing sonic driver.\n"); | 51 | printk("sonic_open: initializing sonic driver.\n"); |
52 | 52 | ||
53 | /* | ||
54 | * We don't need to deal with auto-irq stuff since we | ||
55 | * hardwire the sonic interrupt. | ||
56 | */ | ||
57 | /* | ||
58 | * XXX Horrible work around: We install sonic_interrupt as fast interrupt. | ||
59 | * This means that during execution of the handler interrupt are disabled | ||
60 | * covering another bug otherwise corrupting data. This doesn't mean | ||
61 | * this glue works ok under all situations. | ||
62 | * | ||
63 | * Note (dhd): this also appears to prevent lockups on the Macintrash | ||
64 | * when more than one Ethernet card is installed (knock on wood) | ||
65 | * | ||
66 | * Note (fthain): whether the above is still true is anyones guess. Certainly | ||
67 | * the buffer handling algorithms will not tolerate re-entrance without some | ||
68 | * mutual exclusion added. Anyway, the memcpy has now been eliminated from the | ||
69 | * rx code to make this a faster "fast interrupt". | ||
70 | */ | ||
71 | if (request_irq(dev->irq, &sonic_interrupt, SONIC_IRQ_FLAG, "sonic", dev)) { | ||
72 | printk(KERN_ERR "\n%s: unable to get IRQ %d .\n", dev->name, dev->irq); | ||
73 | return -EAGAIN; | ||
74 | } | ||
75 | |||
76 | for (i = 0; i < SONIC_NUM_RRS; i++) { | 53 | for (i = 0; i < SONIC_NUM_RRS; i++) { |
77 | struct sk_buff *skb = dev_alloc_skb(SONIC_RBSIZE + 2); | 54 | struct sk_buff *skb = dev_alloc_skb(SONIC_RBSIZE + 2); |
78 | if (skb == NULL) { | 55 | if (skb == NULL) { |
@@ -169,8 +146,6 @@ static int sonic_close(struct net_device *dev) | |||
169 | } | 146 | } |
170 | } | 147 | } |
171 | 148 | ||
172 | free_irq(dev->irq, dev); /* release the IRQ */ | ||
173 | |||
174 | return 0; | 149 | return 0; |
175 | } | 150 | } |
176 | 151 | ||
@@ -178,8 +153,13 @@ static void sonic_tx_timeout(struct net_device *dev) | |||
178 | { | 153 | { |
179 | struct sonic_local *lp = netdev_priv(dev); | 154 | struct sonic_local *lp = netdev_priv(dev); |
180 | int i; | 155 | int i; |
181 | /* Stop the interrupts for this */ | 156 | /* |
157 | * put the Sonic into software-reset mode and | ||
158 | * disable all interrupts before releasing DMA buffers | ||
159 | */ | ||
182 | SONIC_WRITE(SONIC_IMR, 0); | 160 | SONIC_WRITE(SONIC_IMR, 0); |
161 | SONIC_WRITE(SONIC_ISR, 0x7fff); | ||
162 | SONIC_WRITE(SONIC_CMD, SONIC_CR_RST); | ||
183 | /* We could resend the original skbs. Easier to re-initialise. */ | 163 | /* We could resend the original skbs. Easier to re-initialise. */ |
184 | for (i = 0; i < SONIC_NUM_TDS; i++) { | 164 | for (i = 0; i < SONIC_NUM_TDS; i++) { |
185 | if(lp->tx_laddr[i]) { | 165 | if(lp->tx_laddr[i]) { |
diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c index 396c3d961f88..a123ea87893b 100644 --- a/drivers/net/sun3_82586.c +++ b/drivers/net/sun3_82586.c | |||
@@ -1023,10 +1023,11 @@ static int sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev) | |||
1023 | { | 1023 | { |
1024 | len = skb->len; | 1024 | len = skb->len; |
1025 | if (len < ETH_ZLEN) { | 1025 | if (len < ETH_ZLEN) { |
1026 | memset((char *)p->xmit_cbuffs[p->xmit_count], 0, ETH_ZLEN); | 1026 | memset((void *)p->xmit_cbuffs[p->xmit_count], 0, |
1027 | ETH_ZLEN); | ||
1027 | len = ETH_ZLEN; | 1028 | len = ETH_ZLEN; |
1028 | } | 1029 | } |
1029 | skb_copy_from_linear_data(skb, p->xmit_cbuffs[p->xmit_count], skb->len); | 1030 | skb_copy_from_linear_data(skb, (void *)p->xmit_cbuffs[p->xmit_count], skb->len); |
1030 | 1031 | ||
1031 | #if (NUM_XMIT_BUFFS == 1) | 1032 | #if (NUM_XMIT_BUFFS == 1) |
1032 | # ifdef NO_NOPCOMMANDS | 1033 | # ifdef NO_NOPCOMMANDS |
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c index ed274d6909d0..f8f4d74f01f1 100644 --- a/drivers/net/tokenring/madgemc.c +++ b/drivers/net/tokenring/madgemc.c | |||
@@ -23,7 +23,6 @@ static const char version[] = "madgemc.c: v0.91 23/01/2000 by Adam Fritzler\n"; | |||
23 | #include <linux/mca.h> | 23 | #include <linux/mca.h> |
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
26 | #include <linux/pci.h> | ||
27 | #include <linux/init.h> | 26 | #include <linux/init.h> |
28 | #include <linux/netdevice.h> | 27 | #include <linux/netdevice.h> |
29 | #include <linux/trdevice.h> | 28 | #include <linux/trdevice.h> |
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c index 9bbea5c8acf4..58d7e5d452fa 100644 --- a/drivers/net/tokenring/smctr.c +++ b/drivers/net/tokenring/smctr.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <linux/time.h> | 41 | #include <linux/time.h> |
42 | #include <linux/errno.h> | 42 | #include <linux/errno.h> |
43 | #include <linux/init.h> | 43 | #include <linux/init.h> |
44 | #include <linux/pci.h> | ||
45 | #include <linux/mca-legacy.h> | 44 | #include <linux/mca-legacy.h> |
46 | #include <linux/delay.h> | 45 | #include <linux/delay.h> |
47 | #include <linux/netdevice.h> | 46 | #include <linux/netdevice.h> |
diff --git a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c index 942b839ccc5b..6c400ccd38b4 100644 --- a/drivers/net/tulip/21142.c +++ b/drivers/net/tulip/21142.c | |||
@@ -14,7 +14,6 @@ | |||
14 | 14 | ||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
19 | #include "tulip.h" | 18 | #include "tulip.h" |
20 | 19 | ||
diff --git a/drivers/net/tulip/pnic.c b/drivers/net/tulip/pnic.c index 85a521e0d052..be82a2effee3 100644 --- a/drivers/net/tulip/pnic.c +++ b/drivers/net/tulip/pnic.c | |||
@@ -15,7 +15,6 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/pci.h> | ||
19 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
20 | #include "tulip.h" | 19 | #include "tulip.h" |
21 | 20 | ||
diff --git a/drivers/net/tulip/pnic2.c b/drivers/net/tulip/pnic2.c index c31be0e377a8..4e4a879c3fa5 100644 --- a/drivers/net/tulip/pnic2.c +++ b/drivers/net/tulip/pnic2.c | |||
@@ -76,7 +76,6 @@ | |||
76 | 76 | ||
77 | 77 | ||
78 | 78 | ||
79 | #include <linux/pci.h> | ||
80 | #include "tulip.h" | 79 | #include "tulip.h" |
81 | #include <linux/delay.h> | 80 | #include <linux/delay.h> |
82 | 81 | ||
diff --git a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c index df326fe1cc8f..d2c1f42109b0 100644 --- a/drivers/net/tulip/timer.c +++ b/drivers/net/tulip/timer.c | |||
@@ -14,7 +14,6 @@ | |||
14 | 14 | ||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/pci.h> | ||
18 | #include "tulip.h" | 17 | #include "tulip.h" |
19 | 18 | ||
20 | 19 | ||
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h index c840d2e67b23..16f26a8364f0 100644 --- a/drivers/net/tulip/tulip.h +++ b/drivers/net/tulip/tulip.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/netdevice.h> | 22 | #include <linux/netdevice.h> |
23 | #include <linux/timer.h> | 23 | #include <linux/timer.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/pci.h> | ||
25 | #include <asm/io.h> | 26 | #include <asm/io.h> |
26 | #include <asm/irq.h> | 27 | #include <asm/irq.h> |
27 | 28 | ||
diff --git a/drivers/net/wan/lmc/lmc_media.c b/drivers/net/wan/lmc/lmc_media.c index ae01555d24cf..574737b55f39 100644 --- a/drivers/net/wan/lmc/lmc_media.c +++ b/drivers/net/wan/lmc/lmc_media.c | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <linux/ioport.h> | 8 | #include <linux/ioport.h> |
9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
10 | #include <linux/interrupt.h> | 10 | #include <linux/interrupt.h> |
11 | #include <linux/pci.h> | ||
12 | #include <linux/in.h> | 11 | #include <linux/in.h> |
13 | #include <linux/if_arp.h> | 12 | #include <linux/if_arp.h> |
14 | #include <linux/netdevice.h> | 13 | #include <linux/netdevice.h> |
diff --git a/drivers/net/wan/lmc/lmc_proto.c b/drivers/net/wan/lmc/lmc_proto.c index 74876c0073e8..31e1799571ad 100644 --- a/drivers/net/wan/lmc/lmc_proto.c +++ b/drivers/net/wan/lmc/lmc_proto.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/pci.h> | ||
31 | #include <linux/in.h> | 30 | #include <linux/in.h> |
32 | #include <linux/if_arp.h> | 31 | #include <linux/if_arp.h> |
33 | #include <linux/netdevice.h> | 32 | #include <linux/netdevice.h> |
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c index 07dbdfbfc15d..e24a7b095dd6 100644 --- a/drivers/net/wan/pc300_tty.c +++ b/drivers/net/wan/pc300_tty.c | |||
@@ -38,7 +38,6 @@ | |||
38 | 38 | ||
39 | #include <linux/module.h> | 39 | #include <linux/module.h> |
40 | #include <linux/kernel.h> | 40 | #include <linux/kernel.h> |
41 | #include <linux/pci.h> | ||
42 | #include <linux/errno.h> | 41 | #include <linux/errno.h> |
43 | #include <linux/string.h> | 42 | #include <linux/string.h> |
44 | #include <linux/init.h> | 43 | #include <linux/init.h> |
diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c index 9bb4db552f3c..a68b3b3761a2 100644 --- a/drivers/parisc/hppb.c +++ b/drivers/parisc/hppb.c | |||
@@ -22,8 +22,6 @@ | |||
22 | #include <asm/hardware.h> | 22 | #include <asm/hardware.h> |
23 | #include <asm/parisc-device.h> | 23 | #include <asm/parisc-device.h> |
24 | 24 | ||
25 | #include <linux/pci.h> | ||
26 | |||
27 | struct hppb_card { | 25 | struct hppb_card { |
28 | unsigned long hpa; | 26 | unsigned long hpa; |
29 | struct resource mmio_region; | 27 | struct resource mmio_region; |
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 5ea5bc70cb82..7a1d6d512837 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig | |||
@@ -1,10 +1,14 @@ | |||
1 | # | 1 | # |
2 | # PCI configuration | 2 | # PCI configuration |
3 | # | 3 | # |
4 | config ARCH_SUPPORTS_MSI | ||
5 | bool | ||
6 | default n | ||
7 | |||
4 | config PCI_MSI | 8 | config PCI_MSI |
5 | bool "Message Signaled Interrupts (MSI and MSI-X)" | 9 | bool "Message Signaled Interrupts (MSI and MSI-X)" |
6 | depends on PCI | 10 | depends on PCI |
7 | depends on (X86_LOCAL_APIC && X86_IO_APIC) || IA64 || SPARC64 | 11 | depends on ARCH_SUPPORTS_MSI |
8 | help | 12 | help |
9 | This allows device drivers to enable MSI (Message Signaled | 13 | This allows device drivers to enable MSI (Message Signaled |
10 | Interrupts). Message Signaled Interrupts enable a device to | 14 | Interrupts). Message Signaled Interrupts enable a device to |
@@ -17,31 +21,6 @@ config PCI_MSI | |||
17 | 21 | ||
18 | If you don't know what to do here, say N. | 22 | If you don't know what to do here, say N. |
19 | 23 | ||
20 | config PCI_MULTITHREAD_PROBE | ||
21 | bool "PCI Multi-threaded probe (EXPERIMENTAL)" | ||
22 | depends on PCI && EXPERIMENTAL && BROKEN | ||
23 | help | ||
24 | Say Y here if you want the PCI core to spawn a new thread for | ||
25 | every PCI device that is probed. This can cause a huge | ||
26 | speedup in boot times on multiprocessor machines, and even a | ||
27 | smaller speedup on single processor machines. | ||
28 | |||
29 | But it can also cause lots of bad things to happen. A number | ||
30 | of PCI drivers cannot properly handle running in this way, | ||
31 | some will just not work properly at all, while others might | ||
32 | decide to blow up power supplies with a huge load all at once, | ||
33 | so use this option at your own risk. | ||
34 | |||
35 | It is very unwise to use this option if you are not using a | ||
36 | boot process that can handle devices being created in any | ||
37 | order. A program that can create persistent block and network | ||
38 | device names (like udev) is a good idea if you wish to use | ||
39 | this option. | ||
40 | |||
41 | Again, use this option at your own risk, you have been warned! | ||
42 | |||
43 | When in doubt, say N. | ||
44 | |||
45 | config PCI_DEBUG | 24 | config PCI_DEBUG |
46 | bool "PCI Debugging" | 25 | bool "PCI Debugging" |
47 | depends on PCI && DEBUG_KERNEL | 26 | depends on PCI && DEBUG_KERNEL |
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index aadaa3c8096b..9e5ea074ad20 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c | |||
@@ -77,7 +77,7 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, | |||
77 | * This adds a single pci device to the global | 77 | * This adds a single pci device to the global |
78 | * device list and adds sysfs and procfs entries | 78 | * device list and adds sysfs and procfs entries |
79 | */ | 79 | */ |
80 | int __devinit pci_bus_add_device(struct pci_dev *dev) | 80 | int pci_bus_add_device(struct pci_dev *dev) |
81 | { | 81 | { |
82 | int retval; | 82 | int retval; |
83 | retval = device_add(&dev->dev); | 83 | retval = device_add(&dev->dev); |
@@ -105,7 +105,7 @@ int __devinit pci_bus_add_device(struct pci_dev *dev) | |||
105 | * | 105 | * |
106 | * Call hotplug for each new devices. | 106 | * Call hotplug for each new devices. |
107 | */ | 107 | */ |
108 | void __devinit pci_bus_add_devices(struct pci_bus *bus) | 108 | void pci_bus_add_devices(struct pci_bus *bus) |
109 | { | 109 | { |
110 | struct pci_dev *dev; | 110 | struct pci_dev *dev; |
111 | int retval; | 111 | int retval; |
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index be92695a7833..63d62752fb91 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig | |||
@@ -2,9 +2,7 @@ | |||
2 | # PCI Hotplug support | 2 | # PCI Hotplug support |
3 | # | 3 | # |
4 | 4 | ||
5 | menu "PCI Hotplug Support" | 5 | menuconfig HOTPLUG_PCI |
6 | |||
7 | config HOTPLUG_PCI | ||
8 | tristate "Support for PCI Hotplug (EXPERIMENTAL)" | 6 | tristate "Support for PCI Hotplug (EXPERIMENTAL)" |
9 | depends on PCI && EXPERIMENTAL && HOTPLUG | 7 | depends on PCI && EXPERIMENTAL && HOTPLUG |
10 | ---help--- | 8 | ---help--- |
@@ -17,9 +15,10 @@ config HOTPLUG_PCI | |||
17 | 15 | ||
18 | When in doubt, say N. | 16 | When in doubt, say N. |
19 | 17 | ||
18 | if HOTPLUG_PCI | ||
19 | |||
20 | config HOTPLUG_PCI_FAKE | 20 | config HOTPLUG_PCI_FAKE |
21 | tristate "Fake PCI Hotplug driver" | 21 | tristate "Fake PCI Hotplug driver" |
22 | depends on HOTPLUG_PCI | ||
23 | help | 22 | help |
24 | Say Y here if you want to use the fake PCI hotplug driver. It can | 23 | Say Y here if you want to use the fake PCI hotplug driver. It can |
25 | be used to simulate PCI hotplug events if even if your system is | 24 | be used to simulate PCI hotplug events if even if your system is |
@@ -42,7 +41,7 @@ config HOTPLUG_PCI_FAKE | |||
42 | 41 | ||
43 | config HOTPLUG_PCI_COMPAQ | 42 | config HOTPLUG_PCI_COMPAQ |
44 | tristate "Compaq PCI Hotplug driver" | 43 | tristate "Compaq PCI Hotplug driver" |
45 | depends on HOTPLUG_PCI && X86 && PCI_BIOS | 44 | depends on X86 && PCI_BIOS |
46 | help | 45 | help |
47 | Say Y here if you have a motherboard with a Compaq PCI Hotplug | 46 | Say Y here if you have a motherboard with a Compaq PCI Hotplug |
48 | controller. | 47 | controller. |
@@ -64,7 +63,7 @@ config HOTPLUG_PCI_COMPAQ_NVRAM | |||
64 | 63 | ||
65 | config HOTPLUG_PCI_IBM | 64 | config HOTPLUG_PCI_IBM |
66 | tristate "IBM PCI Hotplug driver" | 65 | tristate "IBM PCI Hotplug driver" |
67 | depends on HOTPLUG_PCI && X86_IO_APIC && X86 && PCI_BIOS | 66 | depends on X86_IO_APIC && X86 && PCI_BIOS |
68 | help | 67 | help |
69 | Say Y here if you have a motherboard with a IBM PCI Hotplug | 68 | Say Y here if you have a motherboard with a IBM PCI Hotplug |
70 | controller. | 69 | controller. |
@@ -76,7 +75,6 @@ config HOTPLUG_PCI_IBM | |||
76 | 75 | ||
77 | config HOTPLUG_PCI_ACPI | 76 | config HOTPLUG_PCI_ACPI |
78 | tristate "ACPI PCI Hotplug driver" | 77 | tristate "ACPI PCI Hotplug driver" |
79 | depends on HOTPLUG_PCI | ||
80 | depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK) | 78 | depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK) |
81 | help | 79 | help |
82 | Say Y here if you have a system that supports PCI Hotplug using | 80 | Say Y here if you have a system that supports PCI Hotplug using |
@@ -101,7 +99,6 @@ config HOTPLUG_PCI_ACPI_IBM | |||
101 | 99 | ||
102 | config HOTPLUG_PCI_CPCI | 100 | config HOTPLUG_PCI_CPCI |
103 | bool "CompactPCI Hotplug driver" | 101 | bool "CompactPCI Hotplug driver" |
104 | depends on HOTPLUG_PCI | ||
105 | help | 102 | help |
106 | Say Y here if you have a CompactPCI system card with CompactPCI | 103 | Say Y here if you have a CompactPCI system card with CompactPCI |
107 | hotswap support per the PICMG 2.1 specification. | 104 | hotswap support per the PICMG 2.1 specification. |
@@ -110,7 +107,7 @@ config HOTPLUG_PCI_CPCI | |||
110 | 107 | ||
111 | config HOTPLUG_PCI_CPCI_ZT5550 | 108 | config HOTPLUG_PCI_CPCI_ZT5550 |
112 | tristate "Ziatech ZT5550 CompactPCI Hotplug driver" | 109 | tristate "Ziatech ZT5550 CompactPCI Hotplug driver" |
113 | depends on HOTPLUG_PCI && HOTPLUG_PCI_CPCI && X86 | 110 | depends on HOTPLUG_PCI_CPCI && X86 |
114 | help | 111 | help |
115 | Say Y here if you have an Performance Technologies (formerly Intel, | 112 | Say Y here if you have an Performance Technologies (formerly Intel, |
116 | formerly just Ziatech) Ziatech ZT5550 CompactPCI system card. | 113 | formerly just Ziatech) Ziatech ZT5550 CompactPCI system card. |
@@ -122,7 +119,7 @@ config HOTPLUG_PCI_CPCI_ZT5550 | |||
122 | 119 | ||
123 | config HOTPLUG_PCI_CPCI_GENERIC | 120 | config HOTPLUG_PCI_CPCI_GENERIC |
124 | tristate "Generic port I/O CompactPCI Hotplug driver" | 121 | tristate "Generic port I/O CompactPCI Hotplug driver" |
125 | depends on HOTPLUG_PCI && HOTPLUG_PCI_CPCI && X86 | 122 | depends on HOTPLUG_PCI_CPCI && X86 |
126 | help | 123 | help |
127 | Say Y here if you have a CompactPCI system card that exposes the #ENUM | 124 | Say Y here if you have a CompactPCI system card that exposes the #ENUM |
128 | hotswap signal as a bit in a system register that can be read through | 125 | hotswap signal as a bit in a system register that can be read through |
@@ -135,7 +132,6 @@ config HOTPLUG_PCI_CPCI_GENERIC | |||
135 | 132 | ||
136 | config HOTPLUG_PCI_SHPC | 133 | config HOTPLUG_PCI_SHPC |
137 | tristate "SHPC PCI Hotplug driver" | 134 | tristate "SHPC PCI Hotplug driver" |
138 | depends on HOTPLUG_PCI | ||
139 | help | 135 | help |
140 | Say Y here if you have a motherboard with a SHPC PCI Hotplug | 136 | Say Y here if you have a motherboard with a SHPC PCI Hotplug |
141 | controller. | 137 | controller. |
@@ -147,7 +143,7 @@ config HOTPLUG_PCI_SHPC | |||
147 | 143 | ||
148 | config HOTPLUG_PCI_RPA | 144 | config HOTPLUG_PCI_RPA |
149 | tristate "RPA PCI Hotplug driver" | 145 | tristate "RPA PCI Hotplug driver" |
150 | depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE | 146 | depends on PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE |
151 | help | 147 | help |
152 | Say Y here if you have a RPA system that supports PCI Hotplug. | 148 | Say Y here if you have a RPA system that supports PCI Hotplug. |
153 | 149 | ||
@@ -170,12 +166,11 @@ config HOTPLUG_PCI_RPA_DLPAR | |||
170 | 166 | ||
171 | config HOTPLUG_PCI_SGI | 167 | config HOTPLUG_PCI_SGI |
172 | tristate "SGI PCI Hotplug Support" | 168 | tristate "SGI PCI Hotplug Support" |
173 | depends on HOTPLUG_PCI && (IA64_SGI_SN2 || IA64_GENERIC) | 169 | depends on IA64_SGI_SN2 || IA64_GENERIC |
174 | help | 170 | help |
175 | Say Y here if you want to use the SGI Altix Hotplug | 171 | Say Y here if you want to use the SGI Altix Hotplug |
176 | Driver for PCI devices. | 172 | Driver for PCI devices. |
177 | 173 | ||
178 | When in doubt, say N. | 174 | When in doubt, say N. |
179 | 175 | ||
180 | endmenu | 176 | endif # HOTPLUG_PCI |
181 | |||
diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c index 1c12e9171097..41f6a8d79c81 100644 --- a/drivers/pci/hotplug/cpcihp_zt5550.c +++ b/drivers/pci/hotplug/cpcihp_zt5550.c | |||
@@ -296,13 +296,17 @@ static struct pci_driver zt5550_hc_driver = { | |||
296 | static int __init zt5550_init(void) | 296 | static int __init zt5550_init(void) |
297 | { | 297 | { |
298 | struct resource* r; | 298 | struct resource* r; |
299 | int rc; | ||
299 | 300 | ||
300 | info(DRIVER_DESC " version: " DRIVER_VERSION); | 301 | info(DRIVER_DESC " version: " DRIVER_VERSION); |
301 | r = request_region(ENUM_PORT, 1, "#ENUM hotswap signal register"); | 302 | r = request_region(ENUM_PORT, 1, "#ENUM hotswap signal register"); |
302 | if(!r) | 303 | if(!r) |
303 | return -EBUSY; | 304 | return -EBUSY; |
304 | 305 | ||
305 | return pci_register_driver(&zt5550_hc_driver); | 306 | rc = pci_register_driver(&zt5550_hc_driver); |
307 | if(rc < 0) | ||
308 | release_region(ENUM_PORT, 1); | ||
309 | return rc; | ||
306 | } | 310 | } |
307 | 311 | ||
308 | static void __exit | 312 | static void __exit |
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index e27907c91d92..027f6865d7e3 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c | |||
@@ -238,7 +238,7 @@ static void pci_rescan_bus(const struct pci_bus *bus) | |||
238 | { | 238 | { |
239 | unsigned int devfn; | 239 | unsigned int devfn; |
240 | struct pci_dev *dev; | 240 | struct pci_dev *dev; |
241 | dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); | 241 | dev = alloc_pci_dev(); |
242 | if (!dev) | 242 | if (!dev) |
243 | return; | 243 | return; |
244 | 244 | ||
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index d19fcae8a7c0..ccc57627201e 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -43,6 +43,7 @@ extern int pciehp_poll_mode; | |||
43 | extern int pciehp_poll_time; | 43 | extern int pciehp_poll_time; |
44 | extern int pciehp_debug; | 44 | extern int pciehp_debug; |
45 | extern int pciehp_force; | 45 | extern int pciehp_force; |
46 | extern struct workqueue_struct *pciehp_wq; | ||
46 | 47 | ||
47 | #define dbg(format, arg...) \ | 48 | #define dbg(format, arg...) \ |
48 | do { \ | 49 | do { \ |
@@ -70,14 +71,16 @@ struct slot { | |||
70 | struct list_head slot_list; | 71 | struct list_head slot_list; |
71 | char name[SLOT_NAME_SIZE]; | 72 | char name[SLOT_NAME_SIZE]; |
72 | unsigned long last_emi_toggle; | 73 | unsigned long last_emi_toggle; |
74 | struct delayed_work work; /* work for button event */ | ||
75 | struct mutex lock; | ||
73 | }; | 76 | }; |
74 | 77 | ||
75 | struct event_info { | 78 | struct event_info { |
76 | u32 event_type; | 79 | u32 event_type; |
77 | u8 hp_slot; | 80 | struct slot *p_slot; |
81 | struct work_struct work; | ||
78 | }; | 82 | }; |
79 | 83 | ||
80 | #define MAX_EVENTS 10 | ||
81 | struct controller { | 84 | struct controller { |
82 | struct controller *next; | 85 | struct controller *next; |
83 | struct mutex crit_sect; /* critical section mutex */ | 86 | struct mutex crit_sect; /* critical section mutex */ |
@@ -86,11 +89,9 @@ struct controller { | |||
86 | int slot_num_inc; /* 1 or -1 */ | 89 | int slot_num_inc; /* 1 or -1 */ |
87 | struct pci_dev *pci_dev; | 90 | struct pci_dev *pci_dev; |
88 | struct list_head slot_list; | 91 | struct list_head slot_list; |
89 | struct event_info event_queue[MAX_EVENTS]; | ||
90 | struct slot *slot; | 92 | struct slot *slot; |
91 | struct hpc_ops *hpc_ops; | 93 | struct hpc_ops *hpc_ops; |
92 | wait_queue_head_t queue; /* sleep & wake process */ | 94 | wait_queue_head_t queue; /* sleep & wake process */ |
93 | u8 next_event; | ||
94 | u8 bus; | 95 | u8 bus; |
95 | u8 device; | 96 | u8 device; |
96 | u8 function; | 97 | u8 function; |
@@ -149,21 +150,17 @@ struct controller { | |||
149 | #define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP) | 150 | #define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP) |
150 | #define EMI(cap) (cap & EMI_PRSN) | 151 | #define EMI(cap) (cap & EMI_PRSN) |
151 | 152 | ||
152 | extern int pciehp_event_start_thread(void); | 153 | extern int pciehp_sysfs_enable_slot(struct slot *slot); |
153 | extern void pciehp_event_stop_thread(void); | 154 | extern int pciehp_sysfs_disable_slot(struct slot *slot); |
154 | extern int pciehp_enable_slot(struct slot *slot); | ||
155 | extern int pciehp_disable_slot(struct slot *slot); | ||
156 | extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl); | 155 | extern u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl); |
157 | extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl); | 156 | extern u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl); |
158 | extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl); | 157 | extern u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl); |
159 | extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl); | 158 | extern u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl); |
160 | extern int pciehp_configure_device(struct slot *p_slot); | 159 | extern int pciehp_configure_device(struct slot *p_slot); |
161 | extern int pciehp_unconfigure_device(struct slot *p_slot); | 160 | extern int pciehp_unconfigure_device(struct slot *p_slot); |
161 | extern void pciehp_queue_pushbutton_work(struct work_struct *work); | ||
162 | int pcie_init(struct controller *ctrl, struct pcie_device *dev); | 162 | int pcie_init(struct controller *ctrl, struct pcie_device *dev); |
163 | 163 | ||
164 | /* Global variables */ | ||
165 | extern struct controller *pciehp_ctrl_list; | ||
166 | |||
167 | static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) | 164 | static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) |
168 | { | 165 | { |
169 | struct slot *slot; | 166 | struct slot *slot; |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index a92eda6e02f6..e5d3f0b4f45a 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -41,7 +41,7 @@ int pciehp_debug; | |||
41 | int pciehp_poll_mode; | 41 | int pciehp_poll_mode; |
42 | int pciehp_poll_time; | 42 | int pciehp_poll_time; |
43 | int pciehp_force; | 43 | int pciehp_force; |
44 | struct controller *pciehp_ctrl_list; | 44 | struct workqueue_struct *pciehp_wq; |
45 | 45 | ||
46 | #define DRIVER_VERSION "0.4" | 46 | #define DRIVER_VERSION "0.4" |
47 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" | 47 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" |
@@ -62,7 +62,6 @@ MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing" | |||
62 | 62 | ||
63 | #define PCIE_MODULE_NAME "pciehp" | 63 | #define PCIE_MODULE_NAME "pciehp" |
64 | 64 | ||
65 | static int pcie_start_thread (void); | ||
66 | static int set_attention_status (struct hotplug_slot *slot, u8 value); | 65 | static int set_attention_status (struct hotplug_slot *slot, u8 value); |
67 | static int enable_slot (struct hotplug_slot *slot); | 66 | static int enable_slot (struct hotplug_slot *slot); |
68 | static int disable_slot (struct hotplug_slot *slot); | 67 | static int disable_slot (struct hotplug_slot *slot); |
@@ -229,6 +228,8 @@ static int init_slots(struct controller *ctrl) | |||
229 | slot->device = ctrl->slot_device_offset + i; | 228 | slot->device = ctrl->slot_device_offset + i; |
230 | slot->hpc_ops = ctrl->hpc_ops; | 229 | slot->hpc_ops = ctrl->hpc_ops; |
231 | slot->number = ctrl->first_slot; | 230 | slot->number = ctrl->first_slot; |
231 | mutex_init(&slot->lock); | ||
232 | INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); | ||
232 | 233 | ||
233 | /* register this slot with the hotplug pci core */ | 234 | /* register this slot with the hotplug pci core */ |
234 | hotplug_slot->private = slot; | 235 | hotplug_slot->private = slot; |
@@ -286,6 +287,9 @@ static void cleanup_slots(struct controller *ctrl) | |||
286 | if (EMI(ctrl->ctrlcap)) | 287 | if (EMI(ctrl->ctrlcap)) |
287 | sysfs_remove_file(&slot->hotplug_slot->kobj, | 288 | sysfs_remove_file(&slot->hotplug_slot->kobj, |
288 | &hotplug_slot_attr_lock.attr); | 289 | &hotplug_slot_attr_lock.attr); |
290 | cancel_delayed_work(&slot->work); | ||
291 | flush_scheduled_work(); | ||
292 | flush_workqueue(pciehp_wq); | ||
289 | pci_hp_deregister(slot->hotplug_slot); | 293 | pci_hp_deregister(slot->hotplug_slot); |
290 | } | 294 | } |
291 | } | 295 | } |
@@ -314,7 +318,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) | |||
314 | 318 | ||
315 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 319 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
316 | 320 | ||
317 | return pciehp_enable_slot(slot); | 321 | return pciehp_sysfs_enable_slot(slot); |
318 | } | 322 | } |
319 | 323 | ||
320 | 324 | ||
@@ -324,7 +328,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) | |||
324 | 328 | ||
325 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); | 329 | dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); |
326 | 330 | ||
327 | return pciehp_disable_slot(slot); | 331 | return pciehp_sysfs_disable_slot(slot); |
328 | } | 332 | } |
329 | 333 | ||
330 | static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) | 334 | static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) |
@@ -466,17 +470,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
466 | 470 | ||
467 | t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); | 471 | t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); |
468 | 472 | ||
469 | /* Finish setting up the hot plug ctrl device */ | ||
470 | ctrl->next_event = 0; | ||
471 | |||
472 | if (!pciehp_ctrl_list) { | ||
473 | pciehp_ctrl_list = ctrl; | ||
474 | ctrl->next = NULL; | ||
475 | } else { | ||
476 | ctrl->next = pciehp_ctrl_list; | ||
477 | pciehp_ctrl_list = ctrl; | ||
478 | } | ||
479 | |||
480 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ | 473 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ |
481 | if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { | 474 | if ((POWER_CTRL(ctrl->ctrlcap)) && !value) { |
482 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ | 475 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ |
@@ -496,48 +489,14 @@ err_out_none: | |||
496 | return -ENODEV; | 489 | return -ENODEV; |
497 | } | 490 | } |
498 | 491 | ||
499 | 492 | static void pciehp_remove (struct pcie_device *dev) | |
500 | static int pcie_start_thread(void) | ||
501 | { | 493 | { |
502 | int retval = 0; | 494 | struct pci_dev *pdev = dev->port; |
503 | 495 | struct controller *ctrl = pci_get_drvdata(pdev); | |
504 | dbg("Initialize + Start the notification/polling mechanism \n"); | ||
505 | |||
506 | retval = pciehp_event_start_thread(); | ||
507 | if (retval) { | ||
508 | dbg("pciehp_event_start_thread() failed\n"); | ||
509 | return retval; | ||
510 | } | ||
511 | |||
512 | return retval; | ||
513 | } | ||
514 | |||
515 | static void __exit unload_pciehpd(void) | ||
516 | { | ||
517 | struct controller *ctrl; | ||
518 | struct controller *tctrl; | ||
519 | |||
520 | ctrl = pciehp_ctrl_list; | ||
521 | |||
522 | while (ctrl) { | ||
523 | cleanup_slots(ctrl); | ||
524 | 496 | ||
525 | ctrl->hpc_ops->release_ctlr(ctrl); | 497 | cleanup_slots(ctrl); |
526 | 498 | ctrl->hpc_ops->release_ctlr(ctrl); | |
527 | tctrl = ctrl; | 499 | kfree(ctrl); |
528 | ctrl = ctrl->next; | ||
529 | |||
530 | kfree(tctrl); | ||
531 | } | ||
532 | |||
533 | /* Stop the notification mechanism */ | ||
534 | pciehp_event_stop_thread(); | ||
535 | |||
536 | } | ||
537 | |||
538 | static void pciehp_remove (struct pcie_device *device) | ||
539 | { | ||
540 | /* XXX - Needs to be adapted to device driver model */ | ||
541 | } | 500 | } |
542 | 501 | ||
543 | #ifdef CONFIG_PM | 502 | #ifdef CONFIG_PM |
@@ -585,31 +544,18 @@ static int __init pcied_init(void) | |||
585 | pciehp_poll_mode = 1; | 544 | pciehp_poll_mode = 1; |
586 | #endif | 545 | #endif |
587 | 546 | ||
588 | retval = pcie_start_thread(); | ||
589 | if (retval) | ||
590 | goto error_hpc_init; | ||
591 | |||
592 | retval = pcie_port_service_register(&hpdriver_portdrv); | 547 | retval = pcie_port_service_register(&hpdriver_portdrv); |
593 | dbg("pcie_port_service_register = %d\n", retval); | 548 | dbg("pcie_port_service_register = %d\n", retval); |
594 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 549 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
595 | if (retval) | 550 | if (retval) |
596 | dbg("%s: Failure to register service\n", __FUNCTION__); | 551 | dbg("%s: Failure to register service\n", __FUNCTION__); |
597 | |||
598 | error_hpc_init: | ||
599 | if (retval) { | ||
600 | pciehp_event_stop_thread(); | ||
601 | }; | ||
602 | |||
603 | return retval; | 552 | return retval; |
604 | } | 553 | } |
605 | 554 | ||
606 | static void __exit pcied_cleanup(void) | 555 | static void __exit pcied_cleanup(void) |
607 | { | 556 | { |
608 | dbg("unload_pciehpd()\n"); | 557 | dbg("unload_pciehpd()\n"); |
609 | unload_pciehpd(); | ||
610 | |||
611 | pcie_port_service_unregister(&hpdriver_portdrv); | 558 | pcie_port_service_unregister(&hpdriver_portdrv); |
612 | |||
613 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); | 559 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); |
614 | } | 560 | } |
615 | 561 | ||
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 4283ef56dbd9..7f22caa70178 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -32,92 +32,61 @@ | |||
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/smp_lock.h> | 33 | #include <linux/smp_lock.h> |
34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
35 | #include <linux/workqueue.h> | ||
35 | #include "../pci.h" | 36 | #include "../pci.h" |
36 | #include "pciehp.h" | 37 | #include "pciehp.h" |
37 | 38 | ||
38 | static void interrupt_event_handler(struct controller *ctrl); | 39 | static void interrupt_event_handler(struct work_struct *work); |
40 | static int pciehp_enable_slot(struct slot *p_slot); | ||
41 | static int pciehp_disable_slot(struct slot *p_slot); | ||
39 | 42 | ||
40 | static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ | 43 | static int queue_interrupt_event(struct slot *p_slot, u32 event_type) |
41 | static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */ | ||
42 | static int event_finished; | ||
43 | static unsigned long pushbutton_pending; /* = 0 */ | ||
44 | static unsigned long surprise_rm_pending; /* = 0 */ | ||
45 | |||
46 | static inline char *slot_name(struct slot *p_slot) | ||
47 | { | 44 | { |
48 | return p_slot->hotplug_slot->name; | 45 | struct event_info *info; |
46 | |||
47 | info = kmalloc(sizeof(*info), GFP_ATOMIC); | ||
48 | if (!info) | ||
49 | return -ENOMEM; | ||
50 | |||
51 | info->event_type = event_type; | ||
52 | info->p_slot = p_slot; | ||
53 | INIT_WORK(&info->work, interrupt_event_handler); | ||
54 | |||
55 | schedule_work(&info->work); | ||
56 | |||
57 | return 0; | ||
49 | } | 58 | } |
50 | 59 | ||
51 | u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl) | 60 | u8 pciehp_handle_attention_button(u8 hp_slot, struct controller *ctrl) |
52 | { | 61 | { |
53 | struct slot *p_slot; | 62 | struct slot *p_slot; |
54 | u8 rc = 0; | 63 | u32 event_type; |
55 | u8 getstatus; | ||
56 | struct event_info *taskInfo; | ||
57 | 64 | ||
58 | /* Attention Button Change */ | 65 | /* Attention Button Change */ |
59 | dbg("pciehp: Attention button interrupt received.\n"); | 66 | dbg("pciehp: Attention button interrupt received.\n"); |
60 | |||
61 | /* This is the structure that tells the worker thread what to do */ | ||
62 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | ||
63 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | ||
64 | |||
65 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | ||
66 | |||
67 | ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; | ||
68 | taskInfo->hp_slot = hp_slot; | ||
69 | 67 | ||
70 | rc++; | 68 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
71 | 69 | ||
72 | /* | 70 | /* |
73 | * Button pressed - See if need to TAKE ACTION!!! | 71 | * Button pressed - See if need to TAKE ACTION!!! |
74 | */ | 72 | */ |
75 | info("Button pressed on Slot(%s)\n", slot_name(p_slot)); | 73 | info("Button pressed on Slot(%s)\n", p_slot->name); |
76 | taskInfo->event_type = INT_BUTTON_PRESS; | 74 | event_type = INT_BUTTON_PRESS; |
77 | |||
78 | if ((p_slot->state == BLINKINGON_STATE) | ||
79 | || (p_slot->state == BLINKINGOFF_STATE)) { | ||
80 | /* Cancel if we are still blinking; this means that we press the | ||
81 | * attention again before the 5 sec. limit expires to cancel hot-add | ||
82 | * or hot-remove | ||
83 | */ | ||
84 | taskInfo->event_type = INT_BUTTON_CANCEL; | ||
85 | info("Button cancel on Slot(%s)\n", slot_name(p_slot)); | ||
86 | } else if ((p_slot->state == POWERON_STATE) | ||
87 | || (p_slot->state == POWEROFF_STATE)) { | ||
88 | /* Ignore if the slot is on power-on or power-off state; this | ||
89 | * means that the previous attention button action to hot-add or | ||
90 | * hot-remove is undergoing | ||
91 | */ | ||
92 | taskInfo->event_type = INT_BUTTON_IGNORE; | ||
93 | info("Button ignore on Slot(%s)\n", slot_name(p_slot)); | ||
94 | } | ||
95 | 75 | ||
96 | if (rc) | 76 | queue_interrupt_event(p_slot, event_type); |
97 | up(&event_semaphore); /* signal event thread that new event is posted */ | ||
98 | 77 | ||
99 | return 0; | 78 | return 0; |
100 | |||
101 | } | 79 | } |
102 | 80 | ||
103 | u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl) | 81 | u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl) |
104 | { | 82 | { |
105 | struct slot *p_slot; | 83 | struct slot *p_slot; |
106 | u8 rc = 0; | ||
107 | u8 getstatus; | 84 | u8 getstatus; |
108 | struct event_info *taskInfo; | 85 | u32 event_type; |
109 | 86 | ||
110 | /* Switch Change */ | 87 | /* Switch Change */ |
111 | dbg("pciehp: Switch interrupt received.\n"); | 88 | dbg("pciehp: Switch interrupt received.\n"); |
112 | 89 | ||
113 | /* This is the structure that tells the worker thread | ||
114 | * what to do | ||
115 | */ | ||
116 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | ||
117 | ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; | ||
118 | taskInfo->hp_slot = hp_slot; | ||
119 | |||
120 | rc++; | ||
121 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 90 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
122 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 91 | p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
123 | 92 | ||
@@ -125,39 +94,30 @@ u8 pciehp_handle_switch_change(u8 hp_slot, struct controller *ctrl) | |||
125 | /* | 94 | /* |
126 | * Switch opened | 95 | * Switch opened |
127 | */ | 96 | */ |
128 | info("Latch open on Slot(%s)\n", slot_name(p_slot)); | 97 | info("Latch open on Slot(%s)\n", p_slot->name); |
129 | taskInfo->event_type = INT_SWITCH_OPEN; | 98 | event_type = INT_SWITCH_OPEN; |
130 | } else { | 99 | } else { |
131 | /* | 100 | /* |
132 | * Switch closed | 101 | * Switch closed |
133 | */ | 102 | */ |
134 | info("Latch close on Slot(%s)\n", slot_name(p_slot)); | 103 | info("Latch close on Slot(%s)\n", p_slot->name); |
135 | taskInfo->event_type = INT_SWITCH_CLOSE; | 104 | event_type = INT_SWITCH_CLOSE; |
136 | } | 105 | } |
137 | 106 | ||
138 | if (rc) | 107 | queue_interrupt_event(p_slot, event_type); |
139 | up(&event_semaphore); /* signal event thread that new event is posted */ | ||
140 | 108 | ||
141 | return rc; | 109 | return 1; |
142 | } | 110 | } |
143 | 111 | ||
144 | u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl) | 112 | u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl) |
145 | { | 113 | { |
146 | struct slot *p_slot; | 114 | struct slot *p_slot; |
147 | u8 presence_save, rc = 0; | 115 | u32 event_type; |
148 | struct event_info *taskInfo; | 116 | u8 presence_save; |
149 | 117 | ||
150 | /* Presence Change */ | 118 | /* Presence Change */ |
151 | dbg("pciehp: Presence/Notify input change.\n"); | 119 | dbg("pciehp: Presence/Notify input change.\n"); |
152 | 120 | ||
153 | /* This is the structure that tells the worker thread | ||
154 | * what to do | ||
155 | */ | ||
156 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | ||
157 | ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; | ||
158 | taskInfo->hp_slot = hp_slot; | ||
159 | |||
160 | rc++; | ||
161 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 121 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
162 | 122 | ||
163 | /* Switch is open, assume a presence change | 123 | /* Switch is open, assume a presence change |
@@ -168,59 +128,49 @@ u8 pciehp_handle_presence_change(u8 hp_slot, struct controller *ctrl) | |||
168 | /* | 128 | /* |
169 | * Card Present | 129 | * Card Present |
170 | */ | 130 | */ |
171 | info("Card present on Slot(%s)\n", slot_name(p_slot)); | 131 | info("Card present on Slot(%s)\n", p_slot->name); |
172 | taskInfo->event_type = INT_PRESENCE_ON; | 132 | event_type = INT_PRESENCE_ON; |
173 | } else { | 133 | } else { |
174 | /* | 134 | /* |
175 | * Not Present | 135 | * Not Present |
176 | */ | 136 | */ |
177 | info("Card not present on Slot(%s)\n", slot_name(p_slot)); | 137 | info("Card not present on Slot(%s)\n", p_slot->name); |
178 | taskInfo->event_type = INT_PRESENCE_OFF; | 138 | event_type = INT_PRESENCE_OFF; |
179 | } | 139 | } |
180 | 140 | ||
181 | if (rc) | 141 | queue_interrupt_event(p_slot, event_type); |
182 | up(&event_semaphore); /* signal event thread that new event is posted */ | ||
183 | 142 | ||
184 | return rc; | 143 | return 1; |
185 | } | 144 | } |
186 | 145 | ||
187 | u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) | 146 | u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl) |
188 | { | 147 | { |
189 | struct slot *p_slot; | 148 | struct slot *p_slot; |
190 | u8 rc = 0; | 149 | u32 event_type; |
191 | struct event_info *taskInfo; | ||
192 | 150 | ||
193 | /* power fault */ | 151 | /* power fault */ |
194 | dbg("pciehp: Power fault interrupt received.\n"); | 152 | dbg("pciehp: Power fault interrupt received.\n"); |
195 | 153 | ||
196 | /* this is the structure that tells the worker thread | ||
197 | * what to do | ||
198 | */ | ||
199 | taskInfo = &(ctrl->event_queue[ctrl->next_event]); | ||
200 | ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS; | ||
201 | taskInfo->hp_slot = hp_slot; | ||
202 | |||
203 | rc++; | ||
204 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 154 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); |
205 | 155 | ||
206 | if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { | 156 | if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { |
207 | /* | 157 | /* |
208 | * power fault Cleared | 158 | * power fault Cleared |
209 | */ | 159 | */ |
210 | info("Power fault cleared on Slot(%s)\n", slot_name(p_slot)); | 160 | info("Power fault cleared on Slot(%s)\n", p_slot->name); |
211 | taskInfo->event_type = INT_POWER_FAULT_CLEAR; | 161 | event_type = INT_POWER_FAULT_CLEAR; |
212 | } else { | 162 | } else { |
213 | /* | 163 | /* |
214 | * power fault | 164 | * power fault |
215 | */ | 165 | */ |
216 | info("Power fault on Slot(%s)\n", slot_name(p_slot)); | 166 | info("Power fault on Slot(%s)\n", p_slot->name); |
217 | taskInfo->event_type = INT_POWER_FAULT; | 167 | event_type = INT_POWER_FAULT; |
218 | info("power fault bit %x set\n", hp_slot); | 168 | info("power fault bit %x set\n", hp_slot); |
219 | } | 169 | } |
220 | if (rc) | ||
221 | up(&event_semaphore); /* signal event thread that new event is posted */ | ||
222 | 170 | ||
223 | return rc; | 171 | queue_interrupt_event(p_slot, event_type); |
172 | |||
173 | return 1; | ||
224 | } | 174 | } |
225 | 175 | ||
226 | /* The following routines constitute the bulk of the | 176 | /* The following routines constitute the bulk of the |
@@ -357,13 +307,10 @@ static int remove_board(struct slot *p_slot) | |||
357 | return 0; | 307 | return 0; |
358 | } | 308 | } |
359 | 309 | ||
360 | 310 | struct power_work_info { | |
361 | static void pushbutton_helper_thread(unsigned long data) | 311 | struct slot *p_slot; |
362 | { | 312 | struct work_struct work; |
363 | pushbutton_pending = data; | 313 | }; |
364 | |||
365 | up(&event_semaphore); | ||
366 | } | ||
367 | 314 | ||
368 | /** | 315 | /** |
369 | * pciehp_pushbutton_thread | 316 | * pciehp_pushbutton_thread |
@@ -372,276 +319,214 @@ static void pushbutton_helper_thread(unsigned long data) | |||
372 | * Handles all pending events and exits. | 319 | * Handles all pending events and exits. |
373 | * | 320 | * |
374 | */ | 321 | */ |
375 | static void pciehp_pushbutton_thread(unsigned long slot) | 322 | static void pciehp_power_thread(struct work_struct *work) |
376 | { | 323 | { |
377 | struct slot *p_slot = (struct slot *) slot; | 324 | struct power_work_info *info = |
378 | u8 getstatus; | 325 | container_of(work, struct power_work_info, work); |
379 | 326 | struct slot *p_slot = info->p_slot; | |
380 | pushbutton_pending = 0; | 327 | |
381 | 328 | mutex_lock(&p_slot->lock); | |
382 | if (!p_slot) { | 329 | switch (p_slot->state) { |
383 | dbg("%s: Error! slot NULL\n", __FUNCTION__); | 330 | case POWEROFF_STATE: |
384 | return; | 331 | mutex_unlock(&p_slot->lock); |
385 | } | 332 | dbg("%s: disabling bus:device(%x:%x)\n", |
386 | 333 | __FUNCTION__, p_slot->bus, p_slot->device); | |
387 | p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | ||
388 | if (getstatus) { | ||
389 | p_slot->state = POWEROFF_STATE; | ||
390 | dbg("%s: disabling bus:device(%x:%x)\n", __FUNCTION__, | ||
391 | p_slot->bus, p_slot->device); | ||
392 | |||
393 | pciehp_disable_slot(p_slot); | 334 | pciehp_disable_slot(p_slot); |
335 | mutex_lock(&p_slot->lock); | ||
394 | p_slot->state = STATIC_STATE; | 336 | p_slot->state = STATIC_STATE; |
395 | } else { | 337 | break; |
396 | p_slot->state = POWERON_STATE; | 338 | case POWERON_STATE: |
397 | dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__, | 339 | mutex_unlock(&p_slot->lock); |
398 | p_slot->bus, p_slot->device); | ||
399 | |||
400 | if (pciehp_enable_slot(p_slot) && | 340 | if (pciehp_enable_slot(p_slot) && |
401 | PWR_LED(p_slot->ctrl->ctrlcap)) | 341 | PWR_LED(p_slot->ctrl->ctrlcap)) |
402 | p_slot->hpc_ops->green_led_off(p_slot); | 342 | p_slot->hpc_ops->green_led_off(p_slot); |
403 | 343 | mutex_lock(&p_slot->lock); | |
404 | p_slot->state = STATIC_STATE; | 344 | p_slot->state = STATIC_STATE; |
345 | break; | ||
346 | default: | ||
347 | break; | ||
405 | } | 348 | } |
349 | mutex_unlock(&p_slot->lock); | ||
406 | 350 | ||
407 | return; | 351 | kfree(info); |
408 | } | 352 | } |
409 | 353 | ||
410 | /** | 354 | void pciehp_queue_pushbutton_work(struct work_struct *work) |
411 | * pciehp_surprise_rm_thread | ||
412 | * | ||
413 | * Scheduled procedure to handle blocking stuff for the surprise removal | ||
414 | * Handles all pending events and exits. | ||
415 | * | ||
416 | */ | ||
417 | static void pciehp_surprise_rm_thread(unsigned long slot) | ||
418 | { | 355 | { |
419 | struct slot *p_slot = (struct slot *) slot; | 356 | struct slot *p_slot = container_of(work, struct slot, work.work); |
420 | u8 getstatus; | 357 | struct power_work_info *info; |
421 | |||
422 | surprise_rm_pending = 0; | ||
423 | 358 | ||
424 | if (!p_slot) { | 359 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
425 | dbg("%s: Error! slot NULL\n", __FUNCTION__); | 360 | if (!info) { |
361 | err("%s: Cannot allocate memory\n", __FUNCTION__); | ||
426 | return; | 362 | return; |
427 | } | 363 | } |
364 | info->p_slot = p_slot; | ||
365 | INIT_WORK(&info->work, pciehp_power_thread); | ||
428 | 366 | ||
429 | p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); | 367 | mutex_lock(&p_slot->lock); |
430 | if (!getstatus) { | 368 | switch (p_slot->state) { |
369 | case BLINKINGOFF_STATE: | ||
431 | p_slot->state = POWEROFF_STATE; | 370 | p_slot->state = POWEROFF_STATE; |
432 | dbg("%s: removing bus:device(%x:%x)\n", | 371 | break; |
433 | __FUNCTION__, p_slot->bus, p_slot->device); | 372 | case BLINKINGON_STATE: |
434 | |||
435 | pciehp_disable_slot(p_slot); | ||
436 | p_slot->state = STATIC_STATE; | ||
437 | } else { | ||
438 | p_slot->state = POWERON_STATE; | 373 | p_slot->state = POWERON_STATE; |
439 | dbg("%s: adding bus:device(%x:%x)\n", | 374 | break; |
440 | __FUNCTION__, p_slot->bus, p_slot->device); | 375 | default: |
441 | 376 | goto out; | |
442 | if (pciehp_enable_slot(p_slot) && | ||
443 | PWR_LED(p_slot->ctrl->ctrlcap)) | ||
444 | p_slot->hpc_ops->green_led_off(p_slot); | ||
445 | |||
446 | p_slot->state = STATIC_STATE; | ||
447 | } | 377 | } |
448 | 378 | queue_work(pciehp_wq, &info->work); | |
449 | return; | 379 | out: |
380 | mutex_unlock(&p_slot->lock); | ||
450 | } | 381 | } |
451 | 382 | ||
452 | |||
453 | |||
454 | /* this is the main worker thread */ | ||
455 | static int event_thread(void* data) | ||
456 | { | ||
457 | struct controller *ctrl; | ||
458 | lock_kernel(); | ||
459 | daemonize("pciehpd_event"); | ||
460 | |||
461 | unlock_kernel(); | ||
462 | |||
463 | while (1) { | ||
464 | dbg("!!!!event_thread sleeping\n"); | ||
465 | down_interruptible (&event_semaphore); | ||
466 | dbg("event_thread woken finished = %d\n", event_finished); | ||
467 | if (event_finished || signal_pending(current)) | ||
468 | break; | ||
469 | /* Do stuff here */ | ||
470 | if (pushbutton_pending) | ||
471 | pciehp_pushbutton_thread(pushbutton_pending); | ||
472 | else if (surprise_rm_pending) | ||
473 | pciehp_surprise_rm_thread(surprise_rm_pending); | ||
474 | else | ||
475 | for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next) | ||
476 | interrupt_event_handler(ctrl); | ||
477 | } | ||
478 | dbg("event_thread signals exit\n"); | ||
479 | up(&event_exit); | ||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | int pciehp_event_start_thread(void) | ||
484 | { | ||
485 | int pid; | ||
486 | |||
487 | /* initialize our semaphores */ | ||
488 | init_MUTEX_LOCKED(&event_exit); | ||
489 | event_finished=0; | ||
490 | |||
491 | init_MUTEX_LOCKED(&event_semaphore); | ||
492 | pid = kernel_thread(event_thread, NULL, 0); | ||
493 | |||
494 | if (pid < 0) { | ||
495 | err ("Can't start up our event thread\n"); | ||
496 | return -1; | ||
497 | } | ||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | |||
502 | void pciehp_event_stop_thread(void) | ||
503 | { | ||
504 | event_finished = 1; | ||
505 | up(&event_semaphore); | ||
506 | down(&event_exit); | ||
507 | } | ||
508 | |||
509 | |||
510 | static int update_slot_info(struct slot *slot) | 383 | static int update_slot_info(struct slot *slot) |
511 | { | 384 | { |
512 | struct hotplug_slot_info *info; | 385 | struct hotplug_slot_info *info; |
513 | /* char buffer[SLOT_NAME_SIZE]; */ | ||
514 | int result; | 386 | int result; |
515 | 387 | ||
516 | info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); | 388 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
517 | if (!info) | 389 | if (!info) |
518 | return -ENOMEM; | 390 | return -ENOMEM; |
519 | 391 | ||
520 | /* make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot); */ | ||
521 | |||
522 | slot->hpc_ops->get_power_status(slot, &(info->power_status)); | 392 | slot->hpc_ops->get_power_status(slot, &(info->power_status)); |
523 | slot->hpc_ops->get_attention_status(slot, &(info->attention_status)); | 393 | slot->hpc_ops->get_attention_status(slot, &(info->attention_status)); |
524 | slot->hpc_ops->get_latch_status(slot, &(info->latch_status)); | 394 | slot->hpc_ops->get_latch_status(slot, &(info->latch_status)); |
525 | slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status)); | 395 | slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status)); |
526 | 396 | ||
527 | /* result = pci_hp_change_slot_info(buffer, info); */ | ||
528 | result = pci_hp_change_slot_info(slot->hotplug_slot, info); | 397 | result = pci_hp_change_slot_info(slot->hotplug_slot, info); |
529 | kfree (info); | 398 | kfree (info); |
530 | return result; | 399 | return result; |
531 | } | 400 | } |
532 | 401 | ||
533 | static void interrupt_event_handler(struct controller *ctrl) | 402 | /* |
403 | * Note: This function must be called with slot->lock held | ||
404 | */ | ||
405 | static void handle_button_press_event(struct slot *p_slot) | ||
534 | { | 406 | { |
535 | int loop = 0; | 407 | struct controller *ctrl = p_slot->ctrl; |
536 | int change = 1; | ||
537 | u8 hp_slot; | ||
538 | u8 getstatus; | 408 | u8 getstatus; |
539 | struct slot *p_slot; | ||
540 | 409 | ||
541 | while (change) { | 410 | switch (p_slot->state) { |
542 | change = 0; | 411 | case STATIC_STATE: |
543 | 412 | p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | |
544 | for (loop = 0; loop < MAX_EVENTS; loop++) { | 413 | if (getstatus) { |
545 | if (ctrl->event_queue[loop].event_type != 0) { | 414 | p_slot->state = BLINKINGOFF_STATE; |
546 | hp_slot = ctrl->event_queue[loop].hp_slot; | 415 | info("PCI slot #%s - powering off due to button " |
547 | 416 | "press.\n", p_slot->name); | |
548 | p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); | 417 | } else { |
549 | 418 | p_slot->state = BLINKINGON_STATE; | |
550 | if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { | 419 | info("PCI slot #%s - powering on due to button " |
551 | dbg("button cancel\n"); | 420 | "press.\n", p_slot->name); |
552 | del_timer(&p_slot->task_event); | 421 | } |
553 | 422 | /* blink green LED and turn off amber */ | |
554 | switch (p_slot->state) { | 423 | if (PWR_LED(ctrl->ctrlcap)) |
555 | case BLINKINGOFF_STATE: | 424 | p_slot->hpc_ops->green_led_blink(p_slot); |
556 | if (PWR_LED(ctrl->ctrlcap)) | 425 | if (ATTN_LED(ctrl->ctrlcap)) |
557 | p_slot->hpc_ops->green_led_on(p_slot); | 426 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
558 | 427 | ||
559 | if (ATTN_LED(ctrl->ctrlcap)) | 428 | schedule_delayed_work(&p_slot->work, 5*HZ); |
560 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 429 | break; |
561 | break; | 430 | case BLINKINGOFF_STATE: |
562 | case BLINKINGON_STATE: | 431 | case BLINKINGON_STATE: |
563 | if (PWR_LED(ctrl->ctrlcap)) | 432 | /* |
564 | p_slot->hpc_ops->green_led_off(p_slot); | 433 | * Cancel if we are still blinking; this means that we |
565 | 434 | * press the attention again before the 5 sec. limit | |
566 | if (ATTN_LED(ctrl->ctrlcap)) | 435 | * expires to cancel hot-add or hot-remove |
567 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 436 | */ |
568 | break; | 437 | info("Button cancel on Slot(%s)\n", p_slot->name); |
569 | default: | 438 | dbg("%s: button cancel\n", __FUNCTION__); |
570 | warn("Not a valid state\n"); | 439 | cancel_delayed_work(&p_slot->work); |
571 | return; | 440 | if (p_slot->state == BLINKINGOFF_STATE) { |
572 | } | 441 | if (PWR_LED(ctrl->ctrlcap)) |
573 | info("PCI slot #%s - action canceled due to button press.\n", slot_name(p_slot)); | 442 | p_slot->hpc_ops->green_led_on(p_slot); |
574 | p_slot->state = STATIC_STATE; | 443 | } else { |
575 | } | 444 | if (PWR_LED(ctrl->ctrlcap)) |
576 | /* ***********Button Pressed (No action on 1st press...) */ | 445 | p_slot->hpc_ops->green_led_off(p_slot); |
577 | else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { | 446 | } |
578 | 447 | if (ATTN_LED(ctrl->ctrlcap)) | |
579 | if (ATTN_BUTTN(ctrl->ctrlcap)) { | 448 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
580 | dbg("Button pressed\n"); | 449 | info("PCI slot #%s - action canceled due to button press\n", |
581 | p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 450 | p_slot->name); |
582 | if (getstatus) { | 451 | p_slot->state = STATIC_STATE; |
583 | /* slot is on */ | 452 | break; |
584 | dbg("slot is on\n"); | 453 | case POWEROFF_STATE: |
585 | p_slot->state = BLINKINGOFF_STATE; | 454 | case POWERON_STATE: |
586 | info("PCI slot #%s - powering off due to button press.\n", slot_name(p_slot)); | 455 | /* |
587 | } else { | 456 | * Ignore if the slot is on power-on or power-off state; |
588 | /* slot is off */ | 457 | * this means that the previous attention button action |
589 | dbg("slot is off\n"); | 458 | * to hot-add or hot-remove is undergoing |
590 | p_slot->state = BLINKINGON_STATE; | 459 | */ |
591 | info("PCI slot #%s - powering on due to button press.\n", slot_name(p_slot)); | 460 | info("Button ignore on Slot(%s)\n", p_slot->name); |
592 | } | 461 | update_slot_info(p_slot); |
593 | 462 | break; | |
594 | /* blink green LED and turn off amber */ | 463 | default: |
595 | if (PWR_LED(ctrl->ctrlcap)) | 464 | warn("Not a valid state\n"); |
596 | p_slot->hpc_ops->green_led_blink(p_slot); | 465 | break; |
597 | |||
598 | if (ATTN_LED(ctrl->ctrlcap)) | ||
599 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | ||
600 | |||
601 | init_timer(&p_slot->task_event); | ||
602 | p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ | ||
603 | p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; | ||
604 | p_slot->task_event.data = (unsigned long) p_slot; | ||
605 | |||
606 | add_timer(&p_slot->task_event); | ||
607 | } | ||
608 | } | ||
609 | /***********POWER FAULT********************/ | ||
610 | else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { | ||
611 | if (POWER_CTRL(ctrl->ctrlcap)) { | ||
612 | dbg("power fault\n"); | ||
613 | if (ATTN_LED(ctrl->ctrlcap)) | ||
614 | p_slot->hpc_ops->set_attention_status(p_slot, 1); | ||
615 | |||
616 | if (PWR_LED(ctrl->ctrlcap)) | ||
617 | p_slot->hpc_ops->green_led_off(p_slot); | ||
618 | } | ||
619 | } | ||
620 | /***********SURPRISE REMOVAL********************/ | ||
621 | else if ((ctrl->event_queue[loop].event_type == INT_PRESENCE_ON) || | ||
622 | (ctrl->event_queue[loop].event_type == INT_PRESENCE_OFF)) { | ||
623 | if (HP_SUPR_RM(ctrl->ctrlcap)) { | ||
624 | dbg("Surprise Removal\n"); | ||
625 | if (p_slot) { | ||
626 | surprise_rm_pending = (unsigned long) p_slot; | ||
627 | up(&event_semaphore); | ||
628 | update_slot_info(p_slot); | ||
629 | } | ||
630 | } | ||
631 | } else { | ||
632 | /* refresh notification */ | ||
633 | if (p_slot) | ||
634 | update_slot_info(p_slot); | ||
635 | } | ||
636 | |||
637 | ctrl->event_queue[loop].event_type = 0; | ||
638 | |||
639 | change = 1; | ||
640 | } | ||
641 | } /* End of FOR loop */ | ||
642 | } | 466 | } |
643 | } | 467 | } |
644 | 468 | ||
469 | /* | ||
470 | * Note: This function must be called with slot->lock held | ||
471 | */ | ||
472 | static void handle_surprise_event(struct slot *p_slot) | ||
473 | { | ||
474 | u8 getstatus; | ||
475 | struct power_work_info *info; | ||
476 | |||
477 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
478 | if (!info) { | ||
479 | err("%s: Cannot allocate memory\n", __FUNCTION__); | ||
480 | return; | ||
481 | } | ||
482 | info->p_slot = p_slot; | ||
483 | INIT_WORK(&info->work, pciehp_power_thread); | ||
484 | |||
485 | p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); | ||
486 | if (!getstatus) | ||
487 | p_slot->state = POWEROFF_STATE; | ||
488 | else | ||
489 | p_slot->state = POWERON_STATE; | ||
490 | |||
491 | queue_work(pciehp_wq, &info->work); | ||
492 | } | ||
493 | |||
494 | static void interrupt_event_handler(struct work_struct *work) | ||
495 | { | ||
496 | struct event_info *info = container_of(work, struct event_info, work); | ||
497 | struct slot *p_slot = info->p_slot; | ||
498 | struct controller *ctrl = p_slot->ctrl; | ||
499 | |||
500 | mutex_lock(&p_slot->lock); | ||
501 | switch (info->event_type) { | ||
502 | case INT_BUTTON_PRESS: | ||
503 | handle_button_press_event(p_slot); | ||
504 | break; | ||
505 | case INT_POWER_FAULT: | ||
506 | if (!POWER_CTRL(ctrl->ctrlcap)) | ||
507 | break; | ||
508 | if (ATTN_LED(ctrl->ctrlcap)) | ||
509 | p_slot->hpc_ops->set_attention_status(p_slot, 1); | ||
510 | if (PWR_LED(ctrl->ctrlcap)) | ||
511 | p_slot->hpc_ops->green_led_off(p_slot); | ||
512 | break; | ||
513 | case INT_PRESENCE_ON: | ||
514 | case INT_PRESENCE_OFF: | ||
515 | if (!HP_SUPR_RM(ctrl->ctrlcap)) | ||
516 | break; | ||
517 | dbg("Surprise Removal\n"); | ||
518 | update_slot_info(p_slot); | ||
519 | handle_surprise_event(p_slot); | ||
520 | break; | ||
521 | default: | ||
522 | update_slot_info(p_slot); | ||
523 | break; | ||
524 | } | ||
525 | mutex_unlock(&p_slot->lock); | ||
526 | |||
527 | kfree(info); | ||
528 | } | ||
529 | |||
645 | int pciehp_enable_slot(struct slot *p_slot) | 530 | int pciehp_enable_slot(struct slot *p_slot) |
646 | { | 531 | { |
647 | u8 getstatus = 0; | 532 | u8 getstatus = 0; |
@@ -653,7 +538,7 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
653 | rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); | 538 | rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); |
654 | if (rc || !getstatus) { | 539 | if (rc || !getstatus) { |
655 | info("%s: no adapter on slot(%s)\n", __FUNCTION__, | 540 | info("%s: no adapter on slot(%s)\n", __FUNCTION__, |
656 | slot_name(p_slot)); | 541 | p_slot->name); |
657 | mutex_unlock(&p_slot->ctrl->crit_sect); | 542 | mutex_unlock(&p_slot->ctrl->crit_sect); |
658 | return -ENODEV; | 543 | return -ENODEV; |
659 | } | 544 | } |
@@ -661,7 +546,7 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
661 | rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 546 | rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
662 | if (rc || getstatus) { | 547 | if (rc || getstatus) { |
663 | info("%s: latch open on slot(%s)\n", __FUNCTION__, | 548 | info("%s: latch open on slot(%s)\n", __FUNCTION__, |
664 | slot_name(p_slot)); | 549 | p_slot->name); |
665 | mutex_unlock(&p_slot->ctrl->crit_sect); | 550 | mutex_unlock(&p_slot->ctrl->crit_sect); |
666 | return -ENODEV; | 551 | return -ENODEV; |
667 | } | 552 | } |
@@ -671,7 +556,7 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
671 | rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 556 | rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
672 | if (rc || getstatus) { | 557 | if (rc || getstatus) { |
673 | info("%s: already enabled on slot(%s)\n", __FUNCTION__, | 558 | info("%s: already enabled on slot(%s)\n", __FUNCTION__, |
674 | slot_name(p_slot)); | 559 | p_slot->name); |
675 | mutex_unlock(&p_slot->ctrl->crit_sect); | 560 | mutex_unlock(&p_slot->ctrl->crit_sect); |
676 | return -EINVAL; | 561 | return -EINVAL; |
677 | } | 562 | } |
@@ -706,7 +591,7 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
706 | ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); | 591 | ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); |
707 | if (ret || !getstatus) { | 592 | if (ret || !getstatus) { |
708 | info("%s: no adapter on slot(%s)\n", __FUNCTION__, | 593 | info("%s: no adapter on slot(%s)\n", __FUNCTION__, |
709 | slot_name(p_slot)); | 594 | p_slot->name); |
710 | mutex_unlock(&p_slot->ctrl->crit_sect); | 595 | mutex_unlock(&p_slot->ctrl->crit_sect); |
711 | return -ENODEV; | 596 | return -ENODEV; |
712 | } | 597 | } |
@@ -716,7 +601,7 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
716 | ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); | 601 | ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); |
717 | if (ret || getstatus) { | 602 | if (ret || getstatus) { |
718 | info("%s: latch open on slot(%s)\n", __FUNCTION__, | 603 | info("%s: latch open on slot(%s)\n", __FUNCTION__, |
719 | slot_name(p_slot)); | 604 | p_slot->name); |
720 | mutex_unlock(&p_slot->ctrl->crit_sect); | 605 | mutex_unlock(&p_slot->ctrl->crit_sect); |
721 | return -ENODEV; | 606 | return -ENODEV; |
722 | } | 607 | } |
@@ -726,7 +611,7 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
726 | ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); | 611 | ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); |
727 | if (ret || !getstatus) { | 612 | if (ret || !getstatus) { |
728 | info("%s: already disabled slot(%s)\n", __FUNCTION__, | 613 | info("%s: already disabled slot(%s)\n", __FUNCTION__, |
729 | slot_name(p_slot)); | 614 | p_slot->name); |
730 | mutex_unlock(&p_slot->ctrl->crit_sect); | 615 | mutex_unlock(&p_slot->ctrl->crit_sect); |
731 | return -EINVAL; | 616 | return -EINVAL; |
732 | } | 617 | } |
@@ -739,3 +624,66 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
739 | return ret; | 624 | return ret; |
740 | } | 625 | } |
741 | 626 | ||
627 | int pciehp_sysfs_enable_slot(struct slot *p_slot) | ||
628 | { | ||
629 | int retval = -ENODEV; | ||
630 | |||
631 | mutex_lock(&p_slot->lock); | ||
632 | switch (p_slot->state) { | ||
633 | case BLINKINGON_STATE: | ||
634 | cancel_delayed_work(&p_slot->work); | ||
635 | case STATIC_STATE: | ||
636 | p_slot->state = POWERON_STATE; | ||
637 | mutex_unlock(&p_slot->lock); | ||
638 | retval = pciehp_enable_slot(p_slot); | ||
639 | mutex_lock(&p_slot->lock); | ||
640 | p_slot->state = STATIC_STATE; | ||
641 | break; | ||
642 | case POWERON_STATE: | ||
643 | info("Slot %s is already in powering on state\n", | ||
644 | p_slot->name); | ||
645 | break; | ||
646 | case BLINKINGOFF_STATE: | ||
647 | case POWEROFF_STATE: | ||
648 | info("Already enabled on slot %s\n", p_slot->name); | ||
649 | break; | ||
650 | default: | ||
651 | err("Not a valid state on slot %s\n", p_slot->name); | ||
652 | break; | ||
653 | } | ||
654 | mutex_unlock(&p_slot->lock); | ||
655 | |||
656 | return retval; | ||
657 | } | ||
658 | |||
659 | int pciehp_sysfs_disable_slot(struct slot *p_slot) | ||
660 | { | ||
661 | int retval = -ENODEV; | ||
662 | |||
663 | mutex_lock(&p_slot->lock); | ||
664 | switch (p_slot->state) { | ||
665 | case BLINKINGOFF_STATE: | ||
666 | cancel_delayed_work(&p_slot->work); | ||
667 | case STATIC_STATE: | ||
668 | p_slot->state = POWEROFF_STATE; | ||
669 | mutex_unlock(&p_slot->lock); | ||
670 | retval = pciehp_disable_slot(p_slot); | ||
671 | mutex_lock(&p_slot->lock); | ||
672 | p_slot->state = STATIC_STATE; | ||
673 | break; | ||
674 | case POWEROFF_STATE: | ||
675 | info("Slot %s is already in powering off state\n", | ||
676 | p_slot->name); | ||
677 | break; | ||
678 | case BLINKINGON_STATE: | ||
679 | case POWERON_STATE: | ||
680 | info("Already disabled on slot %s\n", p_slot->name); | ||
681 | break; | ||
682 | default: | ||
683 | err("Not a valid state on slot %s\n", p_slot->name); | ||
684 | break; | ||
685 | } | ||
686 | mutex_unlock(&p_slot->lock); | ||
687 | |||
688 | return retval; | ||
689 | } | ||
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index fbc64aa2dd68..9aac6a87eb53 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -71,6 +71,8 @@ | |||
71 | #define DBG_LEAVE_ROUTINE | 71 | #define DBG_LEAVE_ROUTINE |
72 | #endif /* DEBUG */ | 72 | #endif /* DEBUG */ |
73 | 73 | ||
74 | static atomic_t pciehp_num_controllers = ATOMIC_INIT(0); | ||
75 | |||
74 | struct ctrl_reg { | 76 | struct ctrl_reg { |
75 | u8 cap_id; | 77 | u8 cap_id; |
76 | u8 nxt_ptr; | 78 | u8 nxt_ptr; |
@@ -219,10 +221,7 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) | |||
219 | #define EMI_STATE 0x0080 | 221 | #define EMI_STATE 0x0080 |
220 | #define EMI_STATUS_BIT 7 | 222 | #define EMI_STATUS_BIT 7 |
221 | 223 | ||
222 | static spinlock_t hpc_event_lock; | ||
223 | |||
224 | DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ | 224 | DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ |
225 | static int ctlr_seq_num = 0; /* Controller sequence # */ | ||
226 | 225 | ||
227 | static irqreturn_t pcie_isr(int irq, void *dev_id); | 226 | static irqreturn_t pcie_isr(int irq, void *dev_id); |
228 | static void start_int_poll_timer(struct controller *ctrl, int sec); | 227 | static void start_int_poll_timer(struct controller *ctrl, int sec); |
@@ -656,6 +655,13 @@ static void hpc_release_ctlr(struct controller *ctrl) | |||
656 | else | 655 | else |
657 | free_irq(ctrl->pci_dev->irq, ctrl); | 656 | free_irq(ctrl->pci_dev->irq, ctrl); |
658 | 657 | ||
658 | /* | ||
659 | * If this is the last controller to be released, destroy the | ||
660 | * pciehp work queue | ||
661 | */ | ||
662 | if (atomic_dec_and_test(&pciehp_num_controllers)) | ||
663 | destroy_workqueue(pciehp_wq); | ||
664 | |||
659 | DBG_LEAVE_ROUTINE | 665 | DBG_LEAVE_ROUTINE |
660 | } | 666 | } |
661 | 667 | ||
@@ -1152,7 +1158,6 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev) | |||
1152 | int pcie_init(struct controller * ctrl, struct pcie_device *dev) | 1158 | int pcie_init(struct controller * ctrl, struct pcie_device *dev) |
1153 | { | 1159 | { |
1154 | int rc; | 1160 | int rc; |
1155 | static int first = 1; | ||
1156 | u16 temp_word; | 1161 | u16 temp_word; |
1157 | u16 cap_reg; | 1162 | u16 cap_reg; |
1158 | u16 intr_enable = 0; | 1163 | u16 intr_enable = 0; |
@@ -1221,11 +1226,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
1221 | dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n", | 1226 | dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n", |
1222 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl); | 1227 | __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl); |
1223 | 1228 | ||
1224 | if (first) { | ||
1225 | spin_lock_init(&hpc_event_lock); | ||
1226 | first = 0; | ||
1227 | } | ||
1228 | |||
1229 | for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++) | 1229 | for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++) |
1230 | if (pci_resource_len(pdev, rc) > 0) | 1230 | if (pci_resource_len(pdev, rc) > 0) |
1231 | dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc, | 1231 | dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc, |
@@ -1286,7 +1286,8 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
1286 | rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED, | 1286 | rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED, |
1287 | MY_NAME, (void *)ctrl); | 1287 | MY_NAME, (void *)ctrl); |
1288 | dbg("%s: request_irq %d for hpc%d (returns %d)\n", | 1288 | dbg("%s: request_irq %d for hpc%d (returns %d)\n", |
1289 | __FUNCTION__, ctrl->pci_dev->irq, ctlr_seq_num, rc); | 1289 | __FUNCTION__, ctrl->pci_dev->irq, |
1290 | atomic_read(&pciehp_num_controllers), rc); | ||
1290 | if (rc) { | 1291 | if (rc) { |
1291 | err("Can't get irq %d for the hotplug controller\n", | 1292 | err("Can't get irq %d for the hotplug controller\n", |
1292 | ctrl->pci_dev->irq); | 1293 | ctrl->pci_dev->irq); |
@@ -1296,6 +1297,18 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
1296 | dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number, | 1297 | dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number, |
1297 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq); | 1298 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq); |
1298 | 1299 | ||
1300 | /* | ||
1301 | * If this is the first controller to be initialized, | ||
1302 | * initialize the pciehp work queue | ||
1303 | */ | ||
1304 | if (atomic_add_return(1, &pciehp_num_controllers) == 1) { | ||
1305 | pciehp_wq = create_singlethread_workqueue("pciehpd"); | ||
1306 | if (!pciehp_wq) { | ||
1307 | rc = -ENOMEM; | ||
1308 | goto abort_free_irq; | ||
1309 | } | ||
1310 | } | ||
1311 | |||
1299 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); | 1312 | rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); |
1300 | if (rc) { | 1313 | if (rc) { |
1301 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); | 1314 | err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); |
@@ -1349,7 +1362,6 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) | |||
1349 | goto abort_disable_intr; | 1362 | goto abort_disable_intr; |
1350 | } | 1363 | } |
1351 | 1364 | ||
1352 | ctlr_seq_num++; | ||
1353 | ctrl->hpc_ops = &pciehp_hpc_ops; | 1365 | ctrl->hpc_ops = &pciehp_hpc_ops; |
1354 | 1366 | ||
1355 | DBG_LEAVE_ROUTINE | 1367 | DBG_LEAVE_ROUTINE |
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 72383467a0d5..bb3c101c2c5a 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c | |||
@@ -98,7 +98,15 @@ static struct device_node *find_dlpar_node(char *drc_name, int *node_type) | |||
98 | return NULL; | 98 | return NULL; |
99 | } | 99 | } |
100 | 100 | ||
101 | static struct slot *find_slot(struct device_node *dn) | 101 | /** |
102 | * find_php_slot - return hotplug slot structure for device node | ||
103 | * | ||
104 | * This routine will return the hotplug slot structure | ||
105 | * for a given device node. Note that built-in PCI slots | ||
106 | * may be dlpar-able, but not hot-pluggable, so this routine | ||
107 | * will return NULL for built-in PCI slots. | ||
108 | */ | ||
109 | static struct slot *find_php_slot(struct device_node *dn) | ||
102 | { | 110 | { |
103 | struct list_head *tmp, *n; | 111 | struct list_head *tmp, *n; |
104 | struct slot *slot; | 112 | struct slot *slot; |
@@ -224,9 +232,9 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn) | |||
224 | if (!pcibios_find_pci_bus(dn)) | 232 | if (!pcibios_find_pci_bus(dn)) |
225 | return -EINVAL; | 233 | return -EINVAL; |
226 | 234 | ||
227 | slot = find_slot(dn); | 235 | /* If pci slot is hotplugable, use hotplug to remove it */ |
236 | slot = find_php_slot(dn); | ||
228 | if (slot) { | 237 | if (slot) { |
229 | /* Remove hotplug slot */ | ||
230 | if (rpaphp_deregister_slot(slot)) { | 238 | if (rpaphp_deregister_slot(slot)) { |
231 | printk(KERN_ERR | 239 | printk(KERN_ERR |
232 | "%s: unable to remove hotplug slot %s\n", | 240 | "%s: unable to remove hotplug slot %s\n", |
@@ -370,22 +378,17 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) | |||
370 | if (!bus) | 378 | if (!bus) |
371 | return -EINVAL; | 379 | return -EINVAL; |
372 | 380 | ||
373 | slot = find_slot(dn); | 381 | /* If pci slot is hotplugable, use hotplug to remove it */ |
382 | slot = find_php_slot(dn); | ||
374 | if (slot) { | 383 | if (slot) { |
375 | /* Remove hotplug slot */ | ||
376 | if (rpaphp_deregister_slot(slot)) { | 384 | if (rpaphp_deregister_slot(slot)) { |
377 | printk(KERN_ERR | 385 | printk(KERN_ERR |
378 | "%s: unable to remove hotplug slot %s\n", | 386 | "%s: unable to remove hotplug slot %s\n", |
379 | __FUNCTION__, drc_name); | 387 | __FUNCTION__, drc_name); |
380 | return -EIO; | 388 | return -EIO; |
381 | } | 389 | } |
382 | } else { | 390 | } else |
383 | struct pci_dev *dev, *tmp; | 391 | pcibios_remove_pci_devices(bus); |
384 | list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { | ||
385 | eeh_remove_bus_device(dev); | ||
386 | pci_remove_bus_device(dev); | ||
387 | } | ||
388 | } | ||
389 | 392 | ||
390 | if (unmap_bus_range(bus)) { | 393 | if (unmap_bus_range(bus)) { |
391 | printk(KERN_ERR "%s: failed to unmap bus range\n", | 394 | printk(KERN_ERR "%s: failed to unmap bus range\n", |
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 2e7accf0f734..c822a779653f 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h | |||
@@ -83,19 +83,15 @@ struct slot { | |||
83 | 83 | ||
84 | extern struct hotplug_slot_ops rpaphp_hotplug_slot_ops; | 84 | extern struct hotplug_slot_ops rpaphp_hotplug_slot_ops; |
85 | extern struct list_head rpaphp_slot_head; | 85 | extern struct list_head rpaphp_slot_head; |
86 | extern int num_slots; | ||
87 | 86 | ||
88 | /* function prototypes */ | 87 | /* function prototypes */ |
89 | 88 | ||
90 | /* rpaphp_pci.c */ | 89 | /* rpaphp_pci.c */ |
91 | extern int rpaphp_enable_pci_slot(struct slot *slot); | 90 | extern int rpaphp_enable_slot(struct slot *slot); |
92 | extern int rpaphp_register_pci_slot(struct slot *slot); | ||
93 | extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value); | ||
94 | extern int rpaphp_get_sensor_state(struct slot *slot, int *state); | 91 | extern int rpaphp_get_sensor_state(struct slot *slot, int *state); |
95 | 92 | ||
96 | /* rpaphp_core.c */ | 93 | /* rpaphp_core.c */ |
97 | extern int rpaphp_add_slot(struct device_node *dn); | 94 | extern int rpaphp_add_slot(struct device_node *dn); |
98 | extern int rpaphp_remove_slot(struct slot *slot); | ||
99 | extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index, | 95 | extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index, |
100 | char **drc_name, char **drc_type, int *drc_power_domain); | 96 | char **drc_name, char **drc_type, int *drc_power_domain); |
101 | 97 | ||
@@ -104,7 +100,5 @@ extern void dealloc_slot_struct(struct slot *slot); | |||
104 | extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain); | 100 | extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain); |
105 | extern int rpaphp_register_slot(struct slot *slot); | 101 | extern int rpaphp_register_slot(struct slot *slot); |
106 | extern int rpaphp_deregister_slot(struct slot *slot); | 102 | extern int rpaphp_deregister_slot(struct slot *slot); |
107 | extern int rpaphp_get_power_status(struct slot *slot, u8 * value); | ||
108 | extern int rpaphp_set_attention_status(struct slot *slot, u8 status); | ||
109 | 103 | ||
110 | #endif /* _PPC64PHP_H */ | 104 | #endif /* _PPC64PHP_H */ |
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 71a2cb8baa4a..847936fe327e 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c | |||
@@ -39,9 +39,7 @@ | |||
39 | #include "rpaphp.h" | 39 | #include "rpaphp.h" |
40 | 40 | ||
41 | int debug; | 41 | int debug; |
42 | static struct semaphore rpaphp_sem; | ||
43 | LIST_HEAD(rpaphp_slot_head); | 42 | LIST_HEAD(rpaphp_slot_head); |
44 | int num_slots; | ||
45 | 43 | ||
46 | #define DRIVER_VERSION "0.1" | 44 | #define DRIVER_VERSION "0.1" |
47 | #define DRIVER_AUTHOR "Linda Xie <lxie@us.ibm.com>" | 45 | #define DRIVER_AUTHOR "Linda Xie <lxie@us.ibm.com>" |
@@ -55,11 +53,6 @@ MODULE_LICENSE("GPL"); | |||
55 | 53 | ||
56 | module_param(debug, bool, 0644); | 54 | module_param(debug, bool, 0644); |
57 | 55 | ||
58 | static int rpaphp_get_attention_status(struct slot *slot) | ||
59 | { | ||
60 | return slot->hotplug_slot->info->attention_status; | ||
61 | } | ||
62 | |||
63 | /** | 56 | /** |
64 | * set_attention_status - set attention LED | 57 | * set_attention_status - set attention LED |
65 | * echo 0 > attention -- set LED OFF | 58 | * echo 0 > attention -- set LED OFF |
@@ -69,79 +62,75 @@ static int rpaphp_get_attention_status(struct slot *slot) | |||
69 | */ | 62 | */ |
70 | static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) | 63 | static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value) |
71 | { | 64 | { |
72 | int retval = 0; | 65 | int rc; |
73 | struct slot *slot = (struct slot *)hotplug_slot->private; | 66 | struct slot *slot = (struct slot *)hotplug_slot->private; |
74 | 67 | ||
75 | down(&rpaphp_sem); | ||
76 | switch (value) { | 68 | switch (value) { |
77 | case 0: | 69 | case 0: |
78 | retval = rpaphp_set_attention_status(slot, LED_OFF); | ||
79 | hotplug_slot->info->attention_status = 0; | ||
80 | break; | ||
81 | case 1: | 70 | case 1: |
82 | default: | ||
83 | retval = rpaphp_set_attention_status(slot, LED_ON); | ||
84 | hotplug_slot->info->attention_status = 1; | ||
85 | break; | ||
86 | case 2: | 71 | case 2: |
87 | retval = rpaphp_set_attention_status(slot, LED_ID); | 72 | break; |
88 | hotplug_slot->info->attention_status = 2; | 73 | default: |
74 | value = 1; | ||
89 | break; | 75 | break; |
90 | } | 76 | } |
91 | up(&rpaphp_sem); | 77 | |
92 | return retval; | 78 | rc = rtas_set_indicator(DR_INDICATOR, slot->index, value); |
79 | if (!rc) | ||
80 | hotplug_slot->info->attention_status = value; | ||
81 | |||
82 | return rc; | ||
93 | } | 83 | } |
94 | 84 | ||
95 | /** | 85 | /** |
96 | * get_power_status - get power status of a slot | 86 | * get_power_status - get power status of a slot |
97 | * @hotplug_slot: slot to get status | 87 | * @hotplug_slot: slot to get status |
98 | * @value: pointer to store status | 88 | * @value: pointer to store status |
99 | * | ||
100 | * | ||
101 | */ | 89 | */ |
102 | static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) | 90 | static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) |
103 | { | 91 | { |
104 | int retval; | 92 | int retval, level; |
105 | struct slot *slot = (struct slot *)hotplug_slot->private; | 93 | struct slot *slot = (struct slot *)hotplug_slot->private; |
106 | 94 | ||
107 | down(&rpaphp_sem); | 95 | retval = rtas_get_power_level (slot->power_domain, &level); |
108 | retval = rpaphp_get_power_status(slot, value); | 96 | if (!retval) |
109 | up(&rpaphp_sem); | 97 | *value = level; |
110 | return retval; | 98 | return retval; |
111 | } | 99 | } |
112 | 100 | ||
113 | /** | 101 | /** |
114 | * get_attention_status - get attention LED status | 102 | * get_attention_status - get attention LED status |
115 | * | ||
116 | * | ||
117 | */ | 103 | */ |
118 | static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) | 104 | static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) |
119 | { | 105 | { |
120 | int retval = 0; | ||
121 | struct slot *slot = (struct slot *)hotplug_slot->private; | 106 | struct slot *slot = (struct slot *)hotplug_slot->private; |
122 | 107 | *value = slot->hotplug_slot->info->attention_status; | |
123 | down(&rpaphp_sem); | 108 | return 0; |
124 | *value = rpaphp_get_attention_status(slot); | ||
125 | up(&rpaphp_sem); | ||
126 | return retval; | ||
127 | } | 109 | } |
128 | 110 | ||
129 | static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value) | 111 | static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value) |
130 | { | 112 | { |
131 | struct slot *slot = (struct slot *)hotplug_slot->private; | 113 | struct slot *slot = (struct slot *)hotplug_slot->private; |
132 | int retval = 0; | 114 | int rc, state; |
133 | 115 | ||
134 | down(&rpaphp_sem); | 116 | rc = rpaphp_get_sensor_state(slot, &state); |
135 | retval = rpaphp_get_pci_adapter_status(slot, 0, value); | 117 | |
136 | up(&rpaphp_sem); | 118 | *value = NOT_VALID; |
137 | return retval; | 119 | if (rc) |
120 | return rc; | ||
121 | |||
122 | if (state == EMPTY) | ||
123 | *value = EMPTY; | ||
124 | else if (state == PRESENT) | ||
125 | *value = slot->state; | ||
126 | |||
127 | return 0; | ||
138 | } | 128 | } |
139 | 129 | ||
140 | static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) | 130 | static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) |
141 | { | 131 | { |
142 | struct slot *slot = (struct slot *)hotplug_slot->private; | 132 | struct slot *slot = (struct slot *)hotplug_slot->private; |
143 | 133 | ||
144 | down(&rpaphp_sem); | ||
145 | switch (slot->type) { | 134 | switch (slot->type) { |
146 | case 1: | 135 | case 1: |
147 | case 2: | 136 | case 2: |
@@ -172,7 +161,6 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe | |||
172 | break; | 161 | break; |
173 | 162 | ||
174 | } | 163 | } |
175 | up(&rpaphp_sem); | ||
176 | return 0; | 164 | return 0; |
177 | } | 165 | } |
178 | 166 | ||
@@ -265,6 +253,14 @@ static int is_php_type(char *drc_type) | |||
265 | return 1; | 253 | return 1; |
266 | } | 254 | } |
267 | 255 | ||
256 | /** | ||
257 | * is_php_dn() - return 1 if this is a hotpluggable pci slot, else 0 | ||
258 | * | ||
259 | * This routine will return true only if the device node is | ||
260 | * a hotpluggable slot. This routine will return false | ||
261 | * for built-in pci slots (even when the built-in slots are | ||
262 | * dlparable.) | ||
263 | */ | ||
268 | static int is_php_dn(struct device_node *dn, const int **indexes, | 264 | static int is_php_dn(struct device_node *dn, const int **indexes, |
269 | const int **names, const int **types, const int **power_domains) | 265 | const int **names, const int **types, const int **power_domains) |
270 | { | 266 | { |
@@ -272,24 +268,31 @@ static int is_php_dn(struct device_node *dn, const int **indexes, | |||
272 | int rc; | 268 | int rc; |
273 | 269 | ||
274 | rc = get_children_props(dn, indexes, names, &drc_types, power_domains); | 270 | rc = get_children_props(dn, indexes, names, &drc_types, power_domains); |
275 | if (rc >= 0) { | 271 | if (rc < 0) |
276 | if (is_php_type((char *) &drc_types[1])) { | 272 | return 0; |
277 | *types = drc_types; | ||
278 | return 1; | ||
279 | } | ||
280 | } | ||
281 | 273 | ||
282 | return 0; | 274 | if (!is_php_type((char *) &drc_types[1])) |
275 | return 0; | ||
276 | |||
277 | *types = drc_types; | ||
278 | return 1; | ||
283 | } | 279 | } |
284 | 280 | ||
285 | /** | 281 | /** |
286 | * rpaphp_add_slot -- add hotplug or dlpar slot | 282 | * rpaphp_add_slot -- declare a hotplug slot to the hotplug subsystem. |
283 | * @dn device node of slot | ||
284 | * | ||
285 | * This subroutine will register a hotplugable slot with the | ||
286 | * PCI hotplug infrastructure. This routine is typicaly called | ||
287 | * during boot time, if the hotplug slots are present at boot time, | ||
288 | * or is called later, by the dlpar add code, if the slot is | ||
289 | * being dynamically added during runtime. | ||
290 | * | ||
291 | * If the device node points at an embedded (built-in) slot, this | ||
292 | * routine will just return without doing anything, since embedded | ||
293 | * slots cannot be hotplugged. | ||
287 | * | 294 | * |
288 | * rpaphp not only registers PCI hotplug slots(HOTPLUG), | 295 | * To remove a slot, it suffices to call rpaphp_deregister_slot() |
289 | * but also logical DR slots(EMBEDDED). | ||
290 | * HOTPLUG slot: An adapter can be physically added/removed. | ||
291 | * EMBEDDED slot: An adapter can be logically removed/added | ||
292 | * from/to a partition with the slot. | ||
293 | */ | 296 | */ |
294 | int rpaphp_add_slot(struct device_node *dn) | 297 | int rpaphp_add_slot(struct device_node *dn) |
295 | { | 298 | { |
@@ -299,34 +302,42 @@ int rpaphp_add_slot(struct device_node *dn) | |||
299 | const int *indexes, *names, *types, *power_domains; | 302 | const int *indexes, *names, *types, *power_domains; |
300 | char *name, *type; | 303 | char *name, *type; |
301 | 304 | ||
305 | if (!dn->name || strcmp(dn->name, "pci")) | ||
306 | return 0; | ||
307 | |||
308 | /* If this is not a hotplug slot, return without doing anything. */ | ||
309 | if (!is_php_dn(dn, &indexes, &names, &types, &power_domains)) | ||
310 | return 0; | ||
311 | |||
302 | dbg("Entry %s: dn->full_name=%s\n", __FUNCTION__, dn->full_name); | 312 | dbg("Entry %s: dn->full_name=%s\n", __FUNCTION__, dn->full_name); |
303 | 313 | ||
304 | /* register PCI devices */ | 314 | /* register PCI devices */ |
305 | if (dn->name != 0 && strcmp(dn->name, "pci") == 0) { | 315 | name = (char *) &names[1]; |
306 | if (!is_php_dn(dn, &indexes, &names, &types, &power_domains)) | 316 | type = (char *) &types[1]; |
307 | goto exit; | 317 | for (i = 0; i < indexes[0]; i++) { |
308 | 318 | ||
309 | name = (char *) &names[1]; | 319 | slot = alloc_slot_struct(dn, indexes[i + 1], name, power_domains[i + 1]); |
310 | type = (char *) &types[1]; | 320 | if (!slot) |
311 | for (i = 0; i < indexes[0]; i++, | 321 | return -ENOMEM; |
312 | name += (strlen(name) + 1), type += (strlen(type) + 1)) { | 322 | |
313 | 323 | slot->type = simple_strtoul(type, NULL, 10); | |
314 | if (!(slot = alloc_slot_struct(dn, indexes[i + 1], name, | ||
315 | power_domains[i + 1]))) { | ||
316 | retval = -ENOMEM; | ||
317 | goto exit; | ||
318 | } | ||
319 | slot->type = simple_strtoul(type, NULL, 10); | ||
320 | 324 | ||
321 | dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n", | 325 | dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n", |
322 | indexes[i + 1], name, type); | 326 | indexes[i + 1], name, type); |
323 | 327 | ||
324 | retval = rpaphp_register_pci_slot(slot); | 328 | retval = rpaphp_enable_slot(slot); |
325 | } | 329 | if (!retval) |
330 | retval = rpaphp_register_slot(slot); | ||
331 | |||
332 | if (retval) | ||
333 | dealloc_slot_struct(slot); | ||
334 | |||
335 | name += strlen(name) + 1; | ||
336 | type += strlen(type) + 1; | ||
326 | } | 337 | } |
327 | exit: | 338 | dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); |
328 | dbg("%s - Exit: num_slots=%d rc[%d]\n", | 339 | |
329 | __FUNCTION__, num_slots, retval); | 340 | /* XXX FIXME: reports a failure only if last entry in loop failed */ |
330 | return retval; | 341 | return retval; |
331 | } | 342 | } |
332 | 343 | ||
@@ -354,7 +365,6 @@ static int __init rpaphp_init(void) | |||
354 | struct device_node *dn = NULL; | 365 | struct device_node *dn = NULL; |
355 | 366 | ||
356 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 367 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
357 | init_MUTEX(&rpaphp_sem); | ||
358 | 368 | ||
359 | while ((dn = of_find_node_by_name(dn, "pci"))) | 369 | while ((dn = of_find_node_by_name(dn, "pci"))) |
360 | rpaphp_add_slot(dn); | 370 | rpaphp_add_slot(dn); |
@@ -367,8 +377,9 @@ static void __exit rpaphp_exit(void) | |||
367 | cleanup_slots(); | 377 | cleanup_slots(); |
368 | } | 378 | } |
369 | 379 | ||
370 | static int __enable_slot(struct slot *slot) | 380 | static int enable_slot(struct hotplug_slot *hotplug_slot) |
371 | { | 381 | { |
382 | struct slot *slot = (struct slot *)hotplug_slot->private; | ||
372 | int state; | 383 | int state; |
373 | int retval; | 384 | int retval; |
374 | 385 | ||
@@ -392,46 +403,17 @@ static int __enable_slot(struct slot *slot) | |||
392 | return 0; | 403 | return 0; |
393 | } | 404 | } |
394 | 405 | ||
395 | static int enable_slot(struct hotplug_slot *hotplug_slot) | 406 | static int disable_slot(struct hotplug_slot *hotplug_slot) |
396 | { | 407 | { |
397 | int retval; | ||
398 | struct slot *slot = (struct slot *)hotplug_slot->private; | 408 | struct slot *slot = (struct slot *)hotplug_slot->private; |
399 | |||
400 | down(&rpaphp_sem); | ||
401 | retval = __enable_slot(slot); | ||
402 | up(&rpaphp_sem); | ||
403 | |||
404 | return retval; | ||
405 | } | ||
406 | |||
407 | static int __disable_slot(struct slot *slot) | ||
408 | { | ||
409 | struct pci_dev *dev, *tmp; | ||
410 | |||
411 | if (slot->state == NOT_CONFIGURED) | 409 | if (slot->state == NOT_CONFIGURED) |
412 | return -EINVAL; | 410 | return -EINVAL; |
413 | 411 | ||
414 | list_for_each_entry_safe(dev, tmp, &slot->bus->devices, bus_list) { | 412 | pcibios_remove_pci_devices(slot->bus); |
415 | eeh_remove_bus_device(dev); | ||
416 | pci_remove_bus_device(dev); | ||
417 | } | ||
418 | |||
419 | slot->state = NOT_CONFIGURED; | 413 | slot->state = NOT_CONFIGURED; |
420 | return 0; | 414 | return 0; |
421 | } | 415 | } |
422 | 416 | ||
423 | static int disable_slot(struct hotplug_slot *hotplug_slot) | ||
424 | { | ||
425 | struct slot *slot = (struct slot *)hotplug_slot->private; | ||
426 | int retval; | ||
427 | |||
428 | down(&rpaphp_sem); | ||
429 | retval = __disable_slot (slot); | ||
430 | up(&rpaphp_sem); | ||
431 | |||
432 | return retval; | ||
433 | } | ||
434 | |||
435 | struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { | 417 | struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { |
436 | .owner = THIS_MODULE, | 418 | .owner = THIS_MODULE, |
437 | .enable_slot = enable_slot, | 419 | .enable_slot = enable_slot, |
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 6f6cbede5135..54ca8650d511 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c | |||
@@ -64,75 +64,6 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state) | |||
64 | return rc; | 64 | return rc; |
65 | } | 65 | } |
66 | 66 | ||
67 | /** | ||
68 | * get_pci_adapter_status - get the status of a slot | ||
69 | * | ||
70 | * 0-- slot is empty | ||
71 | * 1-- adapter is configured | ||
72 | * 2-- adapter is not configured | ||
73 | * 3-- not valid | ||
74 | */ | ||
75 | int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value) | ||
76 | { | ||
77 | struct pci_bus *bus; | ||
78 | int state, rc; | ||
79 | |||
80 | *value = NOT_VALID; | ||
81 | rc = rpaphp_get_sensor_state(slot, &state); | ||
82 | if (rc) | ||
83 | goto exit; | ||
84 | |||
85 | if (state == EMPTY) | ||
86 | *value = EMPTY; | ||
87 | else if (state == PRESENT) { | ||
88 | if (!is_init) { | ||
89 | /* at run-time slot->state can be changed by */ | ||
90 | /* config/unconfig adapter */ | ||
91 | *value = slot->state; | ||
92 | } else { | ||
93 | bus = pcibios_find_pci_bus(slot->dn); | ||
94 | if (bus && !list_empty(&bus->devices)) | ||
95 | *value = CONFIGURED; | ||
96 | else | ||
97 | *value = NOT_CONFIGURED; | ||
98 | } | ||
99 | } | ||
100 | exit: | ||
101 | return rc; | ||
102 | } | ||
103 | |||
104 | static void print_slot_pci_funcs(struct pci_bus *bus) | ||
105 | { | ||
106 | struct device_node *dn; | ||
107 | struct pci_dev *dev; | ||
108 | |||
109 | dn = pci_bus_to_OF_node(bus); | ||
110 | if (!dn) | ||
111 | return; | ||
112 | |||
113 | dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, dn->full_name); | ||
114 | list_for_each_entry (dev, &bus->devices, bus_list) | ||
115 | dbg("\t%s\n", pci_name(dev)); | ||
116 | return; | ||
117 | } | ||
118 | |||
119 | static int setup_pci_hotplug_slot_info(struct slot *slot) | ||
120 | { | ||
121 | struct hotplug_slot_info *hotplug_slot_info = slot->hotplug_slot->info; | ||
122 | |||
123 | dbg("%s Initilize the PCI slot's hotplug->info structure ...\n", | ||
124 | __FUNCTION__); | ||
125 | rpaphp_get_power_status(slot, &hotplug_slot_info->power_status); | ||
126 | rpaphp_get_pci_adapter_status(slot, 1, | ||
127 | &hotplug_slot_info->adapter_status); | ||
128 | if (hotplug_slot_info->adapter_status == NOT_VALID) { | ||
129 | err("%s: NOT_VALID: skip dn->full_name=%s\n", | ||
130 | __FUNCTION__, slot->dn->full_name); | ||
131 | return -EINVAL; | ||
132 | } | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static void set_slot_name(struct slot *slot) | 67 | static void set_slot_name(struct slot *slot) |
137 | { | 68 | { |
138 | struct pci_bus *bus = slot->bus; | 69 | struct pci_bus *bus = slot->bus; |
@@ -146,69 +77,73 @@ static void set_slot_name(struct slot *slot) | |||
146 | bus->number); | 77 | bus->number); |
147 | } | 78 | } |
148 | 79 | ||
149 | static int setup_pci_slot(struct slot *slot) | 80 | /** |
81 | * rpaphp_enable_slot - record slot state, config pci device | ||
82 | * | ||
83 | * Initialize values in the slot, and the hotplug_slot info | ||
84 | * structures to indicate if there is a pci card plugged into | ||
85 | * the slot. If the slot is not empty, run the pcibios routine | ||
86 | * to get pcibios stuff correctly set up. | ||
87 | */ | ||
88 | int rpaphp_enable_slot(struct slot *slot) | ||
150 | { | 89 | { |
151 | struct device_node *dn = slot->dn; | 90 | int rc, level, state; |
152 | struct pci_bus *bus; | 91 | struct pci_bus *bus; |
92 | struct hotplug_slot_info *info = slot->hotplug_slot->info; | ||
93 | |||
94 | info->adapter_status = NOT_VALID; | ||
95 | slot->state = EMPTY; | ||
96 | |||
97 | /* Find out if the power is turned on for the slot */ | ||
98 | rc = rtas_get_power_level(slot->power_domain, &level); | ||
99 | if (rc) | ||
100 | return rc; | ||
101 | info->power_status = level; | ||
102 | |||
103 | /* Figure out if there is an adapter in the slot */ | ||
104 | rc = rpaphp_get_sensor_state(slot, &state); | ||
105 | if (rc) | ||
106 | return rc; | ||
153 | 107 | ||
154 | BUG_ON(!dn); | 108 | bus = pcibios_find_pci_bus(slot->dn); |
155 | bus = pcibios_find_pci_bus(dn); | ||
156 | if (!bus) { | 109 | if (!bus) { |
157 | err("%s: no pci_bus for dn %s\n", __FUNCTION__, dn->full_name); | 110 | err("%s: no pci_bus for dn %s\n", __FUNCTION__, slot->dn->full_name); |
158 | goto exit_rc; | 111 | return -EINVAL; |
159 | } | 112 | } |
160 | 113 | ||
114 | info->adapter_status = EMPTY; | ||
161 | slot->bus = bus; | 115 | slot->bus = bus; |
162 | slot->pci_devs = &bus->devices; | 116 | slot->pci_devs = &bus->devices; |
163 | set_slot_name(slot); | 117 | set_slot_name(slot); |
164 | 118 | ||
165 | /* find slot's pci_dev if it's not empty */ | 119 | /* if there's an adapter in the slot, go add the pci devices */ |
166 | if (slot->hotplug_slot->info->adapter_status == EMPTY) { | 120 | if (state == PRESENT) { |
167 | slot->state = EMPTY; /* slot is empty */ | 121 | info->adapter_status = NOT_CONFIGURED; |
168 | } else { | 122 | slot->state = NOT_CONFIGURED; |
169 | /* slot is occupied */ | 123 | |
170 | if (!dn->child) { | 124 | /* non-empty slot has to have child */ |
171 | /* non-empty slot has to have child */ | 125 | if (!slot->dn->child) { |
172 | err("%s: slot[%s]'s device_node doesn't have child for adapter\n", | 126 | err("%s: slot[%s]'s device_node doesn't have child for adapter\n", |
173 | __FUNCTION__, slot->name); | 127 | __FUNCTION__, slot->name); |
174 | goto exit_rc; | 128 | return -EINVAL; |
175 | } | 129 | } |
176 | 130 | ||
177 | if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) { | 131 | if (list_empty(&bus->devices)) |
178 | dbg("%s CONFIGURING pci adapter in slot[%s]\n", | 132 | pcibios_add_pci_devices(bus); |
179 | __FUNCTION__, slot->name); | ||
180 | pcibios_add_pci_devices(slot->bus); | ||
181 | 133 | ||
182 | } else if (slot->hotplug_slot->info->adapter_status != CONFIGURED) { | 134 | if (!list_empty(&bus->devices)) { |
183 | err("%s: slot[%s]'s adapter_status is NOT_VALID.\n", | 135 | info->adapter_status = CONFIGURED; |
184 | __FUNCTION__, slot->name); | ||
185 | goto exit_rc; | ||
186 | } | ||
187 | print_slot_pci_funcs(slot->bus); | ||
188 | if (!list_empty(slot->pci_devs)) { | ||
189 | slot->state = CONFIGURED; | 136 | slot->state = CONFIGURED; |
190 | } else { | 137 | } |
191 | /* DLPAR add as opposed to | 138 | |
192 | * boot time */ | 139 | if (debug) { |
193 | slot->state = NOT_CONFIGURED; | 140 | struct pci_dev *dev; |
141 | dbg("%s: pci_devs of slot[%s]\n", __FUNCTION__, slot->dn->full_name); | ||
142 | list_for_each_entry (dev, &bus->devices, bus_list) | ||
143 | dbg("\t%s\n", pci_name(dev)); | ||
194 | } | 144 | } |
195 | } | 145 | } |
196 | return 0; | ||
197 | exit_rc: | ||
198 | dealloc_slot_struct(slot); | ||
199 | return -EINVAL; | ||
200 | } | ||
201 | 146 | ||
202 | int rpaphp_register_pci_slot(struct slot *slot) | 147 | return 0; |
203 | { | ||
204 | int rc = -EINVAL; | ||
205 | |||
206 | if (setup_pci_hotplug_slot_info(slot)) | ||
207 | goto exit_rc; | ||
208 | if (setup_pci_slot(slot)) | ||
209 | goto exit_rc; | ||
210 | rc = rpaphp_register_slot(slot); | ||
211 | exit_rc: | ||
212 | return rc; | ||
213 | } | 148 | } |
214 | 149 | ||
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index 3009193f0058..d4ee8723fcb3 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c | |||
@@ -56,7 +56,6 @@ static struct hotplug_slot_attribute php_attr_location = { | |||
56 | static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot) | 56 | static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot) |
57 | { | 57 | { |
58 | struct slot *slot = (struct slot *) hotplug_slot->private; | 58 | struct slot *slot = (struct slot *) hotplug_slot->private; |
59 | |||
60 | dealloc_slot_struct(slot); | 59 | dealloc_slot_struct(slot); |
61 | } | 60 | } |
62 | 61 | ||
@@ -65,12 +64,12 @@ void dealloc_slot_struct(struct slot *slot) | |||
65 | kfree(slot->hotplug_slot->info); | 64 | kfree(slot->hotplug_slot->info); |
66 | kfree(slot->hotplug_slot->name); | 65 | kfree(slot->hotplug_slot->name); |
67 | kfree(slot->hotplug_slot); | 66 | kfree(slot->hotplug_slot); |
67 | kfree(slot->location); | ||
68 | kfree(slot); | 68 | kfree(slot); |
69 | return; | ||
70 | } | 69 | } |
71 | 70 | ||
72 | struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, | 71 | struct slot *alloc_slot_struct(struct device_node *dn, |
73 | int power_domain) | 72 | int drc_index, char *drc_name, int power_domain) |
74 | { | 73 | { |
75 | struct slot *slot; | 74 | struct slot *slot; |
76 | 75 | ||
@@ -115,7 +114,7 @@ error_nomem: | |||
115 | 114 | ||
116 | static int is_registered(struct slot *slot) | 115 | static int is_registered(struct slot *slot) |
117 | { | 116 | { |
118 | struct slot *tmp_slot; | 117 | struct slot *tmp_slot; |
119 | 118 | ||
120 | list_for_each_entry(tmp_slot, &rpaphp_slot_head, rpaphp_slot_list) { | 119 | list_for_each_entry(tmp_slot, &rpaphp_slot_head, rpaphp_slot_list) { |
121 | if (!strcmp(tmp_slot->name, slot->name)) | 120 | if (!strcmp(tmp_slot->name, slot->name)) |
@@ -140,8 +139,6 @@ int rpaphp_deregister_slot(struct slot *slot) | |||
140 | retval = pci_hp_deregister(php_slot); | 139 | retval = pci_hp_deregister(php_slot); |
141 | if (retval) | 140 | if (retval) |
142 | err("Problem unregistering a slot %s\n", slot->name); | 141 | err("Problem unregistering a slot %s\n", slot->name); |
143 | else | ||
144 | num_slots--; | ||
145 | 142 | ||
146 | dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); | 143 | dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval); |
147 | return retval; | 144 | return retval; |
@@ -160,14 +157,13 @@ int rpaphp_register_slot(struct slot *slot) | |||
160 | /* should not try to register the same slot twice */ | 157 | /* should not try to register the same slot twice */ |
161 | if (is_registered(slot)) { | 158 | if (is_registered(slot)) { |
162 | err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name); | 159 | err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name); |
163 | retval = -EAGAIN; | 160 | return -EAGAIN; |
164 | goto register_fail; | ||
165 | } | 161 | } |
166 | 162 | ||
167 | retval = pci_hp_register(php_slot); | 163 | retval = pci_hp_register(php_slot); |
168 | if (retval) { | 164 | if (retval) { |
169 | err("pci_hp_register failed with error %d\n", retval); | 165 | err("pci_hp_register failed with error %d\n", retval); |
170 | goto register_fail; | 166 | return retval; |
171 | } | 167 | } |
172 | 168 | ||
173 | /* create "phy_location" file */ | 169 | /* create "phy_location" file */ |
@@ -181,43 +177,10 @@ int rpaphp_register_slot(struct slot *slot) | |||
181 | list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head); | 177 | list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head); |
182 | info("Slot [%s](PCI location=%s) registered\n", slot->name, | 178 | info("Slot [%s](PCI location=%s) registered\n", slot->name, |
183 | slot->location); | 179 | slot->location); |
184 | num_slots++; | ||
185 | return 0; | 180 | return 0; |
186 | 181 | ||
187 | sysfs_fail: | 182 | sysfs_fail: |
188 | pci_hp_deregister(php_slot); | 183 | pci_hp_deregister(php_slot); |
189 | register_fail: | ||
190 | rpaphp_release_slot(php_slot); | ||
191 | return retval; | 184 | return retval; |
192 | } | 185 | } |
193 | 186 | ||
194 | int rpaphp_get_power_status(struct slot *slot, u8 * value) | ||
195 | { | ||
196 | int rc = 0, level; | ||
197 | |||
198 | rc = rtas_get_power_level(slot->power_domain, &level); | ||
199 | if (rc < 0) { | ||
200 | err("failed to get power-level for slot(%s), rc=0x%x\n", | ||
201 | slot->location, rc); | ||
202 | return rc; | ||
203 | } | ||
204 | |||
205 | dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n", | ||
206 | __FUNCTION__, slot->name, slot->power_domain, level); | ||
207 | *value = level; | ||
208 | |||
209 | return rc; | ||
210 | } | ||
211 | |||
212 | int rpaphp_set_attention_status(struct slot *slot, u8 status) | ||
213 | { | ||
214 | int rc; | ||
215 | |||
216 | /* status: LED_OFF or LED_ON */ | ||
217 | rc = rtas_set_indicator(DR_INDICATOR, slot->index, status); | ||
218 | if (rc < 0) | ||
219 | err("slot(name=%s location=%s index=0x%x) set attention-status(%d) failed! rc=0x%x\n", | ||
220 | slot->name, slot->location, slot->index, status, rc); | ||
221 | |||
222 | return rc; | ||
223 | } | ||
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 01d31a1f697c..37ed0884b972 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
@@ -166,7 +166,7 @@ extern u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl); | |||
166 | extern int shpchp_configure_device(struct slot *p_slot); | 166 | extern int shpchp_configure_device(struct slot *p_slot); |
167 | extern int shpchp_unconfigure_device(struct slot *p_slot); | 167 | extern int shpchp_unconfigure_device(struct slot *p_slot); |
168 | extern void cleanup_slots(struct controller *ctrl); | 168 | extern void cleanup_slots(struct controller *ctrl); |
169 | extern void queue_pushbutton_work(struct work_struct *work); | 169 | extern void shpchp_queue_pushbutton_work(struct work_struct *work); |
170 | extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev); | 170 | extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev); |
171 | 171 | ||
172 | #ifdef CONFIG_ACPI | 172 | #ifdef CONFIG_ACPI |
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 5f4bc08a633a..80dec9796b31 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c | |||
@@ -136,7 +136,7 @@ static int init_slots(struct controller *ctrl) | |||
136 | slot->hpc_ops = ctrl->hpc_ops; | 136 | slot->hpc_ops = ctrl->hpc_ops; |
137 | slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i); | 137 | slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i); |
138 | mutex_init(&slot->lock); | 138 | mutex_init(&slot->lock); |
139 | INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work); | 139 | INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work); |
140 | 140 | ||
141 | /* register this slot with the hotplug pci core */ | 141 | /* register this slot with the hotplug pci core */ |
142 | hotplug_slot->private = slot; | 142 | hotplug_slot->private = slot; |
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index b746bd265bc6..2c94d44279a3 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
@@ -433,7 +433,7 @@ static void shpchp_pushbutton_thread(struct work_struct *work) | |||
433 | kfree(info); | 433 | kfree(info); |
434 | } | 434 | } |
435 | 435 | ||
436 | void queue_pushbutton_work(struct work_struct *work) | 436 | void shpchp_queue_pushbutton_work(struct work_struct *work) |
437 | { | 437 | { |
438 | struct slot *p_slot = container_of(work, struct slot, work.work); | 438 | struct slot *p_slot = container_of(work, struct slot, work.work); |
439 | struct pushbutton_work_info *info; | 439 | struct pushbutton_work_info *info; |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 435c1958a7b7..9e1321d0d5e6 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -24,20 +24,8 @@ | |||
24 | #include "pci.h" | 24 | #include "pci.h" |
25 | #include "msi.h" | 25 | #include "msi.h" |
26 | 26 | ||
27 | static struct kmem_cache* msi_cachep; | ||
28 | |||
29 | static int pci_msi_enable = 1; | 27 | static int pci_msi_enable = 1; |
30 | 28 | ||
31 | static int msi_cache_init(void) | ||
32 | { | ||
33 | msi_cachep = kmem_cache_create("msi_cache", sizeof(struct msi_desc), | ||
34 | 0, SLAB_HWCACHE_ALIGN, NULL, NULL); | ||
35 | if (!msi_cachep) | ||
36 | return -ENOMEM; | ||
37 | |||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | static void msi_set_enable(struct pci_dev *dev, int enable) | 29 | static void msi_set_enable(struct pci_dev *dev, int enable) |
42 | { | 30 | { |
43 | int pos; | 31 | int pos; |
@@ -68,6 +56,29 @@ static void msix_set_enable(struct pci_dev *dev, int enable) | |||
68 | } | 56 | } |
69 | } | 57 | } |
70 | 58 | ||
59 | static void msix_flush_writes(unsigned int irq) | ||
60 | { | ||
61 | struct msi_desc *entry; | ||
62 | |||
63 | entry = get_irq_msi(irq); | ||
64 | BUG_ON(!entry || !entry->dev); | ||
65 | switch (entry->msi_attrib.type) { | ||
66 | case PCI_CAP_ID_MSI: | ||
67 | /* nothing to do */ | ||
68 | break; | ||
69 | case PCI_CAP_ID_MSIX: | ||
70 | { | ||
71 | int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + | ||
72 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; | ||
73 | readl(entry->mask_base + offset); | ||
74 | break; | ||
75 | } | ||
76 | default: | ||
77 | BUG(); | ||
78 | break; | ||
79 | } | ||
80 | } | ||
81 | |||
71 | static void msi_set_mask_bit(unsigned int irq, int flag) | 82 | static void msi_set_mask_bit(unsigned int irq, int flag) |
72 | { | 83 | { |
73 | struct msi_desc *entry; | 84 | struct msi_desc *entry; |
@@ -187,41 +198,28 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg) | |||
187 | void mask_msi_irq(unsigned int irq) | 198 | void mask_msi_irq(unsigned int irq) |
188 | { | 199 | { |
189 | msi_set_mask_bit(irq, 1); | 200 | msi_set_mask_bit(irq, 1); |
201 | msix_flush_writes(irq); | ||
190 | } | 202 | } |
191 | 203 | ||
192 | void unmask_msi_irq(unsigned int irq) | 204 | void unmask_msi_irq(unsigned int irq) |
193 | { | 205 | { |
194 | msi_set_mask_bit(irq, 0); | 206 | msi_set_mask_bit(irq, 0); |
207 | msix_flush_writes(irq); | ||
195 | } | 208 | } |
196 | 209 | ||
197 | static int msi_free_irq(struct pci_dev* dev, int irq); | 210 | static int msi_free_irqs(struct pci_dev* dev); |
198 | |||
199 | static int msi_init(void) | ||
200 | { | ||
201 | static int status = -ENOMEM; | ||
202 | |||
203 | if (!status) | ||
204 | return status; | ||
205 | 211 | ||
206 | status = msi_cache_init(); | ||
207 | if (status < 0) { | ||
208 | pci_msi_enable = 0; | ||
209 | printk(KERN_WARNING "PCI: MSI cache init failed\n"); | ||
210 | return status; | ||
211 | } | ||
212 | |||
213 | return status; | ||
214 | } | ||
215 | 212 | ||
216 | static struct msi_desc* alloc_msi_entry(void) | 213 | static struct msi_desc* alloc_msi_entry(void) |
217 | { | 214 | { |
218 | struct msi_desc *entry; | 215 | struct msi_desc *entry; |
219 | 216 | ||
220 | entry = kmem_cache_zalloc(msi_cachep, GFP_KERNEL); | 217 | entry = kzalloc(sizeof(struct msi_desc), GFP_KERNEL); |
221 | if (!entry) | 218 | if (!entry) |
222 | return NULL; | 219 | return NULL; |
223 | 220 | ||
224 | entry->link.tail = entry->link.head = 0; /* single message */ | 221 | INIT_LIST_HEAD(&entry->list); |
222 | entry->irq = 0; | ||
225 | entry->dev = NULL; | 223 | entry->dev = NULL; |
226 | 224 | ||
227 | return entry; | 225 | return entry; |
@@ -256,7 +254,6 @@ static void __pci_restore_msi_state(struct pci_dev *dev) | |||
256 | static void __pci_restore_msix_state(struct pci_dev *dev) | 254 | static void __pci_restore_msix_state(struct pci_dev *dev) |
257 | { | 255 | { |
258 | int pos; | 256 | int pos; |
259 | int irq, head, tail = 0; | ||
260 | struct msi_desc *entry; | 257 | struct msi_desc *entry; |
261 | u16 control; | 258 | u16 control; |
262 | 259 | ||
@@ -266,18 +263,15 @@ static void __pci_restore_msix_state(struct pci_dev *dev) | |||
266 | /* route the table */ | 263 | /* route the table */ |
267 | pci_intx(dev, 0); /* disable intx */ | 264 | pci_intx(dev, 0); /* disable intx */ |
268 | msix_set_enable(dev, 0); | 265 | msix_set_enable(dev, 0); |
269 | irq = head = dev->first_msi_irq; | ||
270 | entry = get_irq_msi(irq); | ||
271 | pos = entry->msi_attrib.pos; | ||
272 | while (head != tail) { | ||
273 | entry = get_irq_msi(irq); | ||
274 | write_msi_msg(irq, &entry->msg); | ||
275 | msi_set_mask_bit(irq, entry->msi_attrib.masked); | ||
276 | 266 | ||
277 | tail = entry->link.tail; | 267 | list_for_each_entry(entry, &dev->msi_list, list) { |
278 | irq = tail; | 268 | write_msi_msg(entry->irq, &entry->msg); |
269 | msi_set_mask_bit(entry->irq, entry->msi_attrib.masked); | ||
279 | } | 270 | } |
280 | 271 | ||
272 | BUG_ON(list_empty(&dev->msi_list)); | ||
273 | entry = list_entry(dev->msi_list.next, struct msi_desc, list); | ||
274 | pos = entry->msi_attrib.pos; | ||
281 | pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); | 275 | pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); |
282 | control &= ~PCI_MSIX_FLAGS_MASKALL; | 276 | control &= ~PCI_MSIX_FLAGS_MASKALL; |
283 | control |= PCI_MSIX_FLAGS_ENABLE; | 277 | control |= PCI_MSIX_FLAGS_ENABLE; |
@@ -303,7 +297,7 @@ void pci_restore_msi_state(struct pci_dev *dev) | |||
303 | static int msi_capability_init(struct pci_dev *dev) | 297 | static int msi_capability_init(struct pci_dev *dev) |
304 | { | 298 | { |
305 | struct msi_desc *entry; | 299 | struct msi_desc *entry; |
306 | int pos, irq; | 300 | int pos, ret; |
307 | u16 control; | 301 | u16 control; |
308 | 302 | ||
309 | msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */ | 303 | msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */ |
@@ -340,23 +334,21 @@ static int msi_capability_init(struct pci_dev *dev) | |||
340 | msi_mask_bits_reg(pos, is_64bit_address(control)), | 334 | msi_mask_bits_reg(pos, is_64bit_address(control)), |
341 | maskbits); | 335 | maskbits); |
342 | } | 336 | } |
337 | list_add(&entry->list, &dev->msi_list); | ||
338 | |||
343 | /* Configure MSI capability structure */ | 339 | /* Configure MSI capability structure */ |
344 | irq = arch_setup_msi_irq(dev, entry); | 340 | ret = arch_setup_msi_irqs(dev, 1, PCI_CAP_ID_MSI); |
345 | if (irq < 0) { | 341 | if (ret) { |
346 | kmem_cache_free(msi_cachep, entry); | 342 | msi_free_irqs(dev); |
347 | return irq; | 343 | return ret; |
348 | } | 344 | } |
349 | entry->link.head = irq; | ||
350 | entry->link.tail = irq; | ||
351 | dev->first_msi_irq = irq; | ||
352 | set_irq_msi(irq, entry); | ||
353 | 345 | ||
354 | /* Set MSI enabled bits */ | 346 | /* Set MSI enabled bits */ |
355 | pci_intx(dev, 0); /* disable intx */ | 347 | pci_intx(dev, 0); /* disable intx */ |
356 | msi_set_enable(dev, 1); | 348 | msi_set_enable(dev, 1); |
357 | dev->msi_enabled = 1; | 349 | dev->msi_enabled = 1; |
358 | 350 | ||
359 | dev->irq = irq; | 351 | dev->irq = entry->irq; |
360 | return 0; | 352 | return 0; |
361 | } | 353 | } |
362 | 354 | ||
@@ -373,8 +365,8 @@ static int msi_capability_init(struct pci_dev *dev) | |||
373 | static int msix_capability_init(struct pci_dev *dev, | 365 | static int msix_capability_init(struct pci_dev *dev, |
374 | struct msix_entry *entries, int nvec) | 366 | struct msix_entry *entries, int nvec) |
375 | { | 367 | { |
376 | struct msi_desc *head = NULL, *tail = NULL, *entry = NULL; | 368 | struct msi_desc *entry; |
377 | int irq, pos, i, j, nr_entries, temp = 0; | 369 | int pos, i, j, nr_entries, ret; |
378 | unsigned long phys_addr; | 370 | unsigned long phys_addr; |
379 | u32 table_offset; | 371 | u32 table_offset; |
380 | u16 control; | 372 | u16 control; |
@@ -413,44 +405,34 @@ static int msix_capability_init(struct pci_dev *dev, | |||
413 | entry->dev = dev; | 405 | entry->dev = dev; |
414 | entry->mask_base = base; | 406 | entry->mask_base = base; |
415 | 407 | ||
416 | /* Configure MSI-X capability structure */ | 408 | list_add(&entry->list, &dev->msi_list); |
417 | irq = arch_setup_msi_irq(dev, entry); | ||
418 | if (irq < 0) { | ||
419 | kmem_cache_free(msi_cachep, entry); | ||
420 | break; | ||
421 | } | ||
422 | entries[i].vector = irq; | ||
423 | if (!head) { | ||
424 | entry->link.head = irq; | ||
425 | entry->link.tail = irq; | ||
426 | head = entry; | ||
427 | } else { | ||
428 | entry->link.head = temp; | ||
429 | entry->link.tail = tail->link.tail; | ||
430 | tail->link.tail = irq; | ||
431 | head->link.head = irq; | ||
432 | } | ||
433 | temp = irq; | ||
434 | tail = entry; | ||
435 | |||
436 | set_irq_msi(irq, entry); | ||
437 | } | 409 | } |
438 | if (i != nvec) { | 410 | |
439 | int avail = i - 1; | 411 | ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); |
440 | i--; | 412 | if (ret) { |
441 | for (; i >= 0; i--) { | 413 | int avail = 0; |
442 | irq = (entries + i)->vector; | 414 | list_for_each_entry(entry, &dev->msi_list, list) { |
443 | msi_free_irq(dev, irq); | 415 | if (entry->irq != 0) { |
444 | (entries + i)->vector = 0; | 416 | avail++; |
417 | } | ||
445 | } | 418 | } |
419 | |||
420 | msi_free_irqs(dev); | ||
421 | |||
446 | /* If we had some success report the number of irqs | 422 | /* If we had some success report the number of irqs |
447 | * we succeeded in setting up. | 423 | * we succeeded in setting up. |
448 | */ | 424 | */ |
449 | if (avail <= 0) | 425 | if (avail == 0) |
450 | avail = -EBUSY; | 426 | avail = ret; |
451 | return avail; | 427 | return avail; |
452 | } | 428 | } |
453 | dev->first_msi_irq = entries[0].vector; | 429 | |
430 | i = 0; | ||
431 | list_for_each_entry(entry, &dev->msi_list, list) { | ||
432 | entries[i].vector = entry->irq; | ||
433 | set_irq_msi(entry->irq, entry); | ||
434 | i++; | ||
435 | } | ||
454 | /* Set MSI-X enabled bits */ | 436 | /* Set MSI-X enabled bits */ |
455 | pci_intx(dev, 0); /* disable intx */ | 437 | pci_intx(dev, 0); /* disable intx */ |
456 | msix_set_enable(dev, 1); | 438 | msix_set_enable(dev, 1); |
@@ -460,21 +442,32 @@ static int msix_capability_init(struct pci_dev *dev, | |||
460 | } | 442 | } |
461 | 443 | ||
462 | /** | 444 | /** |
463 | * pci_msi_supported - check whether MSI may be enabled on device | 445 | * pci_msi_check_device - check whether MSI may be enabled on a device |
464 | * @dev: pointer to the pci_dev data structure of MSI device function | 446 | * @dev: pointer to the pci_dev data structure of MSI device function |
447 | * @nvec: how many MSIs have been requested ? | ||
448 | * @type: are we checking for MSI or MSI-X ? | ||
465 | * | 449 | * |
466 | * Look at global flags, the device itself, and its parent busses | 450 | * Look at global flags, the device itself, and its parent busses |
467 | * to return 0 if MSI are supported for the device. | 451 | * to determine if MSI/-X are supported for the device. If MSI/-X is |
452 | * supported return 0, else return an error code. | ||
468 | **/ | 453 | **/ |
469 | static | 454 | static int pci_msi_check_device(struct pci_dev* dev, int nvec, int type) |
470 | int pci_msi_supported(struct pci_dev * dev) | ||
471 | { | 455 | { |
472 | struct pci_bus *bus; | 456 | struct pci_bus *bus; |
457 | int ret; | ||
473 | 458 | ||
474 | /* MSI must be globally enabled and supported by the device */ | 459 | /* MSI must be globally enabled and supported by the device */ |
475 | if (!pci_msi_enable || !dev || dev->no_msi) | 460 | if (!pci_msi_enable || !dev || dev->no_msi) |
476 | return -EINVAL; | 461 | return -EINVAL; |
477 | 462 | ||
463 | /* | ||
464 | * You can't ask to have 0 or less MSIs configured. | ||
465 | * a) it's stupid .. | ||
466 | * b) the list manipulation code assumes nvec >= 1. | ||
467 | */ | ||
468 | if (nvec < 1) | ||
469 | return -ERANGE; | ||
470 | |||
478 | /* Any bridge which does NOT route MSI transactions from it's | 471 | /* Any bridge which does NOT route MSI transactions from it's |
479 | * secondary bus to it's primary bus must set NO_MSI flag on | 472 | * secondary bus to it's primary bus must set NO_MSI flag on |
480 | * the secondary pci_bus. | 473 | * the secondary pci_bus. |
@@ -485,6 +478,13 @@ int pci_msi_supported(struct pci_dev * dev) | |||
485 | if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) | 478 | if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) |
486 | return -EINVAL; | 479 | return -EINVAL; |
487 | 480 | ||
481 | ret = arch_msi_check_device(dev, nvec, type); | ||
482 | if (ret) | ||
483 | return ret; | ||
484 | |||
485 | if (!pci_find_capability(dev, type)) | ||
486 | return -EINVAL; | ||
487 | |||
488 | return 0; | 488 | return 0; |
489 | } | 489 | } |
490 | 490 | ||
@@ -500,19 +500,12 @@ int pci_msi_supported(struct pci_dev * dev) | |||
500 | **/ | 500 | **/ |
501 | int pci_enable_msi(struct pci_dev* dev) | 501 | int pci_enable_msi(struct pci_dev* dev) |
502 | { | 502 | { |
503 | int pos, status; | 503 | int status; |
504 | |||
505 | if (pci_msi_supported(dev) < 0) | ||
506 | return -EINVAL; | ||
507 | 504 | ||
508 | status = msi_init(); | 505 | status = pci_msi_check_device(dev, 1, PCI_CAP_ID_MSI); |
509 | if (status < 0) | 506 | if (status) |
510 | return status; | 507 | return status; |
511 | 508 | ||
512 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | ||
513 | if (!pos) | ||
514 | return -EINVAL; | ||
515 | |||
516 | WARN_ON(!!dev->msi_enabled); | 509 | WARN_ON(!!dev->msi_enabled); |
517 | 510 | ||
518 | /* Check whether driver already requested for MSI-X irqs */ | 511 | /* Check whether driver already requested for MSI-X irqs */ |
@@ -525,69 +518,54 @@ int pci_enable_msi(struct pci_dev* dev) | |||
525 | status = msi_capability_init(dev); | 518 | status = msi_capability_init(dev); |
526 | return status; | 519 | return status; |
527 | } | 520 | } |
521 | EXPORT_SYMBOL(pci_enable_msi); | ||
528 | 522 | ||
529 | void pci_disable_msi(struct pci_dev* dev) | 523 | void pci_disable_msi(struct pci_dev* dev) |
530 | { | 524 | { |
531 | struct msi_desc *entry; | 525 | struct msi_desc *entry; |
532 | int default_irq; | 526 | int default_irq; |
533 | 527 | ||
534 | if (!pci_msi_enable) | 528 | if (!pci_msi_enable || !dev || !dev->msi_enabled) |
535 | return; | ||
536 | if (!dev) | ||
537 | return; | ||
538 | |||
539 | if (!dev->msi_enabled) | ||
540 | return; | 529 | return; |
541 | 530 | ||
542 | msi_set_enable(dev, 0); | 531 | msi_set_enable(dev, 0); |
543 | pci_intx(dev, 1); /* enable intx */ | 532 | pci_intx(dev, 1); /* enable intx */ |
544 | dev->msi_enabled = 0; | 533 | dev->msi_enabled = 0; |
545 | 534 | ||
546 | entry = get_irq_msi(dev->first_msi_irq); | 535 | BUG_ON(list_empty(&dev->msi_list)); |
547 | if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { | 536 | entry = list_entry(dev->msi_list.next, struct msi_desc, list); |
537 | if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { | ||
548 | return; | 538 | return; |
549 | } | 539 | } |
550 | if (irq_has_action(dev->first_msi_irq)) { | 540 | |
551 | printk(KERN_WARNING "PCI: %s: pci_disable_msi() called without " | 541 | default_irq = entry->msi_attrib.default_irq; |
552 | "free_irq() on MSI irq %d\n", | 542 | msi_free_irqs(dev); |
553 | pci_name(dev), dev->first_msi_irq); | 543 | |
554 | BUG_ON(irq_has_action(dev->first_msi_irq)); | 544 | /* Restore dev->irq to its default pin-assertion irq */ |
555 | } else { | 545 | dev->irq = default_irq; |
556 | default_irq = entry->msi_attrib.default_irq; | ||
557 | msi_free_irq(dev, dev->first_msi_irq); | ||
558 | |||
559 | /* Restore dev->irq to its default pin-assertion irq */ | ||
560 | dev->irq = default_irq; | ||
561 | } | ||
562 | dev->first_msi_irq = 0; | ||
563 | } | 546 | } |
547 | EXPORT_SYMBOL(pci_disable_msi); | ||
564 | 548 | ||
565 | static int msi_free_irq(struct pci_dev* dev, int irq) | 549 | static int msi_free_irqs(struct pci_dev* dev) |
566 | { | 550 | { |
567 | struct msi_desc *entry; | 551 | struct msi_desc *entry, *tmp; |
568 | int head, entry_nr, type; | ||
569 | void __iomem *base; | ||
570 | 552 | ||
571 | entry = get_irq_msi(irq); | 553 | list_for_each_entry(entry, &dev->msi_list, list) |
572 | if (!entry || entry->dev != dev) { | 554 | BUG_ON(irq_has_action(entry->irq)); |
573 | return -EINVAL; | 555 | |
574 | } | 556 | arch_teardown_msi_irqs(dev); |
575 | type = entry->msi_attrib.type; | 557 | |
576 | entry_nr = entry->msi_attrib.entry_nr; | 558 | list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { |
577 | head = entry->link.head; | 559 | if (entry->msi_attrib.type == PCI_CAP_ID_MSIX) { |
578 | base = entry->mask_base; | 560 | if (list_is_last(&entry->list, &dev->msi_list)) |
579 | get_irq_msi(entry->link.head)->link.tail = entry->link.tail; | 561 | iounmap(entry->mask_base); |
580 | get_irq_msi(entry->link.tail)->link.head = entry->link.head; | 562 | |
581 | 563 | writel(1, entry->mask_base + entry->msi_attrib.entry_nr | |
582 | arch_teardown_msi_irq(irq); | 564 | * PCI_MSIX_ENTRY_SIZE |
583 | kmem_cache_free(msi_cachep, entry); | 565 | + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); |
584 | 566 | } | |
585 | if (type == PCI_CAP_ID_MSIX) { | 567 | list_del(&entry->list); |
586 | writel(1, base + entry_nr * PCI_MSIX_ENTRY_SIZE + | 568 | kfree(entry); |
587 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); | ||
588 | |||
589 | if (head == irq) | ||
590 | iounmap(base); | ||
591 | } | 569 | } |
592 | 570 | ||
593 | return 0; | 571 | return 0; |
@@ -614,17 +592,14 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | |||
614 | int i, j; | 592 | int i, j; |
615 | u16 control; | 593 | u16 control; |
616 | 594 | ||
617 | if (!entries || pci_msi_supported(dev) < 0) | 595 | if (!entries) |
618 | return -EINVAL; | 596 | return -EINVAL; |
619 | 597 | ||
620 | status = msi_init(); | 598 | status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX); |
621 | if (status < 0) | 599 | if (status) |
622 | return status; | 600 | return status; |
623 | 601 | ||
624 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | 602 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); |
625 | if (!pos) | ||
626 | return -EINVAL; | ||
627 | |||
628 | pci_read_config_word(dev, msi_control_reg(pos), &control); | 603 | pci_read_config_word(dev, msi_control_reg(pos), &control); |
629 | nr_entries = multi_msix_capable(control); | 604 | nr_entries = multi_msix_capable(control); |
630 | if (nvec > nr_entries) | 605 | if (nvec > nr_entries) |
@@ -651,41 +626,25 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | |||
651 | status = msix_capability_init(dev, entries, nvec); | 626 | status = msix_capability_init(dev, entries, nvec); |
652 | return status; | 627 | return status; |
653 | } | 628 | } |
629 | EXPORT_SYMBOL(pci_enable_msix); | ||
654 | 630 | ||
655 | void pci_disable_msix(struct pci_dev* dev) | 631 | static void msix_free_all_irqs(struct pci_dev *dev) |
656 | { | 632 | { |
657 | int irq, head, tail = 0, warning = 0; | 633 | msi_free_irqs(dev); |
658 | 634 | } | |
659 | if (!pci_msi_enable) | ||
660 | return; | ||
661 | if (!dev) | ||
662 | return; | ||
663 | 635 | ||
664 | if (!dev->msix_enabled) | 636 | void pci_disable_msix(struct pci_dev* dev) |
637 | { | ||
638 | if (!pci_msi_enable || !dev || !dev->msix_enabled) | ||
665 | return; | 639 | return; |
666 | 640 | ||
667 | msix_set_enable(dev, 0); | 641 | msix_set_enable(dev, 0); |
668 | pci_intx(dev, 1); /* enable intx */ | 642 | pci_intx(dev, 1); /* enable intx */ |
669 | dev->msix_enabled = 0; | 643 | dev->msix_enabled = 0; |
670 | 644 | ||
671 | irq = head = dev->first_msi_irq; | 645 | msix_free_all_irqs(dev); |
672 | while (head != tail) { | ||
673 | tail = get_irq_msi(irq)->link.tail; | ||
674 | if (irq_has_action(irq)) | ||
675 | warning = 1; | ||
676 | else if (irq != head) /* Release MSI-X irq */ | ||
677 | msi_free_irq(dev, irq); | ||
678 | irq = tail; | ||
679 | } | ||
680 | msi_free_irq(dev, irq); | ||
681 | if (warning) { | ||
682 | printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without " | ||
683 | "free_irq() on all MSI-X irqs\n", | ||
684 | pci_name(dev)); | ||
685 | BUG_ON(warning > 0); | ||
686 | } | ||
687 | dev->first_msi_irq = 0; | ||
688 | } | 646 | } |
647 | EXPORT_SYMBOL(pci_disable_msix); | ||
689 | 648 | ||
690 | /** | 649 | /** |
691 | * msi_remove_pci_irq_vectors - reclaim MSI(X) irqs to unused state | 650 | * msi_remove_pci_irq_vectors - reclaim MSI(X) irqs to unused state |
@@ -701,38 +660,11 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) | |||
701 | if (!pci_msi_enable || !dev) | 660 | if (!pci_msi_enable || !dev) |
702 | return; | 661 | return; |
703 | 662 | ||
704 | if (dev->msi_enabled) { | 663 | if (dev->msi_enabled) |
705 | if (irq_has_action(dev->first_msi_irq)) { | 664 | msi_free_irqs(dev); |
706 | printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " | 665 | |
707 | "called without free_irq() on MSI irq %d\n", | 666 | if (dev->msix_enabled) |
708 | pci_name(dev), dev->first_msi_irq); | 667 | msix_free_all_irqs(dev); |
709 | BUG_ON(irq_has_action(dev->first_msi_irq)); | ||
710 | } else /* Release MSI irq assigned to this device */ | ||
711 | msi_free_irq(dev, dev->first_msi_irq); | ||
712 | } | ||
713 | if (dev->msix_enabled) { | ||
714 | int irq, head, tail = 0, warning = 0; | ||
715 | void __iomem *base = NULL; | ||
716 | |||
717 | irq = head = dev->first_msi_irq; | ||
718 | while (head != tail) { | ||
719 | tail = get_irq_msi(irq)->link.tail; | ||
720 | base = get_irq_msi(irq)->mask_base; | ||
721 | if (irq_has_action(irq)) | ||
722 | warning = 1; | ||
723 | else if (irq != head) /* Release MSI-X irq */ | ||
724 | msi_free_irq(dev, irq); | ||
725 | irq = tail; | ||
726 | } | ||
727 | msi_free_irq(dev, irq); | ||
728 | if (warning) { | ||
729 | iounmap(base); | ||
730 | printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " | ||
731 | "called without free_irq() on all MSI-X irqs\n", | ||
732 | pci_name(dev)); | ||
733 | BUG_ON(warning > 0); | ||
734 | } | ||
735 | } | ||
736 | } | 668 | } |
737 | 669 | ||
738 | void pci_no_msi(void) | 670 | void pci_no_msi(void) |
@@ -740,7 +672,53 @@ void pci_no_msi(void) | |||
740 | pci_msi_enable = 0; | 672 | pci_msi_enable = 0; |
741 | } | 673 | } |
742 | 674 | ||
743 | EXPORT_SYMBOL(pci_enable_msi); | 675 | void pci_msi_init_pci_dev(struct pci_dev *dev) |
744 | EXPORT_SYMBOL(pci_disable_msi); | 676 | { |
745 | EXPORT_SYMBOL(pci_enable_msix); | 677 | INIT_LIST_HEAD(&dev->msi_list); |
746 | EXPORT_SYMBOL(pci_disable_msix); | 678 | } |
679 | |||
680 | |||
681 | /* Arch hooks */ | ||
682 | |||
683 | int __attribute__ ((weak)) | ||
684 | arch_msi_check_device(struct pci_dev* dev, int nvec, int type) | ||
685 | { | ||
686 | return 0; | ||
687 | } | ||
688 | |||
689 | int __attribute__ ((weak)) | ||
690 | arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry) | ||
691 | { | ||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | int __attribute__ ((weak)) | ||
696 | arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | ||
697 | { | ||
698 | struct msi_desc *entry; | ||
699 | int ret; | ||
700 | |||
701 | list_for_each_entry(entry, &dev->msi_list, list) { | ||
702 | ret = arch_setup_msi_irq(dev, entry); | ||
703 | if (ret) | ||
704 | return ret; | ||
705 | } | ||
706 | |||
707 | return 0; | ||
708 | } | ||
709 | |||
710 | void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq) | ||
711 | { | ||
712 | return; | ||
713 | } | ||
714 | |||
715 | void __attribute__ ((weak)) | ||
716 | arch_teardown_msi_irqs(struct pci_dev *dev) | ||
717 | { | ||
718 | struct msi_desc *entry; | ||
719 | |||
720 | list_for_each_entry(entry, &dev->msi_list, list) { | ||
721 | if (entry->irq != 0) | ||
722 | arch_teardown_msi_irq(entry->irq); | ||
723 | } | ||
724 | } | ||
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 39e80fcef4b3..3bb7739d26a5 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -14,20 +14,6 @@ | |||
14 | #include "pci.h" | 14 | #include "pci.h" |
15 | 15 | ||
16 | /* | 16 | /* |
17 | * Registration of PCI drivers and handling of hot-pluggable devices. | ||
18 | */ | ||
19 | |||
20 | /* multithreaded probe logic */ | ||
21 | static int pci_multithread_probe = | ||
22 | #ifdef CONFIG_PCI_MULTITHREAD_PROBE | ||
23 | 1; | ||
24 | #else | ||
25 | 0; | ||
26 | #endif | ||
27 | __module_param_call("", pci_multithread_probe, param_set_bool, param_get_bool, &pci_multithread_probe, 0644); | ||
28 | |||
29 | |||
30 | /* | ||
31 | * Dynamic device IDs are disabled for !CONFIG_HOTPLUG | 17 | * Dynamic device IDs are disabled for !CONFIG_HOTPLUG |
32 | */ | 18 | */ |
33 | 19 | ||
@@ -52,7 +38,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) | |||
52 | { | 38 | { |
53 | struct pci_dynid *dynid; | 39 | struct pci_dynid *dynid; |
54 | struct pci_driver *pdrv = to_pci_driver(driver); | 40 | struct pci_driver *pdrv = to_pci_driver(driver); |
55 | __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID, | 41 | __u32 vendor, device, subvendor=PCI_ANY_ID, |
56 | subdevice=PCI_ANY_ID, class=0, class_mask=0; | 42 | subdevice=PCI_ANY_ID, class=0, class_mask=0; |
57 | unsigned long driver_data=0; | 43 | unsigned long driver_data=0; |
58 | int fields=0; | 44 | int fields=0; |
@@ -61,7 +47,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) | |||
61 | fields = sscanf(buf, "%x %x %x %x %x %x %lux", | 47 | fields = sscanf(buf, "%x %x %x %x %x %x %lux", |
62 | &vendor, &device, &subvendor, &subdevice, | 48 | &vendor, &device, &subvendor, &subdevice, |
63 | &class, &class_mask, &driver_data); | 49 | &class, &class_mask, &driver_data); |
64 | if (fields < 0) | 50 | if (fields < 2) |
65 | return -EINVAL; | 51 | return -EINVAL; |
66 | 52 | ||
67 | dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); | 53 | dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); |
@@ -569,7 +555,6 @@ struct bus_type pci_bus_type = { | |||
569 | 555 | ||
570 | static int __init pci_driver_init(void) | 556 | static int __init pci_driver_init(void) |
571 | { | 557 | { |
572 | pci_bus_type.multithread_probe = pci_multithread_probe; | ||
573 | return bus_register(&pci_bus_type); | 558 | return bus_register(&pci_bus_type); |
574 | } | 559 | } |
575 | 560 | ||
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index cd913a2a416f..284e83a527f9 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -620,7 +620,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) | |||
620 | goto err_bin_file; | 620 | goto err_bin_file; |
621 | 621 | ||
622 | /* If the device has a ROM, try to expose it in sysfs. */ | 622 | /* If the device has a ROM, try to expose it in sysfs. */ |
623 | if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) { | 623 | if (pci_resource_len(pdev, PCI_ROM_RESOURCE) || |
624 | (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) { | ||
624 | rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC); | 625 | rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC); |
625 | if (rom_attr) { | 626 | if (rom_attr) { |
626 | pdev->rom_attr = rom_attr; | 627 | pdev->rom_attr = rom_attr; |
@@ -635,7 +636,7 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) | |||
635 | goto err_rom; | 636 | goto err_rom; |
636 | } else { | 637 | } else { |
637 | retval = -ENOMEM; | 638 | retval = -ENOMEM; |
638 | goto err_bin_file; | 639 | goto err_resource_files; |
639 | } | 640 | } |
640 | } | 641 | } |
641 | /* add platform-specific attributes */ | 642 | /* add platform-specific attributes */ |
@@ -645,6 +646,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) | |||
645 | 646 | ||
646 | err_rom: | 647 | err_rom: |
647 | kfree(rom_attr); | 648 | kfree(rom_attr); |
649 | err_resource_files: | ||
650 | pci_remove_resource_files(pdev); | ||
648 | err_bin_file: | 651 | err_bin_file: |
649 | if (pdev->cfg_size < 4096) | 652 | if (pdev->cfg_size < 4096) |
650 | sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); | 653 | sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); |
@@ -695,4 +698,4 @@ static int __init pci_sysfs_init(void) | |||
695 | return 0; | 698 | return 0; |
696 | } | 699 | } |
697 | 700 | ||
698 | __initcall(pci_sysfs_init); | 701 | late_initcall(pci_sysfs_init); |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 2a458279327a..fd47ac0c4730 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -35,8 +35,7 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE; | |||
35 | * Given a PCI bus, returns the highest PCI bus number present in the set | 35 | * Given a PCI bus, returns the highest PCI bus number present in the set |
36 | * including the given PCI bus and its list of child PCI buses. | 36 | * including the given PCI bus and its list of child PCI buses. |
37 | */ | 37 | */ |
38 | unsigned char __devinit | 38 | unsigned char pci_bus_max_busnr(struct pci_bus* bus) |
39 | pci_bus_max_busnr(struct pci_bus* bus) | ||
40 | { | 39 | { |
41 | struct list_head *tmp; | 40 | struct list_head *tmp; |
42 | unsigned char max, n; | 41 | unsigned char max, n; |
@@ -892,6 +891,34 @@ pci_disable_device(struct pci_dev *dev) | |||
892 | } | 891 | } |
893 | 892 | ||
894 | /** | 893 | /** |
894 | * pcibios_set_pcie_reset_state - set reset state for device dev | ||
895 | * @dev: the PCI-E device reset | ||
896 | * @state: Reset state to enter into | ||
897 | * | ||
898 | * | ||
899 | * Sets the PCI-E reset state for the device. This is the default | ||
900 | * implementation. Architecture implementations can override this. | ||
901 | */ | ||
902 | int __attribute__ ((weak)) pcibios_set_pcie_reset_state(struct pci_dev *dev, | ||
903 | enum pcie_reset_state state) | ||
904 | { | ||
905 | return -EINVAL; | ||
906 | } | ||
907 | |||
908 | /** | ||
909 | * pci_set_pcie_reset_state - set reset state for device dev | ||
910 | * @dev: the PCI-E device reset | ||
911 | * @state: Reset state to enter into | ||
912 | * | ||
913 | * | ||
914 | * Sets the PCI reset state for the device. | ||
915 | */ | ||
916 | int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) | ||
917 | { | ||
918 | return pcibios_set_pcie_reset_state(dev, state); | ||
919 | } | ||
920 | |||
921 | /** | ||
895 | * pci_enable_wake - enable PCI device as wakeup event source | 922 | * pci_enable_wake - enable PCI device as wakeup event source |
896 | * @dev: PCI device affected | 923 | * @dev: PCI device affected |
897 | * @state: PCI state from which device will issue wakeup events | 924 | * @state: PCI state from which device will issue wakeup events |
@@ -1295,7 +1322,7 @@ pci_intx(struct pci_dev *pdev, int enable) | |||
1295 | 1322 | ||
1296 | /** | 1323 | /** |
1297 | * pci_msi_off - disables any msi or msix capabilities | 1324 | * pci_msi_off - disables any msi or msix capabilities |
1298 | * @pdev: the PCI device to operate on | 1325 | * @dev: the PCI device to operate on |
1299 | * | 1326 | * |
1300 | * If you want to use msi see pci_enable_msi and friends. | 1327 | * If you want to use msi see pci_enable_msi and friends. |
1301 | * This is a lower level primitive that allows us to disable | 1328 | * This is a lower level primitive that allows us to disable |
@@ -1427,4 +1454,5 @@ EXPORT_SYMBOL(pci_set_power_state); | |||
1427 | EXPORT_SYMBOL(pci_save_state); | 1454 | EXPORT_SYMBOL(pci_save_state); |
1428 | EXPORT_SYMBOL(pci_restore_state); | 1455 | EXPORT_SYMBOL(pci_restore_state); |
1429 | EXPORT_SYMBOL(pci_enable_wake); | 1456 | EXPORT_SYMBOL(pci_enable_wake); |
1457 | EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state); | ||
1430 | 1458 | ||
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 62ea04c8af64..3fec13d3add7 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -47,8 +47,10 @@ extern unsigned int pci_pm_d3_delay; | |||
47 | 47 | ||
48 | #ifdef CONFIG_PCI_MSI | 48 | #ifdef CONFIG_PCI_MSI |
49 | void pci_no_msi(void); | 49 | void pci_no_msi(void); |
50 | extern void pci_msi_init_pci_dev(struct pci_dev *dev); | ||
50 | #else | 51 | #else |
51 | static inline void pci_no_msi(void) { } | 52 | static inline void pci_no_msi(void) { } |
53 | static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } | ||
52 | #endif | 54 | #endif |
53 | 55 | ||
54 | #if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM) | 56 | #if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM) |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 2fe1d690eb13..e48fcf089621 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -364,7 +364,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) | |||
364 | } | 364 | } |
365 | } | 365 | } |
366 | 366 | ||
367 | static struct pci_bus * __devinit pci_alloc_bus(void) | 367 | static struct pci_bus * pci_alloc_bus(void) |
368 | { | 368 | { |
369 | struct pci_bus *b; | 369 | struct pci_bus *b; |
370 | 370 | ||
@@ -432,7 +432,7 @@ error_register: | |||
432 | return NULL; | 432 | return NULL; |
433 | } | 433 | } |
434 | 434 | ||
435 | struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr) | 435 | struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr) |
436 | { | 436 | { |
437 | struct pci_bus *child; | 437 | struct pci_bus *child; |
438 | 438 | ||
@@ -461,7 +461,7 @@ static void pci_enable_crs(struct pci_dev *dev) | |||
461 | pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl); | 461 | pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl); |
462 | } | 462 | } |
463 | 463 | ||
464 | static void __devinit pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max) | 464 | static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max) |
465 | { | 465 | { |
466 | struct pci_bus *parent = child->parent; | 466 | struct pci_bus *parent = child->parent; |
467 | 467 | ||
@@ -477,7 +477,7 @@ static void __devinit pci_fixup_parent_subordinate_busnr(struct pci_bus *child, | |||
477 | } | 477 | } |
478 | } | 478 | } |
479 | 479 | ||
480 | unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus); | 480 | unsigned int pci_scan_child_bus(struct pci_bus *bus); |
481 | 481 | ||
482 | /* | 482 | /* |
483 | * If it's a bridge, configure it and scan the bus behind it. | 483 | * If it's a bridge, configure it and scan the bus behind it. |
@@ -489,7 +489,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus); | |||
489 | * them, we proceed to assigning numbers to the remaining buses in | 489 | * them, we proceed to assigning numbers to the remaining buses in |
490 | * order to avoid overlaps between old and new bus numbers. | 490 | * order to avoid overlaps between old and new bus numbers. |
491 | */ | 491 | */ |
492 | int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass) | 492 | int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass) |
493 | { | 493 | { |
494 | struct pci_bus *child; | 494 | struct pci_bus *child; |
495 | int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS); | 495 | int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS); |
@@ -846,6 +846,23 @@ static void pci_release_bus_bridge_dev(struct device *dev) | |||
846 | kfree(dev); | 846 | kfree(dev); |
847 | } | 847 | } |
848 | 848 | ||
849 | struct pci_dev *alloc_pci_dev(void) | ||
850 | { | ||
851 | struct pci_dev *dev; | ||
852 | |||
853 | dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); | ||
854 | if (!dev) | ||
855 | return NULL; | ||
856 | |||
857 | INIT_LIST_HEAD(&dev->global_list); | ||
858 | INIT_LIST_HEAD(&dev->bus_list); | ||
859 | |||
860 | pci_msi_init_pci_dev(dev); | ||
861 | |||
862 | return dev; | ||
863 | } | ||
864 | EXPORT_SYMBOL(alloc_pci_dev); | ||
865 | |||
849 | /* | 866 | /* |
850 | * Read the config data for a PCI device, sanity-check it | 867 | * Read the config data for a PCI device, sanity-check it |
851 | * and fill in the dev structure... | 868 | * and fill in the dev structure... |
@@ -885,7 +902,7 @@ pci_scan_device(struct pci_bus *bus, int devfn) | |||
885 | if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type)) | 902 | if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type)) |
886 | return NULL; | 903 | return NULL; |
887 | 904 | ||
888 | dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); | 905 | dev = alloc_pci_dev(); |
889 | if (!dev) | 906 | if (!dev) |
890 | return NULL; | 907 | return NULL; |
891 | 908 | ||
@@ -912,7 +929,7 @@ pci_scan_device(struct pci_bus *bus, int devfn) | |||
912 | return dev; | 929 | return dev; |
913 | } | 930 | } |
914 | 931 | ||
915 | void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus) | 932 | void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) |
916 | { | 933 | { |
917 | device_initialize(&dev->dev); | 934 | device_initialize(&dev->dev); |
918 | dev->dev.release = pci_release_dev; | 935 | dev->dev.release = pci_release_dev; |
@@ -935,8 +952,7 @@ void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus) | |||
935 | up_write(&pci_bus_sem); | 952 | up_write(&pci_bus_sem); |
936 | } | 953 | } |
937 | 954 | ||
938 | struct pci_dev * __devinit | 955 | struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn) |
939 | pci_scan_single_device(struct pci_bus *bus, int devfn) | ||
940 | { | 956 | { |
941 | struct pci_dev *dev; | 957 | struct pci_dev *dev; |
942 | 958 | ||
@@ -958,7 +974,7 @@ pci_scan_single_device(struct pci_bus *bus, int devfn) | |||
958 | * discovered devices to the @bus->devices list. New devices | 974 | * discovered devices to the @bus->devices list. New devices |
959 | * will have an empty dev->global_list head. | 975 | * will have an empty dev->global_list head. |
960 | */ | 976 | */ |
961 | int __devinit pci_scan_slot(struct pci_bus *bus, int devfn) | 977 | int pci_scan_slot(struct pci_bus *bus, int devfn) |
962 | { | 978 | { |
963 | int func, nr = 0; | 979 | int func, nr = 0; |
964 | int scan_all_fns; | 980 | int scan_all_fns; |
@@ -991,7 +1007,7 @@ int __devinit pci_scan_slot(struct pci_bus *bus, int devfn) | |||
991 | return nr; | 1007 | return nr; |
992 | } | 1008 | } |
993 | 1009 | ||
994 | unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) | 1010 | unsigned int pci_scan_child_bus(struct pci_bus *bus) |
995 | { | 1011 | { |
996 | unsigned int devfn, pass, max = bus->secondary; | 1012 | unsigned int devfn, pass, max = bus->secondary; |
997 | struct pci_dev *dev; | 1013 | struct pci_dev *dev; |
@@ -1041,7 +1057,7 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus) | |||
1041 | return max; | 1057 | return max; |
1042 | } | 1058 | } |
1043 | 1059 | ||
1044 | struct pci_bus * __devinit pci_create_bus(struct device *parent, | 1060 | struct pci_bus * pci_create_bus(struct device *parent, |
1045 | int bus, struct pci_ops *ops, void *sysdata) | 1061 | int bus, struct pci_ops *ops, void *sysdata) |
1046 | { | 1062 | { |
1047 | int error; | 1063 | int error; |
@@ -1119,7 +1135,7 @@ err_out: | |||
1119 | } | 1135 | } |
1120 | EXPORT_SYMBOL_GPL(pci_create_bus); | 1136 | EXPORT_SYMBOL_GPL(pci_create_bus); |
1121 | 1137 | ||
1122 | struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, | 1138 | struct pci_bus *pci_scan_bus_parented(struct device *parent, |
1123 | int bus, struct pci_ops *ops, void *sysdata) | 1139 | int bus, struct pci_ops *ops, void *sysdata) |
1124 | { | 1140 | { |
1125 | struct pci_bus *b; | 1141 | struct pci_bus *b; |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 3411483240cd..147d86f8edbf 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -1648,6 +1648,8 @@ static void __devinit quirk_disable_msi(struct pci_dev *dev) | |||
1648 | } | 1648 | } |
1649 | } | 1649 | } |
1650 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi); | 1650 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi); |
1651 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_msi); | ||
1652 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_msi); | ||
1651 | 1653 | ||
1652 | /* Go through the list of Hypertransport capabilities and | 1654 | /* Go through the list of Hypertransport capabilities and |
1653 | * return 1 if a HT MSI capability is found and enabled */ | 1655 | * return 1 if a HT MSI capability is found and enabled */ |
diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 2dd8681d6b31..b137a27472c7 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c | |||
@@ -15,8 +15,7 @@ | |||
15 | 15 | ||
16 | DECLARE_RWSEM(pci_bus_sem); | 16 | DECLARE_RWSEM(pci_bus_sem); |
17 | 17 | ||
18 | static struct pci_bus * | 18 | static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr) |
19 | pci_do_find_bus(struct pci_bus* bus, unsigned char busnr) | ||
20 | { | 19 | { |
21 | struct pci_bus* child; | 20 | struct pci_bus* child; |
22 | struct list_head *tmp; | 21 | struct list_head *tmp; |
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 3554f3948814..5ec297d7a5b4 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -36,8 +36,7 @@ | |||
36 | 36 | ||
37 | #define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) | 37 | #define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) |
38 | 38 | ||
39 | static void __devinit | 39 | static void pbus_assign_resources_sorted(struct pci_bus *bus) |
40 | pbus_assign_resources_sorted(struct pci_bus *bus) | ||
41 | { | 40 | { |
42 | struct pci_dev *dev; | 41 | struct pci_dev *dev; |
43 | struct resource *res; | 42 | struct resource *res; |
@@ -220,8 +219,7 @@ pci_setup_bridge(struct pci_bus *bus) | |||
220 | /* Check whether the bridge supports optional I/O and | 219 | /* Check whether the bridge supports optional I/O and |
221 | prefetchable memory ranges. If not, the respective | 220 | prefetchable memory ranges. If not, the respective |
222 | base/limit registers must be read-only and read as 0. */ | 221 | base/limit registers must be read-only and read as 0. */ |
223 | static void __devinit | 222 | static void pci_bridge_check_ranges(struct pci_bus *bus) |
224 | pci_bridge_check_ranges(struct pci_bus *bus) | ||
225 | { | 223 | { |
226 | u16 io; | 224 | u16 io; |
227 | u32 pmem; | 225 | u32 pmem; |
@@ -259,8 +257,7 @@ pci_bridge_check_ranges(struct pci_bus *bus) | |||
259 | bus resource of a given type. Note: we intentionally skip | 257 | bus resource of a given type. Note: we intentionally skip |
260 | the bus resources which have already been assigned (that is, | 258 | the bus resources which have already been assigned (that is, |
261 | have non-NULL parent resource). */ | 259 | have non-NULL parent resource). */ |
262 | static struct resource * __devinit | 260 | static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned long type) |
263 | find_free_bus_resource(struct pci_bus *bus, unsigned long type) | ||
264 | { | 261 | { |
265 | int i; | 262 | int i; |
266 | struct resource *r; | 263 | struct resource *r; |
@@ -281,8 +278,7 @@ find_free_bus_resource(struct pci_bus *bus, unsigned long type) | |||
281 | since these windows have 4K granularity and the IO ranges | 278 | since these windows have 4K granularity and the IO ranges |
282 | of non-bridge PCI devices are limited to 256 bytes. | 279 | of non-bridge PCI devices are limited to 256 bytes. |
283 | We must be careful with the ISA aliasing though. */ | 280 | We must be careful with the ISA aliasing though. */ |
284 | static void __devinit | 281 | static void pbus_size_io(struct pci_bus *bus) |
285 | pbus_size_io(struct pci_bus *bus) | ||
286 | { | 282 | { |
287 | struct pci_dev *dev; | 283 | struct pci_dev *dev; |
288 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); | 284 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); |
@@ -326,8 +322,7 @@ pbus_size_io(struct pci_bus *bus) | |||
326 | 322 | ||
327 | /* Calculate the size of the bus and minimal alignment which | 323 | /* Calculate the size of the bus and minimal alignment which |
328 | guarantees that all child resources fit in this size. */ | 324 | guarantees that all child resources fit in this size. */ |
329 | static int __devinit | 325 | static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) |
330 | pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) | ||
331 | { | 326 | { |
332 | struct pci_dev *dev; | 327 | struct pci_dev *dev; |
333 | unsigned long min_align, align, size; | 328 | unsigned long min_align, align, size; |
@@ -447,8 +442,7 @@ pci_bus_size_cardbus(struct pci_bus *bus) | |||
447 | } | 442 | } |
448 | } | 443 | } |
449 | 444 | ||
450 | void __devinit | 445 | void pci_bus_size_bridges(struct pci_bus *bus) |
451 | pci_bus_size_bridges(struct pci_bus *bus) | ||
452 | { | 446 | { |
453 | struct pci_dev *dev; | 447 | struct pci_dev *dev; |
454 | unsigned long mask, prefmask; | 448 | unsigned long mask, prefmask; |
@@ -498,8 +492,7 @@ pci_bus_size_bridges(struct pci_bus *bus) | |||
498 | } | 492 | } |
499 | EXPORT_SYMBOL(pci_bus_size_bridges); | 493 | EXPORT_SYMBOL(pci_bus_size_bridges); |
500 | 494 | ||
501 | void __devinit | 495 | void pci_bus_assign_resources(struct pci_bus *bus) |
502 | pci_bus_assign_resources(struct pci_bus *bus) | ||
503 | { | 496 | { |
504 | struct pci_bus *b; | 497 | struct pci_bus *b; |
505 | struct pci_dev *dev; | 498 | struct pci_dev *dev; |
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index cb4ced3560e9..6dfd86167e39 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c | |||
@@ -101,8 +101,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) | |||
101 | new & ~PCI_REGION_FLAG_MASK); | 101 | new & ~PCI_REGION_FLAG_MASK); |
102 | } | 102 | } |
103 | 103 | ||
104 | int __devinit | 104 | int pci_claim_resource(struct pci_dev *dev, int resource) |
105 | pci_claim_resource(struct pci_dev *dev, int resource) | ||
106 | { | 105 | { |
107 | struct resource *res = &dev->resource[resource]; | 106 | struct resource *res = &dev->resource[resource]; |
108 | struct resource *root = NULL; | 107 | struct resource *root = NULL; |
@@ -212,8 +211,7 @@ EXPORT_SYMBOL_GPL(pci_assign_resource_fixed); | |||
212 | #endif | 211 | #endif |
213 | 212 | ||
214 | /* Sort resources by alignment */ | 213 | /* Sort resources by alignment */ |
215 | void __devinit | 214 | void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) |
216 | pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) | ||
217 | { | 215 | { |
218 | int i; | 216 | int i; |
219 | 217 | ||
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index ac004248324a..50cad3a59a6c 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/ioport.h> | 26 | #include <linux/ioport.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/pm.h> | 28 | #include <linux/pm.h> |
29 | #include <linux/pci.h> | ||
30 | #include <linux/device.h> | 29 | #include <linux/device.h> |
31 | #include <linux/kthread.h> | 30 | #include <linux/kthread.h> |
32 | #include <linux/freezer.h> | 31 | #include <linux/freezer.h> |
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index ea5765c3bdc0..a2bb46526b56 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/ioport.h> | 22 | #include <linux/ioport.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
25 | #include <linux/pci.h> | ||
26 | #include <linux/device.h> | 25 | #include <linux/device.h> |
27 | #include <linux/mutex.h> | 26 | #include <linux/mutex.h> |
28 | #include <asm/system.h> | 27 | #include <asm/system.h> |
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c index d21e04ccb021..1393e64335f9 100644 --- a/drivers/ps3/ps3av.c +++ b/drivers/ps3/ps3av.c | |||
@@ -38,7 +38,24 @@ | |||
38 | static int timeout = 5000; /* in msec ( 5 sec ) */ | 38 | static int timeout = 5000; /* in msec ( 5 sec ) */ |
39 | module_param(timeout, int, 0644); | 39 | module_param(timeout, int, 0644); |
40 | 40 | ||
41 | static struct ps3av ps3av; | 41 | static struct ps3av { |
42 | int available; | ||
43 | struct mutex mutex; | ||
44 | struct work_struct work; | ||
45 | struct completion done; | ||
46 | struct workqueue_struct *wq; | ||
47 | int open_count; | ||
48 | struct ps3_vuart_port_device *dev; | ||
49 | |||
50 | int region; | ||
51 | struct ps3av_pkt_av_get_hw_conf av_hw_conf; | ||
52 | u32 av_port[PS3AV_AV_PORT_MAX + PS3AV_OPT_PORT_MAX]; | ||
53 | u32 opt_port[PS3AV_OPT_PORT_MAX]; | ||
54 | u32 head[PS3AV_HEAD_MAX]; | ||
55 | u32 audio_port; | ||
56 | int ps3av_mode; | ||
57 | int ps3av_mode_old; | ||
58 | } ps3av; | ||
42 | 59 | ||
43 | static struct ps3_vuart_port_device ps3av_dev = { | 60 | static struct ps3_vuart_port_device ps3av_dev = { |
44 | .match_id = PS3_MATCH_ID_AV_SETTINGS | 61 | .match_id = PS3_MATCH_ID_AV_SETTINGS |
@@ -159,7 +176,7 @@ static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr) | |||
159 | else | 176 | else |
160 | printk(KERN_ERR | 177 | printk(KERN_ERR |
161 | "%s: failed event packet, cid:%08x size:%d\n", | 178 | "%s: failed event packet, cid:%08x size:%d\n", |
162 | __FUNCTION__, hdr->cid, hdr->size); | 179 | __func__, hdr->cid, hdr->size); |
163 | return 1; /* receive event packet */ | 180 | return 1; /* receive event packet */ |
164 | } | 181 | } |
165 | return 0; | 182 | return 0; |
@@ -181,7 +198,7 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, | |||
181 | if (res < 0) { | 198 | if (res < 0) { |
182 | dev_dbg(&ps3av_dev.core, | 199 | dev_dbg(&ps3av_dev.core, |
183 | "%s: ps3av_vuart_write() failed (result=%d)\n", | 200 | "%s: ps3av_vuart_write() failed (result=%d)\n", |
184 | __FUNCTION__, res); | 201 | __func__, res); |
185 | return res; | 202 | return res; |
186 | } | 203 | } |
187 | 204 | ||
@@ -194,7 +211,7 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, | |||
194 | if (res != PS3AV_HDR_SIZE) { | 211 | if (res != PS3AV_HDR_SIZE) { |
195 | dev_dbg(&ps3av_dev.core, | 212 | dev_dbg(&ps3av_dev.core, |
196 | "%s: ps3av_vuart_read() failed (result=%d)\n", | 213 | "%s: ps3av_vuart_read() failed (result=%d)\n", |
197 | __FUNCTION__, res); | 214 | __func__, res); |
198 | return res; | 215 | return res; |
199 | } | 216 | } |
200 | 217 | ||
@@ -204,7 +221,7 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, | |||
204 | if (res < 0) { | 221 | if (res < 0) { |
205 | dev_dbg(&ps3av_dev.core, | 222 | dev_dbg(&ps3av_dev.core, |
206 | "%s: ps3av_vuart_read() failed (result=%d)\n", | 223 | "%s: ps3av_vuart_read() failed (result=%d)\n", |
207 | __FUNCTION__, res); | 224 | __func__, res); |
208 | return res; | 225 | return res; |
209 | } | 226 | } |
210 | res += PS3AV_HDR_SIZE; /* total len */ | 227 | res += PS3AV_HDR_SIZE; /* total len */ |
@@ -214,7 +231,7 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, | |||
214 | 231 | ||
215 | if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) { | 232 | if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) { |
216 | dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n", | 233 | dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n", |
217 | __FUNCTION__, recv_buf->cid); | 234 | __func__, recv_buf->cid); |
218 | return -EINVAL; | 235 | return -EINVAL; |
219 | } | 236 | } |
220 | 237 | ||
@@ -250,7 +267,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, | |||
250 | struct ps3av_send_hdr *buf) | 267 | struct ps3av_send_hdr *buf) |
251 | { | 268 | { |
252 | int res = 0; | 269 | int res = 0; |
253 | union { | 270 | static union { |
254 | struct ps3av_reply_hdr reply_hdr; | 271 | struct ps3av_reply_hdr reply_hdr; |
255 | u8 raw[PS3AV_BUF_SIZE]; | 272 | u8 raw[PS3AV_BUF_SIZE]; |
256 | } recv_buf; | 273 | } recv_buf; |
@@ -259,8 +276,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, | |||
259 | 276 | ||
260 | BUG_ON(!ps3av.available); | 277 | BUG_ON(!ps3av.available); |
261 | 278 | ||
262 | if (down_interruptible(&ps3av.sem)) | 279 | mutex_lock(&ps3av.mutex); |
263 | return -ERESTARTSYS; | ||
264 | 280 | ||
265 | table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK); | 281 | table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK); |
266 | BUG_ON(!table); | 282 | BUG_ON(!table); |
@@ -277,7 +293,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, | |||
277 | if (res < 0) { | 293 | if (res < 0) { |
278 | printk(KERN_ERR | 294 | printk(KERN_ERR |
279 | "%s: ps3av_send_cmd_pkt() failed (result=%d)\n", | 295 | "%s: ps3av_send_cmd_pkt() failed (result=%d)\n", |
280 | __FUNCTION__, res); | 296 | __func__, res); |
281 | goto err; | 297 | goto err; |
282 | } | 298 | } |
283 | 299 | ||
@@ -286,16 +302,16 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, | |||
286 | usr_buf_size); | 302 | usr_buf_size); |
287 | if (res < 0) { | 303 | if (res < 0) { |
288 | printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n", | 304 | printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n", |
289 | __FUNCTION__, res); | 305 | __func__, res); |
290 | goto err; | 306 | goto err; |
291 | } | 307 | } |
292 | 308 | ||
293 | up(&ps3av.sem); | 309 | mutex_unlock(&ps3av.mutex); |
294 | return 0; | 310 | return 0; |
295 | 311 | ||
296 | err: | 312 | err: |
297 | up(&ps3av.sem); | 313 | mutex_unlock(&ps3av.mutex); |
298 | printk(KERN_ERR "%s: failed cid:%x res:%d\n", __FUNCTION__, cid, res); | 314 | printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res); |
299 | return res; | 315 | return res; |
300 | } | 316 | } |
301 | 317 | ||
@@ -440,7 +456,7 @@ static int ps3av_set_videomode(void) | |||
440 | ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON); | 456 | ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON); |
441 | 457 | ||
442 | /* wake up ps3avd to do the actual video mode setting */ | 458 | /* wake up ps3avd to do the actual video mode setting */ |
443 | up(&ps3av.ping); | 459 | queue_work(ps3av.wq, &ps3av.work); |
444 | 460 | ||
445 | return 0; | 461 | return 0; |
446 | } | 462 | } |
@@ -506,7 +522,7 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id) | |||
506 | if (res == PS3AV_STATUS_NO_SYNC_HEAD) | 522 | if (res == PS3AV_STATUS_NO_SYNC_HEAD) |
507 | printk(KERN_WARNING | 523 | printk(KERN_WARNING |
508 | "%s: Command failed. Please try your request again. \n", | 524 | "%s: Command failed. Please try your request again. \n", |
509 | __FUNCTION__); | 525 | __func__); |
510 | else if (res) | 526 | else if (res) |
511 | dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n"); | 527 | dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n"); |
512 | 528 | ||
@@ -515,18 +531,10 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id) | |||
515 | ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF); | 531 | ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF); |
516 | } | 532 | } |
517 | 533 | ||
518 | static int ps3avd(void *p) | 534 | static void ps3avd(struct work_struct *work) |
519 | { | 535 | { |
520 | struct ps3av *info = p; | 536 | ps3av_set_videomode_cont(ps3av.ps3av_mode, ps3av.ps3av_mode_old); |
521 | 537 | complete(&ps3av.done); | |
522 | daemonize("ps3avd"); | ||
523 | while (1) { | ||
524 | down(&info->ping); | ||
525 | ps3av_set_videomode_cont(info->ps3av_mode, | ||
526 | info->ps3av_mode_old); | ||
527 | up(&info->pong); | ||
528 | } | ||
529 | return 0; | ||
530 | } | 538 | } |
531 | 539 | ||
532 | static int ps3av_vid2table_id(int vid) | 540 | static int ps3av_vid2table_id(int vid) |
@@ -707,8 +715,7 @@ int ps3av_set_video_mode(u32 id, int boot) | |||
707 | 715 | ||
708 | size = ARRAY_SIZE(video_mode_table); | 716 | size = ARRAY_SIZE(video_mode_table); |
709 | if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) { | 717 | if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) { |
710 | dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __FUNCTION__, | 718 | dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __func__, id); |
711 | id); | ||
712 | return -EINVAL; | 719 | return -EINVAL; |
713 | } | 720 | } |
714 | 721 | ||
@@ -717,15 +724,14 @@ int ps3av_set_video_mode(u32 id, int boot) | |||
717 | if ((id & PS3AV_MODE_MASK) == 0) { | 724 | if ((id & PS3AV_MODE_MASK) == 0) { |
718 | id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot); | 725 | id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot); |
719 | if (id < 1) { | 726 | if (id < 1) { |
720 | printk(KERN_ERR "%s: invalid id :%d\n", __FUNCTION__, | 727 | printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); |
721 | id); | ||
722 | return -EINVAL; | 728 | return -EINVAL; |
723 | } | 729 | } |
724 | id |= option; | 730 | id |= option; |
725 | } | 731 | } |
726 | 732 | ||
727 | /* set videomode */ | 733 | /* set videomode */ |
728 | down(&ps3av.pong); | 734 | wait_for_completion(&ps3av.done); |
729 | ps3av.ps3av_mode_old = ps3av.ps3av_mode; | 735 | ps3av.ps3av_mode_old = ps3av.ps3av_mode; |
730 | ps3av.ps3av_mode = id; | 736 | ps3av.ps3av_mode = id; |
731 | if (ps3av_set_videomode()) | 737 | if (ps3av_set_videomode()) |
@@ -736,6 +742,13 @@ int ps3av_set_video_mode(u32 id, int boot) | |||
736 | 742 | ||
737 | EXPORT_SYMBOL_GPL(ps3av_set_video_mode); | 743 | EXPORT_SYMBOL_GPL(ps3av_set_video_mode); |
738 | 744 | ||
745 | int ps3av_get_auto_mode(int boot) | ||
746 | { | ||
747 | return ps3av_auto_videomode(&ps3av.av_hw_conf, boot); | ||
748 | } | ||
749 | |||
750 | EXPORT_SYMBOL_GPL(ps3av_get_auto_mode); | ||
751 | |||
739 | int ps3av_set_mode(u32 id, int boot) | 752 | int ps3av_set_mode(u32 id, int boot) |
740 | { | 753 | { |
741 | int res; | 754 | int res; |
@@ -771,7 +784,7 @@ int ps3av_get_scanmode(int id) | |||
771 | id = id & PS3AV_MODE_MASK; | 784 | id = id & PS3AV_MODE_MASK; |
772 | size = ARRAY_SIZE(video_mode_table); | 785 | size = ARRAY_SIZE(video_mode_table); |
773 | if (id > size - 1 || id < 0) { | 786 | if (id > size - 1 || id < 0) { |
774 | printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id); | 787 | printk(KERN_ERR "%s: invalid mode %d\n", __func__, id); |
775 | return -EINVAL; | 788 | return -EINVAL; |
776 | } | 789 | } |
777 | return video_mode_table[id].interlace; | 790 | return video_mode_table[id].interlace; |
@@ -786,7 +799,7 @@ int ps3av_get_refresh_rate(int id) | |||
786 | id = id & PS3AV_MODE_MASK; | 799 | id = id & PS3AV_MODE_MASK; |
787 | size = ARRAY_SIZE(video_mode_table); | 800 | size = ARRAY_SIZE(video_mode_table); |
788 | if (id > size - 1 || id < 0) { | 801 | if (id > size - 1 || id < 0) { |
789 | printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id); | 802 | printk(KERN_ERR "%s: invalid mode %d\n", __func__, id); |
790 | return -EINVAL; | 803 | return -EINVAL; |
791 | } | 804 | } |
792 | return video_mode_table[id].freq; | 805 | return video_mode_table[id].freq; |
@@ -802,7 +815,7 @@ int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres) | |||
802 | id = id & PS3AV_MODE_MASK; | 815 | id = id & PS3AV_MODE_MASK; |
803 | size = ARRAY_SIZE(video_mode_table); | 816 | size = ARRAY_SIZE(video_mode_table); |
804 | if (id > size - 1 || id < 0) { | 817 | if (id > size - 1 || id < 0) { |
805 | printk(KERN_ERR "%s: invalid mode %d\n", __FUNCTION__, id); | 818 | printk(KERN_ERR "%s: invalid mode %d\n", __func__, id); |
806 | return -EINVAL; | 819 | return -EINVAL; |
807 | } | 820 | } |
808 | *xres = video_mode_table[id].x; | 821 | *xres = video_mode_table[id].x; |
@@ -838,7 +851,7 @@ int ps3av_dev_open(void) | |||
838 | status = lv1_gpu_open(0); | 851 | status = lv1_gpu_open(0); |
839 | if (status) { | 852 | if (status) { |
840 | printk(KERN_ERR "%s: lv1_gpu_open failed %d\n", | 853 | printk(KERN_ERR "%s: lv1_gpu_open failed %d\n", |
841 | __FUNCTION__, status); | 854 | __func__, status); |
842 | ps3av.open_count--; | 855 | ps3av.open_count--; |
843 | } | 856 | } |
844 | } | 857 | } |
@@ -855,13 +868,13 @@ int ps3av_dev_close(void) | |||
855 | 868 | ||
856 | mutex_lock(&ps3av.mutex); | 869 | mutex_lock(&ps3av.mutex); |
857 | if (ps3av.open_count <= 0) { | 870 | if (ps3av.open_count <= 0) { |
858 | printk(KERN_ERR "%s: GPU already closed\n", __FUNCTION__); | 871 | printk(KERN_ERR "%s: GPU already closed\n", __func__); |
859 | status = -1; | 872 | status = -1; |
860 | } else if (!--ps3av.open_count) { | 873 | } else if (!--ps3av.open_count) { |
861 | status = lv1_gpu_close(); | 874 | status = lv1_gpu_close(); |
862 | if (status) | 875 | if (status) |
863 | printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n", | 876 | printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n", |
864 | __FUNCTION__, status); | 877 | __func__, status); |
865 | } | 878 | } |
866 | mutex_unlock(&ps3av.mutex); | 879 | mutex_unlock(&ps3av.mutex); |
867 | 880 | ||
@@ -880,13 +893,16 @@ static int ps3av_probe(struct ps3_vuart_port_device *dev) | |||
880 | 893 | ||
881 | memset(&ps3av, 0, sizeof(ps3av)); | 894 | memset(&ps3av, 0, sizeof(ps3av)); |
882 | 895 | ||
883 | init_MUTEX(&ps3av.sem); | ||
884 | init_MUTEX_LOCKED(&ps3av.ping); | ||
885 | init_MUTEX(&ps3av.pong); | ||
886 | mutex_init(&ps3av.mutex); | 896 | mutex_init(&ps3av.mutex); |
887 | ps3av.ps3av_mode = 0; | 897 | ps3av.ps3av_mode = 0; |
888 | ps3av.dev = dev; | 898 | ps3av.dev = dev; |
889 | kernel_thread(ps3avd, &ps3av, CLONE_KERNEL); | 899 | |
900 | INIT_WORK(&ps3av.work, ps3avd); | ||
901 | init_completion(&ps3av.done); | ||
902 | complete(&ps3av.done); | ||
903 | ps3av.wq = create_singlethread_workqueue("ps3avd"); | ||
904 | if (!ps3av.wq) | ||
905 | return -ENOMEM; | ||
890 | 906 | ||
891 | ps3av.available = 1; | 907 | ps3av.available = 1; |
892 | switch (ps3_os_area_get_av_multi_out()) { | 908 | switch (ps3_os_area_get_av_multi_out()) { |
@@ -908,7 +924,7 @@ static int ps3av_probe(struct ps3_vuart_port_device *dev) | |||
908 | /* init avsetting modules */ | 924 | /* init avsetting modules */ |
909 | res = ps3av_cmd_init(); | 925 | res = ps3av_cmd_init(); |
910 | if (res < 0) | 926 | if (res < 0) |
911 | printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __FUNCTION__, | 927 | printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__, |
912 | res); | 928 | res); |
913 | 929 | ||
914 | ps3av_get_hw_conf(&ps3av); | 930 | ps3av_get_hw_conf(&ps3av); |
@@ -926,6 +942,8 @@ static int ps3av_remove(struct ps3_vuart_port_device *dev) | |||
926 | { | 942 | { |
927 | if (ps3av.available) { | 943 | if (ps3av.available) { |
928 | ps3av_cmd_fin(); | 944 | ps3av_cmd_fin(); |
945 | if (ps3av.wq) | ||
946 | destroy_workqueue(ps3av.wq); | ||
929 | ps3av.available = 0; | 947 | ps3av.available = 0; |
930 | } | 948 | } |
931 | 949 | ||
@@ -958,7 +976,7 @@ static int ps3av_module_init(void) | |||
958 | if (error) { | 976 | if (error) { |
959 | printk(KERN_ERR | 977 | printk(KERN_ERR |
960 | "%s: ps3_vuart_port_driver_register failed %d\n", | 978 | "%s: ps3_vuart_port_driver_register failed %d\n", |
961 | __FUNCTION__, error); | 979 | __func__, error); |
962 | return error; | 980 | return error; |
963 | } | 981 | } |
964 | 982 | ||
@@ -966,7 +984,7 @@ static int ps3av_module_init(void) | |||
966 | if (error) | 984 | if (error) |
967 | printk(KERN_ERR | 985 | printk(KERN_ERR |
968 | "%s: ps3_vuart_port_device_register failed %d\n", | 986 | "%s: ps3_vuart_port_device_register failed %d\n", |
969 | __FUNCTION__, error); | 987 | __func__, error); |
970 | 988 | ||
971 | return error; | 989 | return error; |
972 | } | 990 | } |
diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c index bc70e81f8cb0..0145ea173c42 100644 --- a/drivers/ps3/ps3av_cmd.c +++ b/drivers/ps3/ps3av_cmd.c | |||
@@ -395,7 +395,7 @@ u32 ps3av_cmd_set_video_mode(void *p, u32 head, int video_vid, int video_fmt, | |||
395 | video_mode->video_order = ps3av_video_fmt_table[video_fmt].order; | 395 | video_mode->video_order = ps3av_video_fmt_table[video_fmt].order; |
396 | 396 | ||
397 | pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n", | 397 | pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n", |
398 | __FUNCTION__, video_vid, video_mode->width, video_mode->height, | 398 | __func__, video_vid, video_mode->width, video_mode->height, |
399 | video_mode->pitch, video_mode->video_out_format, | 399 | video_mode->pitch, video_mode->video_out_format, |
400 | video_mode->video_format, video_mode->video_order); | 400 | video_mode->video_format, video_mode->video_order); |
401 | return sizeof(*video_mode); | 401 | return sizeof(*video_mode); |
@@ -477,7 +477,7 @@ static u8 ps3av_cnv_mclk(u32 fs) | |||
477 | if (ps3av_cnv_mclk_table[i].fs == fs) | 477 | if (ps3av_cnv_mclk_table[i].fs == fs) |
478 | return ps3av_cnv_mclk_table[i].mclk; | 478 | return ps3av_cnv_mclk_table[i].mclk; |
479 | 479 | ||
480 | printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs); | 480 | printk(KERN_ERR "%s failed, fs:%x\n", __func__, fs); |
481 | return 0; | 481 | return 0; |
482 | } | 482 | } |
483 | 483 | ||
@@ -526,13 +526,12 @@ static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid) | |||
526 | d = 4; | 526 | d = 4; |
527 | break; | 527 | break; |
528 | default: | 528 | default: |
529 | printk(KERN_ERR "%s failed, vid:%x\n", __FUNCTION__, | 529 | printk(KERN_ERR "%s failed, vid:%x\n", __func__, video_vid); |
530 | video_vid); | ||
531 | break; | 530 | break; |
532 | } | 531 | } |
533 | 532 | ||
534 | if (fs < PS3AV_CMD_AUDIO_FS_44K || fs > PS3AV_CMD_AUDIO_FS_192K) | 533 | if (fs < PS3AV_CMD_AUDIO_FS_44K || fs > PS3AV_CMD_AUDIO_FS_192K) |
535 | printk(KERN_ERR "%s failed, fs:%x\n", __FUNCTION__, fs); | 534 | printk(KERN_ERR "%s failed, fs:%x\n", __func__, fs); |
536 | else | 535 | else |
537 | ns_val = ps3av_ns_table[PS3AV_CMD_AUDIO_FS_44K-BASE][d]; | 536 | ns_val = ps3av_ns_table[PS3AV_CMD_AUDIO_FS_44K-BASE][d]; |
538 | 537 | ||
@@ -555,8 +554,7 @@ static u8 ps3av_cnv_enable(u32 source, const u8 *enable) | |||
555 | ret = ((p[0] << 4) + (p[1] << 5) + (p[2] << 6) + (p[3] << 7)) | | 554 | ret = ((p[0] << 4) + (p[1] << 5) + (p[2] << 6) + (p[3] << 7)) | |
556 | 0x01; | 555 | 0x01; |
557 | } else | 556 | } else |
558 | printk(KERN_ERR "%s failed, source:%x\n", __FUNCTION__, | 557 | printk(KERN_ERR "%s failed, source:%x\n", __func__, source); |
559 | source); | ||
560 | return ret; | 558 | return ret; |
561 | } | 559 | } |
562 | 560 | ||
@@ -585,7 +583,7 @@ static u8 ps3av_cnv_inputlen(u32 word_bits) | |||
585 | ret = PS3AV_CMD_AV_INPUTLEN_24; | 583 | ret = PS3AV_CMD_AV_INPUTLEN_24; |
586 | break; | 584 | break; |
587 | default: | 585 | default: |
588 | printk(KERN_ERR "%s failed, word_bits:%x\n", __FUNCTION__, | 586 | printk(KERN_ERR "%s failed, word_bits:%x\n", __func__, |
589 | word_bits); | 587 | word_bits); |
590 | break; | 588 | break; |
591 | } | 589 | } |
@@ -595,7 +593,7 @@ static u8 ps3av_cnv_inputlen(u32 word_bits) | |||
595 | static u8 ps3av_cnv_layout(u32 num_of_ch) | 593 | static u8 ps3av_cnv_layout(u32 num_of_ch) |
596 | { | 594 | { |
597 | if (num_of_ch > PS3AV_CMD_AUDIO_NUM_OF_CH_8) { | 595 | if (num_of_ch > PS3AV_CMD_AUDIO_NUM_OF_CH_8) { |
598 | printk(KERN_ERR "%s failed, num_of_ch:%x\n", __FUNCTION__, | 596 | printk(KERN_ERR "%s failed, num_of_ch:%x\n", __func__, |
599 | num_of_ch); | 597 | num_of_ch); |
600 | return 0; | 598 | return 0; |
601 | } | 599 | } |
@@ -864,7 +862,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len) | |||
864 | 862 | ||
865 | res = get_status(avb); | 863 | res = get_status(avb); |
866 | if (res) | 864 | if (res) |
867 | pr_debug("%s: PS3AV_CID_AVB_PARAM: failed %x\n", __FUNCTION__, | 865 | pr_debug("%s: PS3AV_CID_AVB_PARAM: failed %x\n", __func__, |
868 | res); | 866 | res); |
869 | 867 | ||
870 | out: | 868 | out: |
@@ -1013,7 +1011,7 @@ int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf, | |||
1013 | return size; | 1011 | return size; |
1014 | if (error != -EAGAIN) { | 1012 | if (error != -EAGAIN) { |
1015 | printk(KERN_ERR "%s: ps3_vuart_read failed %d\n", | 1013 | printk(KERN_ERR "%s: ps3_vuart_read failed %d\n", |
1016 | __FUNCTION__, error); | 1014 | __func__, error); |
1017 | return error; | 1015 | return error; |
1018 | } | 1016 | } |
1019 | msleep(POLLING_INTERVAL); | 1017 | msleep(POLLING_INTERVAL); |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index e71929db8b06..977521013fe8 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -2174,6 +2174,51 @@ dasd_generic_notify(struct ccw_device *cdev, int event) | |||
2174 | return ret; | 2174 | return ret; |
2175 | } | 2175 | } |
2176 | 2176 | ||
2177 | struct dasd_ccw_req * dasd_generic_build_rdc(struct dasd_device *device, | ||
2178 | void *rdc_buffer, | ||
2179 | int rdc_buffer_size, char *magic) | ||
2180 | { | ||
2181 | struct dasd_ccw_req *cqr; | ||
2182 | struct ccw1 *ccw; | ||
2183 | |||
2184 | cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device); | ||
2185 | |||
2186 | if (IS_ERR(cqr)) { | ||
2187 | DEV_MESSAGE(KERN_WARNING, device, "%s", | ||
2188 | "Could not allocate RDC request"); | ||
2189 | return cqr; | ||
2190 | } | ||
2191 | |||
2192 | ccw = cqr->cpaddr; | ||
2193 | ccw->cmd_code = CCW_CMD_RDC; | ||
2194 | ccw->cda = (__u32)(addr_t)rdc_buffer; | ||
2195 | ccw->count = rdc_buffer_size; | ||
2196 | |||
2197 | cqr->device = device; | ||
2198 | cqr->expires = 10*HZ; | ||
2199 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | ||
2200 | cqr->retries = 2; | ||
2201 | cqr->buildclk = get_clock(); | ||
2202 | cqr->status = DASD_CQR_FILLED; | ||
2203 | return cqr; | ||
2204 | } | ||
2205 | |||
2206 | |||
2207 | int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic, | ||
2208 | void **rdc_buffer, int rdc_buffer_size) | ||
2209 | { | ||
2210 | int ret; | ||
2211 | struct dasd_ccw_req *cqr; | ||
2212 | |||
2213 | cqr = dasd_generic_build_rdc(device, *rdc_buffer, rdc_buffer_size, | ||
2214 | magic); | ||
2215 | if (IS_ERR(cqr)) | ||
2216 | return PTR_ERR(cqr); | ||
2217 | |||
2218 | ret = dasd_sleep_on(cqr); | ||
2219 | dasd_sfree_request(cqr, cqr->device); | ||
2220 | return ret; | ||
2221 | } | ||
2177 | 2222 | ||
2178 | static int __init | 2223 | static int __init |
2179 | dasd_init(void) | 2224 | dasd_init(void) |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index cecab2274a6e..c9583fbc2a7d 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -450,6 +450,81 @@ dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid) | |||
450 | return 0; | 450 | return 0; |
451 | } | 451 | } |
452 | 452 | ||
453 | struct dasd_ccw_req * dasd_eckd_build_rcd_lpm(struct dasd_device *device, | ||
454 | void *rcd_buffer, | ||
455 | struct ciw *ciw, __u8 lpm) | ||
456 | { | ||
457 | struct dasd_ccw_req *cqr; | ||
458 | struct ccw1 *ccw; | ||
459 | |||
460 | cqr = dasd_smalloc_request("ECKD", 1 /* RCD */, ciw->count, device); | ||
461 | |||
462 | if (IS_ERR(cqr)) { | ||
463 | DEV_MESSAGE(KERN_WARNING, device, "%s", | ||
464 | "Could not allocate RCD request"); | ||
465 | return cqr; | ||
466 | } | ||
467 | |||
468 | ccw = cqr->cpaddr; | ||
469 | ccw->cmd_code = ciw->cmd; | ||
470 | ccw->cda = (__u32)(addr_t)rcd_buffer; | ||
471 | ccw->count = ciw->count; | ||
472 | |||
473 | cqr->device = device; | ||
474 | cqr->expires = 10*HZ; | ||
475 | cqr->lpm = lpm; | ||
476 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | ||
477 | cqr->retries = 2; | ||
478 | cqr->buildclk = get_clock(); | ||
479 | cqr->status = DASD_CQR_FILLED; | ||
480 | return cqr; | ||
481 | } | ||
482 | |||
483 | static int dasd_eckd_read_conf_lpm(struct dasd_device *device, | ||
484 | void **rcd_buffer, | ||
485 | int *rcd_buffer_size, __u8 lpm) | ||
486 | { | ||
487 | struct ciw *ciw; | ||
488 | char *rcd_buf = NULL; | ||
489 | int ret; | ||
490 | struct dasd_ccw_req *cqr; | ||
491 | |||
492 | /* | ||
493 | * scan for RCD command in extended SenseID data | ||
494 | */ | ||
495 | ciw = ccw_device_get_ciw(device->cdev, CIW_TYPE_RCD); | ||
496 | if (!ciw || ciw->cmd == 0) { | ||
497 | ret = -EOPNOTSUPP; | ||
498 | goto out_error; | ||
499 | } | ||
500 | rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA); | ||
501 | if (!rcd_buf) { | ||
502 | ret = -ENOMEM; | ||
503 | goto out_error; | ||
504 | } | ||
505 | cqr = dasd_eckd_build_rcd_lpm(device, rcd_buf, ciw, lpm); | ||
506 | if (IS_ERR(cqr)) { | ||
507 | ret = PTR_ERR(cqr); | ||
508 | goto out_error; | ||
509 | } | ||
510 | ret = dasd_sleep_on(cqr); | ||
511 | /* | ||
512 | * on success we update the user input parms | ||
513 | */ | ||
514 | dasd_sfree_request(cqr, cqr->device); | ||
515 | if (ret) | ||
516 | goto out_error; | ||
517 | |||
518 | *rcd_buffer_size = ciw->count; | ||
519 | *rcd_buffer = rcd_buf; | ||
520 | return 0; | ||
521 | out_error: | ||
522 | kfree(rcd_buf); | ||
523 | *rcd_buffer = NULL; | ||
524 | *rcd_buffer_size = 0; | ||
525 | return ret; | ||
526 | } | ||
527 | |||
453 | static int | 528 | static int |
454 | dasd_eckd_read_conf(struct dasd_device *device) | 529 | dasd_eckd_read_conf(struct dasd_device *device) |
455 | { | 530 | { |
@@ -469,8 +544,8 @@ dasd_eckd_read_conf(struct dasd_device *device) | |||
469 | /* get configuration data per operational path */ | 544 | /* get configuration data per operational path */ |
470 | for (lpm = 0x80; lpm; lpm>>= 1) { | 545 | for (lpm = 0x80; lpm; lpm>>= 1) { |
471 | if (lpm & path_data->opm){ | 546 | if (lpm & path_data->opm){ |
472 | rc = read_conf_data_lpm(device->cdev, &conf_data, | 547 | rc = dasd_eckd_read_conf_lpm(device, &conf_data, |
473 | &conf_len, lpm); | 548 | &conf_len, lpm); |
474 | if (rc && rc != -EOPNOTSUPP) { /* -EOPNOTSUPP is ok */ | 549 | if (rc && rc != -EOPNOTSUPP) { /* -EOPNOTSUPP is ok */ |
475 | MESSAGE(KERN_WARNING, | 550 | MESSAGE(KERN_WARNING, |
476 | "Read configuration data returned " | 551 | "Read configuration data returned " |
@@ -639,7 +714,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
639 | /* Read Device Characteristics */ | 714 | /* Read Device Characteristics */ |
640 | rdc_data = (void *) &(private->rdc_data); | 715 | rdc_data = (void *) &(private->rdc_data); |
641 | memset(rdc_data, 0, sizeof(rdc_data)); | 716 | memset(rdc_data, 0, sizeof(rdc_data)); |
642 | rc = read_dev_chars(device->cdev, &rdc_data, 64); | 717 | rc = dasd_generic_read_dev_chars(device, "ECKD", &rdc_data, 64); |
643 | if (rc) | 718 | if (rc) |
644 | DEV_MESSAGE(KERN_WARNING, device, | 719 | DEV_MESSAGE(KERN_WARNING, device, |
645 | "Read device characteristics returned " | 720 | "Read device characteristics returned " |
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index be0909e39226..da16ead8aff2 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c | |||
@@ -135,7 +135,7 @@ dasd_fba_check_characteristics(struct dasd_device *device) | |||
135 | } | 135 | } |
136 | /* Read Device Characteristics */ | 136 | /* Read Device Characteristics */ |
137 | rdc_data = (void *) &(private->rdc_data); | 137 | rdc_data = (void *) &(private->rdc_data); |
138 | rc = read_dev_chars(device->cdev, &rdc_data, 32); | 138 | rc = dasd_generic_read_dev_chars(device, "FBA ", &rdc_data, 32); |
139 | if (rc) { | 139 | if (rc) { |
140 | DEV_MESSAGE(KERN_WARNING, device, | 140 | DEV_MESSAGE(KERN_WARNING, device, |
141 | "Read device characteristics returned error %d", | 141 | "Read device characteristics returned error %d", |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index a2cc69e11410..241294cba415 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -509,6 +509,8 @@ int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *); | |||
509 | int dasd_generic_set_offline (struct ccw_device *cdev); | 509 | int dasd_generic_set_offline (struct ccw_device *cdev); |
510 | int dasd_generic_notify(struct ccw_device *, int); | 510 | int dasd_generic_notify(struct ccw_device *, int); |
511 | 511 | ||
512 | int dasd_generic_read_dev_chars(struct dasd_device *, char *, void **, int); | ||
513 | |||
512 | /* externals in dasd_devmap.c */ | 514 | /* externals in dasd_devmap.c */ |
513 | extern int dasd_max_devindex; | 515 | extern int dasd_max_devindex; |
514 | extern int dasd_probeonly; | 516 | extern int dasd_probeonly; |
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h index bb4ff537729d..3b52f5c1dbef 100644 --- a/drivers/s390/char/tape.h +++ b/drivers/s390/char/tape.h | |||
@@ -103,6 +103,7 @@ enum tape_op { | |||
103 | TO_CRYPT_OFF, /* Disable encrpytion */ | 103 | TO_CRYPT_OFF, /* Disable encrpytion */ |
104 | TO_KEKL_SET, /* Set KEK label */ | 104 | TO_KEKL_SET, /* Set KEK label */ |
105 | TO_KEKL_QUERY, /* Query KEK label */ | 105 | TO_KEKL_QUERY, /* Query KEK label */ |
106 | TO_RDC, /* Read device characteristics */ | ||
106 | TO_SIZE, /* #entries in tape_op_t */ | 107 | TO_SIZE, /* #entries in tape_op_t */ |
107 | }; | 108 | }; |
108 | 109 | ||
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 50f5edab83d7..7e2b2ab49264 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c | |||
@@ -788,6 +788,7 @@ tape_3590_done(struct tape_device *device, struct tape_request *request) | |||
788 | case TO_SIZE: | 788 | case TO_SIZE: |
789 | case TO_KEKL_SET: | 789 | case TO_KEKL_SET: |
790 | case TO_KEKL_QUERY: | 790 | case TO_KEKL_QUERY: |
791 | case TO_RDC: | ||
791 | break; | 792 | break; |
792 | } | 793 | } |
793 | return TAPE_IO_SUCCESS; | 794 | return TAPE_IO_SUCCESS; |
@@ -1549,6 +1550,26 @@ tape_3590_irq(struct tape_device *device, struct tape_request *request, | |||
1549 | return TAPE_IO_STOP; | 1550 | return TAPE_IO_STOP; |
1550 | } | 1551 | } |
1551 | 1552 | ||
1553 | |||
1554 | static int tape_3590_read_dev_chars(struct tape_device *device, | ||
1555 | struct tape_3590_rdc_data *rdc_data) | ||
1556 | { | ||
1557 | int rc; | ||
1558 | struct tape_request *request; | ||
1559 | |||
1560 | request = tape_alloc_request(1, sizeof(*rdc_data)); | ||
1561 | if (IS_ERR(request)) | ||
1562 | return PTR_ERR(request); | ||
1563 | request->op = TO_RDC; | ||
1564 | tape_ccw_end(request->cpaddr, CCW_CMD_RDC, sizeof(*rdc_data), | ||
1565 | request->cpdata); | ||
1566 | rc = tape_do_io(device, request); | ||
1567 | if (rc == 0) | ||
1568 | memcpy(rdc_data, request->cpdata, sizeof(*rdc_data)); | ||
1569 | tape_free_request(request); | ||
1570 | return rc; | ||
1571 | } | ||
1572 | |||
1552 | /* | 1573 | /* |
1553 | * Setup device function | 1574 | * Setup device function |
1554 | */ | 1575 | */ |
@@ -1557,7 +1578,7 @@ tape_3590_setup_device(struct tape_device *device) | |||
1557 | { | 1578 | { |
1558 | int rc; | 1579 | int rc; |
1559 | struct tape_3590_disc_data *data; | 1580 | struct tape_3590_disc_data *data; |
1560 | char *rdc_data; | 1581 | struct tape_3590_rdc_data *rdc_data; |
1561 | 1582 | ||
1562 | DBF_EVENT(6, "3590 device setup\n"); | 1583 | DBF_EVENT(6, "3590 device setup\n"); |
1563 | data = kzalloc(sizeof(struct tape_3590_disc_data), GFP_KERNEL | GFP_DMA); | 1584 | data = kzalloc(sizeof(struct tape_3590_disc_data), GFP_KERNEL | GFP_DMA); |
@@ -1566,12 +1587,12 @@ tape_3590_setup_device(struct tape_device *device) | |||
1566 | data->read_back_op = READ_PREVIOUS; | 1587 | data->read_back_op = READ_PREVIOUS; |
1567 | device->discdata = data; | 1588 | device->discdata = data; |
1568 | 1589 | ||
1569 | rdc_data = kmalloc(64, GFP_KERNEL | GFP_DMA); | 1590 | rdc_data = kmalloc(sizeof(*rdc_data), GFP_KERNEL | GFP_DMA); |
1570 | if (!rdc_data) { | 1591 | if (!rdc_data) { |
1571 | rc = -ENOMEM; | 1592 | rc = -ENOMEM; |
1572 | goto fail_kmalloc; | 1593 | goto fail_kmalloc; |
1573 | } | 1594 | } |
1574 | rc = read_dev_chars(device->cdev, (void**)&rdc_data, 64); | 1595 | rc = tape_3590_read_dev_chars(device, rdc_data); |
1575 | if (rc) { | 1596 | if (rc) { |
1576 | DBF_LH(3, "Read device characteristics failed!\n"); | 1597 | DBF_LH(3, "Read device characteristics failed!\n"); |
1577 | goto fail_kmalloc; | 1598 | goto fail_kmalloc; |
@@ -1579,7 +1600,7 @@ tape_3590_setup_device(struct tape_device *device) | |||
1579 | rc = tape_std_assign(device); | 1600 | rc = tape_std_assign(device); |
1580 | if (rc) | 1601 | if (rc) |
1581 | goto fail_rdc_data; | 1602 | goto fail_rdc_data; |
1582 | if (rdc_data[31] == 0x13) { | 1603 | if (rdc_data->data[31] == 0x13) { |
1583 | PRINT_INFO("Device has crypto support\n"); | 1604 | PRINT_INFO("Device has crypto support\n"); |
1584 | data->crypt_info.capability |= TAPE390_CRYPT_SUPPORTED_MASK; | 1605 | data->crypt_info.capability |= TAPE390_CRYPT_SUPPORTED_MASK; |
1585 | tape_3592_disable_crypt(device); | 1606 | tape_3592_disable_crypt(device); |
diff --git a/drivers/s390/char/tape_3590.h b/drivers/s390/char/tape_3590.h index aa5138807af1..4534055f1376 100644 --- a/drivers/s390/char/tape_3590.h +++ b/drivers/s390/char/tape_3590.h | |||
@@ -129,6 +129,10 @@ struct tape_3590_med_sense { | |||
129 | char pad2[116]; | 129 | char pad2[116]; |
130 | } __attribute__ ((packed)); | 130 | } __attribute__ ((packed)); |
131 | 131 | ||
132 | struct tape_3590_rdc_data { | ||
133 | char data[64]; | ||
134 | } __attribute__ ((packed)); | ||
135 | |||
132 | /* Datastructures for 3592 encryption support */ | 136 | /* Datastructures for 3592 encryption support */ |
133 | 137 | ||
134 | struct tape3592_kekl { | 138 | struct tape3592_kekl { |
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index e2a8a1a04bab..2fae6338ee1c 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c | |||
@@ -73,7 +73,7 @@ const char *tape_op_verbose[TO_SIZE] = | |||
73 | [TO_DIS] = "DIS", [TO_ASSIGN] = "ASS", | 73 | [TO_DIS] = "DIS", [TO_ASSIGN] = "ASS", |
74 | [TO_UNASSIGN] = "UAS", [TO_CRYPT_ON] = "CON", | 74 | [TO_UNASSIGN] = "UAS", [TO_CRYPT_ON] = "CON", |
75 | [TO_CRYPT_OFF] = "COF", [TO_KEKL_SET] = "KLS", | 75 | [TO_CRYPT_OFF] = "COF", [TO_KEKL_SET] = "KLS", |
76 | [TO_KEKL_QUERY] = "KLQ", | 76 | [TO_KEKL_QUERY] = "KLQ",[TO_RDC] = "RDC", |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static int | 79 | static int |
@@ -911,6 +911,7 @@ __tape_start_request(struct tape_device *device, struct tape_request *request) | |||
911 | case TO_ASSIGN: | 911 | case TO_ASSIGN: |
912 | case TO_UNASSIGN: | 912 | case TO_UNASSIGN: |
913 | case TO_READ_ATTMSG: | 913 | case TO_READ_ATTMSG: |
914 | case TO_RDC: | ||
914 | if (device->tape_state == TS_INIT) | 915 | if (device->tape_state == TS_INIT) |
915 | break; | 916 | break; |
916 | if (device->tape_state == TS_UNUSED) | 917 | if (device->tape_state == TS_UNUSED) |
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 05fac0733f3d..cba64e4cfcd4 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c | |||
@@ -69,7 +69,6 @@ static const char version[] = "QDIO base support version 2"; | |||
69 | 69 | ||
70 | static int qdio_performance_stats = 0; | 70 | static int qdio_performance_stats = 0; |
71 | static int proc_perf_file_registration; | 71 | static int proc_perf_file_registration; |
72 | static unsigned long i_p_c, i_p_nc, o_p_c, o_p_nc, ii_p_c, ii_p_nc; | ||
73 | static struct qdio_perf_stats perf_stats; | 72 | static struct qdio_perf_stats perf_stats; |
74 | 73 | ||
75 | static int hydra_thinints; | 74 | static int hydra_thinints; |
@@ -111,6 +110,31 @@ qdio_min(int a,int b) | |||
111 | } | 110 | } |
112 | 111 | ||
113 | /***************** SCRUBBER HELPER ROUTINES **********************/ | 112 | /***************** SCRUBBER HELPER ROUTINES **********************/ |
113 | #ifdef CONFIG_64BIT | ||
114 | static inline void qdio_perf_stat_inc(atomic64_t *count) | ||
115 | { | ||
116 | if (qdio_performance_stats) | ||
117 | atomic64_inc(count); | ||
118 | } | ||
119 | |||
120 | static inline void qdio_perf_stat_dec(atomic64_t *count) | ||
121 | { | ||
122 | if (qdio_performance_stats) | ||
123 | atomic64_dec(count); | ||
124 | } | ||
125 | #else /* CONFIG_64BIT */ | ||
126 | static inline void qdio_perf_stat_inc(atomic_t *count) | ||
127 | { | ||
128 | if (qdio_performance_stats) | ||
129 | atomic_inc(count); | ||
130 | } | ||
131 | |||
132 | static inline void qdio_perf_stat_dec(atomic_t *count) | ||
133 | { | ||
134 | if (qdio_performance_stats) | ||
135 | atomic_dec(count); | ||
136 | } | ||
137 | #endif /* CONFIG_64BIT */ | ||
114 | 138 | ||
115 | static inline __u64 | 139 | static inline __u64 |
116 | qdio_get_micros(void) | 140 | qdio_get_micros(void) |
@@ -277,8 +301,7 @@ qdio_siga_sync(struct qdio_q *q, unsigned int gpr2, | |||
277 | QDIO_DBF_TEXT4(0,trace,"sigasync"); | 301 | QDIO_DBF_TEXT4(0,trace,"sigasync"); |
278 | QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); | 302 | QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); |
279 | 303 | ||
280 | if (qdio_performance_stats) | 304 | qdio_perf_stat_inc(&perf_stats.siga_syncs); |
281 | perf_stats.siga_syncs++; | ||
282 | 305 | ||
283 | cc = do_siga_sync(q->schid, gpr2, gpr3); | 306 | cc = do_siga_sync(q->schid, gpr2, gpr3); |
284 | if (cc) | 307 | if (cc) |
@@ -323,8 +346,7 @@ qdio_siga_output(struct qdio_q *q) | |||
323 | __u32 busy_bit; | 346 | __u32 busy_bit; |
324 | __u64 start_time=0; | 347 | __u64 start_time=0; |
325 | 348 | ||
326 | if (qdio_performance_stats) | 349 | qdio_perf_stat_inc(&perf_stats.siga_outs); |
327 | perf_stats.siga_outs++; | ||
328 | 350 | ||
329 | QDIO_DBF_TEXT4(0,trace,"sigaout"); | 351 | QDIO_DBF_TEXT4(0,trace,"sigaout"); |
330 | QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); | 352 | QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); |
@@ -358,8 +380,7 @@ qdio_siga_input(struct qdio_q *q) | |||
358 | QDIO_DBF_TEXT4(0,trace,"sigain"); | 380 | QDIO_DBF_TEXT4(0,trace,"sigain"); |
359 | QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); | 381 | QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); |
360 | 382 | ||
361 | if (qdio_performance_stats) | 383 | qdio_perf_stat_inc(&perf_stats.siga_ins); |
362 | perf_stats.siga_ins++; | ||
363 | 384 | ||
364 | cc = do_siga_input(q->schid, q->mask); | 385 | cc = do_siga_input(q->schid, q->mask); |
365 | 386 | ||
@@ -953,8 +974,7 @@ __qdio_outbound_processing(struct qdio_q *q) | |||
953 | 974 | ||
954 | if (unlikely(qdio_reserve_q(q))) { | 975 | if (unlikely(qdio_reserve_q(q))) { |
955 | qdio_release_q(q); | 976 | qdio_release_q(q); |
956 | if (qdio_performance_stats) | 977 | qdio_perf_stat_inc(&perf_stats.outbound_tl_runs_resched); |
957 | o_p_c++; | ||
958 | /* as we're sissies, we'll check next time */ | 978 | /* as we're sissies, we'll check next time */ |
959 | if (likely(!atomic_read(&q->is_in_shutdown))) { | 979 | if (likely(!atomic_read(&q->is_in_shutdown))) { |
960 | qdio_mark_q(q); | 980 | qdio_mark_q(q); |
@@ -962,10 +982,8 @@ __qdio_outbound_processing(struct qdio_q *q) | |||
962 | } | 982 | } |
963 | return; | 983 | return; |
964 | } | 984 | } |
965 | if (qdio_performance_stats) { | 985 | qdio_perf_stat_inc(&perf_stats.outbound_tl_runs); |
966 | o_p_nc++; | 986 | qdio_perf_stat_inc(&perf_stats.tl_runs); |
967 | perf_stats.tl_runs++; | ||
968 | } | ||
969 | 987 | ||
970 | /* see comment in qdio_kick_outbound_q */ | 988 | /* see comment in qdio_kick_outbound_q */ |
971 | siga_attempts=atomic_read(&q->busy_siga_counter); | 989 | siga_attempts=atomic_read(&q->busy_siga_counter); |
@@ -1139,17 +1157,6 @@ qdio_has_inbound_q_moved(struct qdio_q *q) | |||
1139 | { | 1157 | { |
1140 | int i; | 1158 | int i; |
1141 | 1159 | ||
1142 | static int old_pcis=0; | ||
1143 | static int old_thinints=0; | ||
1144 | |||
1145 | if (qdio_performance_stats) { | ||
1146 | if ((old_pcis==perf_stats.pcis)&& | ||
1147 | (old_thinints==perf_stats.thinints)) | ||
1148 | perf_stats.start_time_inbound=NOW; | ||
1149 | else | ||
1150 | old_pcis=perf_stats.pcis; | ||
1151 | } | ||
1152 | |||
1153 | i=qdio_get_inbound_buffer_frontier(q); | 1160 | i=qdio_get_inbound_buffer_frontier(q); |
1154 | if ( (i!=GET_SAVED_FRONTIER(q)) || | 1161 | if ( (i!=GET_SAVED_FRONTIER(q)) || |
1155 | (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) { | 1162 | (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) { |
@@ -1337,10 +1344,7 @@ qdio_kick_inbound_handler(struct qdio_q *q) | |||
1337 | q->siga_error=0; | 1344 | q->siga_error=0; |
1338 | q->error_status_flags=0; | 1345 | q->error_status_flags=0; |
1339 | 1346 | ||
1340 | if (qdio_performance_stats) { | 1347 | qdio_perf_stat_inc(&perf_stats.inbound_cnt); |
1341 | perf_stats.inbound_time+=NOW-perf_stats.start_time_inbound; | ||
1342 | perf_stats.inbound_cnt++; | ||
1343 | } | ||
1344 | } | 1348 | } |
1345 | 1349 | ||
1346 | static void | 1350 | static void |
@@ -1360,8 +1364,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set) | |||
1360 | */ | 1364 | */ |
1361 | if (unlikely(qdio_reserve_q(q))) { | 1365 | if (unlikely(qdio_reserve_q(q))) { |
1362 | qdio_release_q(q); | 1366 | qdio_release_q(q); |
1363 | if (qdio_performance_stats) | 1367 | qdio_perf_stat_inc(&perf_stats.inbound_thin_tl_runs_resched); |
1364 | ii_p_c++; | ||
1365 | /* | 1368 | /* |
1366 | * as we might just be about to stop polling, we make | 1369 | * as we might just be about to stop polling, we make |
1367 | * sure that we check again at least once more | 1370 | * sure that we check again at least once more |
@@ -1369,8 +1372,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set) | |||
1369 | tiqdio_sched_tl(); | 1372 | tiqdio_sched_tl(); |
1370 | return; | 1373 | return; |
1371 | } | 1374 | } |
1372 | if (qdio_performance_stats) | 1375 | qdio_perf_stat_inc(&perf_stats.inbound_thin_tl_runs); |
1373 | ii_p_nc++; | ||
1374 | if (unlikely(atomic_read(&q->is_in_shutdown))) { | 1376 | if (unlikely(atomic_read(&q->is_in_shutdown))) { |
1375 | qdio_unmark_q(q); | 1377 | qdio_unmark_q(q); |
1376 | goto out; | 1378 | goto out; |
@@ -1412,8 +1414,7 @@ __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set) | |||
1412 | for (i=0;i<irq_ptr->no_output_qs;i++) { | 1414 | for (i=0;i<irq_ptr->no_output_qs;i++) { |
1413 | oq = irq_ptr->output_qs[i]; | 1415 | oq = irq_ptr->output_qs[i]; |
1414 | if (!qdio_is_outbound_q_done(oq)) { | 1416 | if (!qdio_is_outbound_q_done(oq)) { |
1415 | if (qdio_performance_stats) | 1417 | qdio_perf_stat_dec(&perf_stats.tl_runs); |
1416 | perf_stats.tl_runs--; | ||
1417 | __qdio_outbound_processing(oq); | 1418 | __qdio_outbound_processing(oq); |
1418 | } | 1419 | } |
1419 | } | 1420 | } |
@@ -1452,8 +1453,7 @@ __qdio_inbound_processing(struct qdio_q *q) | |||
1452 | 1453 | ||
1453 | if (unlikely(qdio_reserve_q(q))) { | 1454 | if (unlikely(qdio_reserve_q(q))) { |
1454 | qdio_release_q(q); | 1455 | qdio_release_q(q); |
1455 | if (qdio_performance_stats) | 1456 | qdio_perf_stat_inc(&perf_stats.inbound_tl_runs_resched); |
1456 | i_p_c++; | ||
1457 | /* as we're sissies, we'll check next time */ | 1457 | /* as we're sissies, we'll check next time */ |
1458 | if (likely(!atomic_read(&q->is_in_shutdown))) { | 1458 | if (likely(!atomic_read(&q->is_in_shutdown))) { |
1459 | qdio_mark_q(q); | 1459 | qdio_mark_q(q); |
@@ -1461,10 +1461,8 @@ __qdio_inbound_processing(struct qdio_q *q) | |||
1461 | } | 1461 | } |
1462 | return; | 1462 | return; |
1463 | } | 1463 | } |
1464 | if (qdio_performance_stats) { | 1464 | qdio_perf_stat_inc(&perf_stats.inbound_tl_runs); |
1465 | i_p_nc++; | 1465 | qdio_perf_stat_inc(&perf_stats.tl_runs); |
1466 | perf_stats.tl_runs++; | ||
1467 | } | ||
1468 | 1466 | ||
1469 | again: | 1467 | again: |
1470 | if (qdio_has_inbound_q_moved(q)) { | 1468 | if (qdio_has_inbound_q_moved(q)) { |
@@ -1510,8 +1508,7 @@ tiqdio_reset_processing_state(struct qdio_q *q, int q_laps) | |||
1510 | 1508 | ||
1511 | if (unlikely(qdio_reserve_q(q))) { | 1509 | if (unlikely(qdio_reserve_q(q))) { |
1512 | qdio_release_q(q); | 1510 | qdio_release_q(q); |
1513 | if (qdio_performance_stats) | 1511 | qdio_perf_stat_inc(&perf_stats.inbound_thin_tl_runs_resched); |
1514 | ii_p_c++; | ||
1515 | /* | 1512 | /* |
1516 | * as we might just be about to stop polling, we make | 1513 | * as we might just be about to stop polling, we make |
1517 | * sure that we check again at least once more | 1514 | * sure that we check again at least once more |
@@ -1602,8 +1599,7 @@ tiqdio_tl(unsigned long data) | |||
1602 | { | 1599 | { |
1603 | QDIO_DBF_TEXT4(0,trace,"iqdio_tl"); | 1600 | QDIO_DBF_TEXT4(0,trace,"iqdio_tl"); |
1604 | 1601 | ||
1605 | if (qdio_performance_stats) | 1602 | qdio_perf_stat_inc(&perf_stats.tl_runs); |
1606 | perf_stats.tl_runs++; | ||
1607 | 1603 | ||
1608 | tiqdio_inbound_checks(); | 1604 | tiqdio_inbound_checks(); |
1609 | } | 1605 | } |
@@ -1914,10 +1910,7 @@ tiqdio_thinint_handler(void) | |||
1914 | { | 1910 | { |
1915 | QDIO_DBF_TEXT4(0,trace,"thin_int"); | 1911 | QDIO_DBF_TEXT4(0,trace,"thin_int"); |
1916 | 1912 | ||
1917 | if (qdio_performance_stats) { | 1913 | qdio_perf_stat_inc(&perf_stats.thinints); |
1918 | perf_stats.thinints++; | ||
1919 | perf_stats.start_time_inbound=NOW; | ||
1920 | } | ||
1921 | 1914 | ||
1922 | /* SVS only when needed: | 1915 | /* SVS only when needed: |
1923 | * issue SVS to benefit from iqdio interrupt avoidance | 1916 | * issue SVS to benefit from iqdio interrupt avoidance |
@@ -1972,17 +1965,12 @@ qdio_handle_pci(struct qdio_irq *irq_ptr) | |||
1972 | int i; | 1965 | int i; |
1973 | struct qdio_q *q; | 1966 | struct qdio_q *q; |
1974 | 1967 | ||
1975 | if (qdio_performance_stats) { | 1968 | qdio_perf_stat_inc(&perf_stats.pcis); |
1976 | perf_stats.pcis++; | ||
1977 | perf_stats.start_time_inbound=NOW; | ||
1978 | } | ||
1979 | for (i=0;i<irq_ptr->no_input_qs;i++) { | 1969 | for (i=0;i<irq_ptr->no_input_qs;i++) { |
1980 | q=irq_ptr->input_qs[i]; | 1970 | q=irq_ptr->input_qs[i]; |
1981 | if (q->is_input_q&QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT) | 1971 | if (q->is_input_q&QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT) |
1982 | qdio_mark_q(q); | 1972 | qdio_mark_q(q); |
1983 | else { | 1973 | else { |
1984 | if (qdio_performance_stats) | ||
1985 | perf_stats.tl_runs--; | ||
1986 | __qdio_inbound_processing(q); | 1974 | __qdio_inbound_processing(q); |
1987 | } | 1975 | } |
1988 | } | 1976 | } |
@@ -1992,8 +1980,7 @@ qdio_handle_pci(struct qdio_irq *irq_ptr) | |||
1992 | q=irq_ptr->output_qs[i]; | 1980 | q=irq_ptr->output_qs[i]; |
1993 | if (qdio_is_outbound_q_done(q)) | 1981 | if (qdio_is_outbound_q_done(q)) |
1994 | continue; | 1982 | continue; |
1995 | if (qdio_performance_stats) | 1983 | qdio_perf_stat_dec(&perf_stats.tl_runs); |
1996 | perf_stats.tl_runs--; | ||
1997 | if (!irq_ptr->sync_done_on_outb_pcis) | 1984 | if (!irq_ptr->sync_done_on_outb_pcis) |
1998 | SYNC_MEMORY; | 1985 | SYNC_MEMORY; |
1999 | __qdio_outbound_processing(q); | 1986 | __qdio_outbound_processing(q); |
@@ -3463,18 +3450,12 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags, | |||
3463 | struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; | 3450 | struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; |
3464 | 3451 | ||
3465 | /* This is the outbound handling of queues */ | 3452 | /* This is the outbound handling of queues */ |
3466 | if (qdio_performance_stats) | ||
3467 | perf_stats.start_time_outbound=NOW; | ||
3468 | |||
3469 | qdio_do_qdio_fill_output(q,qidx,count,buffers); | 3453 | qdio_do_qdio_fill_output(q,qidx,count,buffers); |
3470 | 3454 | ||
3471 | used_elements=atomic_add_return(count, &q->number_of_buffers_used) - count; | 3455 | used_elements=atomic_add_return(count, &q->number_of_buffers_used) - count; |
3472 | 3456 | ||
3473 | if (callflags&QDIO_FLAG_DONT_SIGA) { | 3457 | if (callflags&QDIO_FLAG_DONT_SIGA) { |
3474 | if (qdio_performance_stats) { | 3458 | qdio_perf_stat_inc(&perf_stats.outbound_cnt); |
3475 | perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound; | ||
3476 | perf_stats.outbound_cnt++; | ||
3477 | } | ||
3478 | return; | 3459 | return; |
3479 | } | 3460 | } |
3480 | if (q->is_iqdio_q) { | 3461 | if (q->is_iqdio_q) { |
@@ -3504,8 +3485,7 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags, | |||
3504 | qdio_kick_outbound_q(q); | 3485 | qdio_kick_outbound_q(q); |
3505 | } else { | 3486 | } else { |
3506 | QDIO_DBF_TEXT3(0,trace, "fast-req"); | 3487 | QDIO_DBF_TEXT3(0,trace, "fast-req"); |
3507 | if (qdio_performance_stats) | 3488 | qdio_perf_stat_inc(&perf_stats.fast_reqs); |
3508 | perf_stats.fast_reqs++; | ||
3509 | } | 3489 | } |
3510 | } | 3490 | } |
3511 | /* | 3491 | /* |
@@ -3516,10 +3496,7 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags, | |||
3516 | __qdio_outbound_processing(q); | 3496 | __qdio_outbound_processing(q); |
3517 | } | 3497 | } |
3518 | 3498 | ||
3519 | if (qdio_performance_stats) { | 3499 | qdio_perf_stat_inc(&perf_stats.outbound_cnt); |
3520 | perf_stats.outbound_time+=NOW-perf_stats.start_time_outbound; | ||
3521 | perf_stats.outbound_cnt++; | ||
3522 | } | ||
3523 | } | 3500 | } |
3524 | 3501 | ||
3525 | /* count must be 1 in iqdio */ | 3502 | /* count must be 1 in iqdio */ |
@@ -3589,33 +3566,67 @@ qdio_perf_procfile_read(char *buffer, char **buffer_location, off_t offset, | |||
3589 | return 0; | 3566 | return 0; |
3590 | 3567 | ||
3591 | #define _OUTP_IT(x...) c+=sprintf(buffer+c,x) | 3568 | #define _OUTP_IT(x...) c+=sprintf(buffer+c,x) |
3592 | _OUTP_IT("i_p_nc/c=%lu/%lu\n",i_p_nc,i_p_c); | 3569 | #ifdef CONFIG_64BIT |
3593 | _OUTP_IT("ii_p_nc/c=%lu/%lu\n",ii_p_nc,ii_p_c); | 3570 | _OUTP_IT("Number of tasklet runs (total) : %li\n", |
3594 | _OUTP_IT("o_p_nc/c=%lu/%lu\n",o_p_nc,o_p_c); | 3571 | (long)atomic64_read(&perf_stats.tl_runs)); |
3595 | _OUTP_IT("Number of tasklet runs (total) : %lu\n", | 3572 | _OUTP_IT("Inbound tasklet runs tried/retried : %li/%li\n", |
3596 | perf_stats.tl_runs); | 3573 | (long)atomic64_read(&perf_stats.inbound_tl_runs), |
3574 | (long)atomic64_read(&perf_stats.inbound_tl_runs_resched)); | ||
3575 | _OUTP_IT("Inbound-thin tasklet runs tried/retried : %li/%li\n", | ||
3576 | (long)atomic64_read(&perf_stats.inbound_thin_tl_runs), | ||
3577 | (long)atomic64_read(&perf_stats.inbound_thin_tl_runs_resched)); | ||
3578 | _OUTP_IT("Outbound tasklet runs tried/retried : %li/%li\n", | ||
3579 | (long)atomic64_read(&perf_stats.outbound_tl_runs), | ||
3580 | (long)atomic64_read(&perf_stats.outbound_tl_runs_resched)); | ||
3597 | _OUTP_IT("\n"); | 3581 | _OUTP_IT("\n"); |
3598 | _OUTP_IT("Number of SIGA sync's issued : %lu\n", | 3582 | _OUTP_IT("Number of SIGA sync's issued : %li\n", |
3599 | perf_stats.siga_syncs); | 3583 | (long)atomic64_read(&perf_stats.siga_syncs)); |
3600 | _OUTP_IT("Number of SIGA in's issued : %lu\n", | 3584 | _OUTP_IT("Number of SIGA in's issued : %li\n", |
3601 | perf_stats.siga_ins); | 3585 | (long)atomic64_read(&perf_stats.siga_ins)); |
3602 | _OUTP_IT("Number of SIGA out's issued : %lu\n", | 3586 | _OUTP_IT("Number of SIGA out's issued : %li\n", |
3603 | perf_stats.siga_outs); | 3587 | (long)atomic64_read(&perf_stats.siga_outs)); |
3604 | _OUTP_IT("Number of PCIs caught : %lu\n", | 3588 | _OUTP_IT("Number of PCIs caught : %li\n", |
3605 | perf_stats.pcis); | 3589 | (long)atomic64_read(&perf_stats.pcis)); |
3606 | _OUTP_IT("Number of adapter interrupts caught : %lu\n", | 3590 | _OUTP_IT("Number of adapter interrupts caught : %li\n", |
3607 | perf_stats.thinints); | 3591 | (long)atomic64_read(&perf_stats.thinints)); |
3608 | _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA) : %lu\n", | 3592 | _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA) : %li\n", |
3609 | perf_stats.fast_reqs); | 3593 | (long)atomic64_read(&perf_stats.fast_reqs)); |
3610 | _OUTP_IT("\n"); | 3594 | _OUTP_IT("\n"); |
3611 | _OUTP_IT("Total time of all inbound actions (us) incl. UL : %lu\n", | 3595 | _OUTP_IT("Number of inbound transfers : %li\n", |
3612 | perf_stats.inbound_time); | 3596 | (long)atomic64_read(&perf_stats.inbound_cnt)); |
3613 | _OUTP_IT("Number of inbound transfers : %lu\n", | 3597 | _OUTP_IT("Number of do_QDIOs outbound : %li\n", |
3614 | perf_stats.inbound_cnt); | 3598 | (long)atomic64_read(&perf_stats.outbound_cnt)); |
3615 | _OUTP_IT("Total time of all outbound do_QDIOs (us) : %lu\n", | 3599 | #else /* CONFIG_64BIT */ |
3616 | perf_stats.outbound_time); | 3600 | _OUTP_IT("Number of tasklet runs (total) : %i\n", |
3617 | _OUTP_IT("Number of do_QDIOs outbound : %lu\n", | 3601 | atomic_read(&perf_stats.tl_runs)); |
3618 | perf_stats.outbound_cnt); | 3602 | _OUTP_IT("Inbound tasklet runs tried/retried : %i/%i\n", |
3603 | atomic_read(&perf_stats.inbound_tl_runs), | ||
3604 | atomic_read(&perf_stats.inbound_tl_runs_resched)); | ||
3605 | _OUTP_IT("Inbound-thin tasklet runs tried/retried : %i/%i\n", | ||
3606 | atomic_read(&perf_stats.inbound_thin_tl_runs), | ||
3607 | atomic_read(&perf_stats.inbound_thin_tl_runs_resched)); | ||
3608 | _OUTP_IT("Outbound tasklet runs tried/retried : %i/%i\n", | ||
3609 | atomic_read(&perf_stats.outbound_tl_runs), | ||
3610 | atomic_read(&perf_stats.outbound_tl_runs_resched)); | ||
3611 | _OUTP_IT("\n"); | ||
3612 | _OUTP_IT("Number of SIGA sync's issued : %i\n", | ||
3613 | atomic_read(&perf_stats.siga_syncs)); | ||
3614 | _OUTP_IT("Number of SIGA in's issued : %i\n", | ||
3615 | atomic_read(&perf_stats.siga_ins)); | ||
3616 | _OUTP_IT("Number of SIGA out's issued : %i\n", | ||
3617 | atomic_read(&perf_stats.siga_outs)); | ||
3618 | _OUTP_IT("Number of PCIs caught : %i\n", | ||
3619 | atomic_read(&perf_stats.pcis)); | ||
3620 | _OUTP_IT("Number of adapter interrupts caught : %i\n", | ||
3621 | atomic_read(&perf_stats.thinints)); | ||
3622 | _OUTP_IT("Number of fast requeues (outg. SBALs w/o SIGA) : %i\n", | ||
3623 | atomic_read(&perf_stats.fast_reqs)); | ||
3624 | _OUTP_IT("\n"); | ||
3625 | _OUTP_IT("Number of inbound transfers : %i\n", | ||
3626 | atomic_read(&perf_stats.inbound_cnt)); | ||
3627 | _OUTP_IT("Number of do_QDIOs outbound : %i\n", | ||
3628 | atomic_read(&perf_stats.outbound_cnt)); | ||
3629 | #endif /* CONFIG_64BIT */ | ||
3619 | _OUTP_IT("\n"); | 3630 | _OUTP_IT("\n"); |
3620 | 3631 | ||
3621 | return c; | 3632 | return c; |
@@ -3642,8 +3653,6 @@ qdio_add_procfs_entry(void) | |||
3642 | static void | 3653 | static void |
3643 | qdio_remove_procfs_entry(void) | 3654 | qdio_remove_procfs_entry(void) |
3644 | { | 3655 | { |
3645 | perf_stats.tl_runs=0; | ||
3646 | |||
3647 | if (!proc_perf_file_registration) /* means if it went ok earlier */ | 3656 | if (!proc_perf_file_registration) /* means if it went ok earlier */ |
3648 | remove_proc_entry(QDIO_PERF,&proc_root); | 3657 | remove_proc_entry(QDIO_PERF,&proc_root); |
3649 | } | 3658 | } |
@@ -3671,13 +3680,38 @@ qdio_performance_stats_store(struct bus_type *bus, const char *buf, size_t count | |||
3671 | qdio_performance_stats = i; | 3680 | qdio_performance_stats = i; |
3672 | if (i==0) { | 3681 | if (i==0) { |
3673 | /* reset perf. stat. info */ | 3682 | /* reset perf. stat. info */ |
3674 | i_p_nc = 0; | 3683 | #ifdef CONFIG_64BIT |
3675 | i_p_c = 0; | 3684 | atomic64_set(&perf_stats.tl_runs, 0); |
3676 | ii_p_nc = 0; | 3685 | atomic64_set(&perf_stats.outbound_tl_runs, 0); |
3677 | ii_p_c = 0; | 3686 | atomic64_set(&perf_stats.inbound_tl_runs, 0); |
3678 | o_p_nc = 0; | 3687 | atomic64_set(&perf_stats.inbound_tl_runs_resched, 0); |
3679 | o_p_c = 0; | 3688 | atomic64_set(&perf_stats.inbound_thin_tl_runs, 0); |
3680 | memset(&perf_stats, 0, sizeof(struct qdio_perf_stats)); | 3689 | atomic64_set(&perf_stats.inbound_thin_tl_runs_resched, |
3690 | 0); | ||
3691 | atomic64_set(&perf_stats.siga_outs, 0); | ||
3692 | atomic64_set(&perf_stats.siga_ins, 0); | ||
3693 | atomic64_set(&perf_stats.siga_syncs, 0); | ||
3694 | atomic64_set(&perf_stats.pcis, 0); | ||
3695 | atomic64_set(&perf_stats.thinints, 0); | ||
3696 | atomic64_set(&perf_stats.fast_reqs, 0); | ||
3697 | atomic64_set(&perf_stats.outbound_cnt, 0); | ||
3698 | atomic64_set(&perf_stats.inbound_cnt, 0); | ||
3699 | #else /* CONFIG_64BIT */ | ||
3700 | atomic_set(&perf_stats.tl_runs, 0); | ||
3701 | atomic_set(&perf_stats.outbound_tl_runs, 0); | ||
3702 | atomic_set(&perf_stats.inbound_tl_runs, 0); | ||
3703 | atomic_set(&perf_stats.inbound_tl_runs_resched, 0); | ||
3704 | atomic_set(&perf_stats.inbound_thin_tl_runs, 0); | ||
3705 | atomic_set(&perf_stats.inbound_thin_tl_runs_resched, 0); | ||
3706 | atomic_set(&perf_stats.siga_outs, 0); | ||
3707 | atomic_set(&perf_stats.siga_ins, 0); | ||
3708 | atomic_set(&perf_stats.siga_syncs, 0); | ||
3709 | atomic_set(&perf_stats.pcis, 0); | ||
3710 | atomic_set(&perf_stats.thinints, 0); | ||
3711 | atomic_set(&perf_stats.fast_reqs, 0); | ||
3712 | atomic_set(&perf_stats.outbound_cnt, 0); | ||
3713 | atomic_set(&perf_stats.inbound_cnt, 0); | ||
3714 | #endif /* CONFIG_64BIT */ | ||
3681 | } | 3715 | } |
3682 | } else { | 3716 | } else { |
3683 | QDIO_PRINT_WARN("QDIO performance_stats: write 0 or 1 to this file!\n"); | 3717 | QDIO_PRINT_WARN("QDIO performance_stats: write 0 or 1 to this file!\n"); |
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index ec9af72b2afc..2895392eaae4 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
@@ -406,21 +406,43 @@ do_clear_global_summary(void) | |||
406 | #define CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS 0x04 | 406 | #define CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS 0x04 |
407 | 407 | ||
408 | struct qdio_perf_stats { | 408 | struct qdio_perf_stats { |
409 | unsigned long tl_runs; | 409 | #ifdef CONFIG_64BIT |
410 | 410 | atomic64_t tl_runs; | |
411 | unsigned long siga_outs; | 411 | atomic64_t outbound_tl_runs; |
412 | unsigned long siga_ins; | 412 | atomic64_t outbound_tl_runs_resched; |
413 | unsigned long siga_syncs; | 413 | atomic64_t inbound_tl_runs; |
414 | unsigned long pcis; | 414 | atomic64_t inbound_tl_runs_resched; |
415 | unsigned long thinints; | 415 | atomic64_t inbound_thin_tl_runs; |
416 | unsigned long fast_reqs; | 416 | atomic64_t inbound_thin_tl_runs_resched; |
417 | 417 | ||
418 | __u64 start_time_outbound; | 418 | atomic64_t siga_outs; |
419 | unsigned long outbound_cnt; | 419 | atomic64_t siga_ins; |
420 | unsigned long outbound_time; | 420 | atomic64_t siga_syncs; |
421 | __u64 start_time_inbound; | 421 | atomic64_t pcis; |
422 | unsigned long inbound_cnt; | 422 | atomic64_t thinints; |
423 | unsigned long inbound_time; | 423 | atomic64_t fast_reqs; |
424 | |||
425 | atomic64_t outbound_cnt; | ||
426 | atomic64_t inbound_cnt; | ||
427 | #else /* CONFIG_64BIT */ | ||
428 | atomic_t tl_runs; | ||
429 | atomic_t outbound_tl_runs; | ||
430 | atomic_t outbound_tl_runs_resched; | ||
431 | atomic_t inbound_tl_runs; | ||
432 | atomic_t inbound_tl_runs_resched; | ||
433 | atomic_t inbound_thin_tl_runs; | ||
434 | atomic_t inbound_thin_tl_runs_resched; | ||
435 | |||
436 | atomic_t siga_outs; | ||
437 | atomic_t siga_ins; | ||
438 | atomic_t siga_syncs; | ||
439 | atomic_t pcis; | ||
440 | atomic_t thinints; | ||
441 | atomic_t fast_reqs; | ||
442 | |||
443 | atomic_t outbound_cnt; | ||
444 | atomic_t inbound_cnt; | ||
445 | #endif /* CONFIG_64BIT */ | ||
424 | }; | 446 | }; |
425 | 447 | ||
426 | /* unlikely as the later the better */ | 448 | /* unlikely as the later the better */ |
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 84b108d7c7fd..b34eb82edd98 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h | |||
@@ -288,6 +288,7 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func) | |||
288 | */ | 288 | */ |
289 | #define IF_NAME_LEN 16 | 289 | #define IF_NAME_LEN 16 |
290 | #define QETH_TX_TIMEOUT 100 * HZ | 290 | #define QETH_TX_TIMEOUT 100 * HZ |
291 | #define QETH_RCD_TIMEOUT 60 * HZ | ||
291 | #define QETH_HEADER_SIZE 32 | 292 | #define QETH_HEADER_SIZE 32 |
292 | #define MAX_PORTNO 15 | 293 | #define MAX_PORTNO 15 |
293 | #define QETH_FAKE_LL_LEN_ETH ETH_HLEN | 294 | #define QETH_FAKE_LL_LEN_ETH ETH_HLEN |
@@ -582,6 +583,8 @@ enum qeth_channel_states { | |||
582 | CH_STATE_ACTIVATING, | 583 | CH_STATE_ACTIVATING, |
583 | CH_STATE_HALTED, | 584 | CH_STATE_HALTED, |
584 | CH_STATE_STOPPED, | 585 | CH_STATE_STOPPED, |
586 | CH_STATE_RCD, | ||
587 | CH_STATE_RCD_DONE, | ||
585 | }; | 588 | }; |
586 | /** | 589 | /** |
587 | * card state machine | 590 | * card state machine |
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index ad7792dc1a04..6fd8870551d3 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
@@ -315,7 +315,8 @@ qeth_alloc_card(void) | |||
315 | } | 315 | } |
316 | 316 | ||
317 | static long | 317 | static long |
318 | __qeth_check_irb_error(struct ccw_device *cdev, struct irb *irb) | 318 | __qeth_check_irb_error(struct ccw_device *cdev, unsigned long intparm, |
319 | struct irb *irb) | ||
319 | { | 320 | { |
320 | if (!IS_ERR(irb)) | 321 | if (!IS_ERR(irb)) |
321 | return 0; | 322 | return 0; |
@@ -330,6 +331,14 @@ __qeth_check_irb_error(struct ccw_device *cdev, struct irb *irb) | |||
330 | PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id); | 331 | PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id); |
331 | QETH_DBF_TEXT(trace, 2, "ckirberr"); | 332 | QETH_DBF_TEXT(trace, 2, "ckirberr"); |
332 | QETH_DBF_TEXT_(trace, 2, " rc%d", -ETIMEDOUT); | 333 | QETH_DBF_TEXT_(trace, 2, " rc%d", -ETIMEDOUT); |
334 | if (intparm == QETH_RCD_PARM) { | ||
335 | struct qeth_card *card = CARD_FROM_CDEV(cdev); | ||
336 | |||
337 | if (card && (card->data.ccwdev == cdev)) { | ||
338 | card->data.state = CH_STATE_DOWN; | ||
339 | wake_up(&card->wait_q); | ||
340 | } | ||
341 | } | ||
333 | break; | 342 | break; |
334 | default: | 343 | default: |
335 | PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb), | 344 | PRINT_WARN("unknown error %ld on device %s\n", PTR_ERR(irb), |
@@ -401,7 +410,7 @@ qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
401 | 410 | ||
402 | QETH_DBF_TEXT(trace,5,"irq"); | 411 | QETH_DBF_TEXT(trace,5,"irq"); |
403 | 412 | ||
404 | if (__qeth_check_irb_error(cdev, irb)) | 413 | if (__qeth_check_irb_error(cdev, intparm, irb)) |
405 | return; | 414 | return; |
406 | cstat = irb->scsw.cstat; | 415 | cstat = irb->scsw.cstat; |
407 | dstat = irb->scsw.dstat; | 416 | dstat = irb->scsw.dstat; |
@@ -429,7 +438,8 @@ qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
429 | channel->state = CH_STATE_HALTED; | 438 | channel->state = CH_STATE_HALTED; |
430 | 439 | ||
431 | /*let's wake up immediately on data channel*/ | 440 | /*let's wake up immediately on data channel*/ |
432 | if ((channel == &card->data) && (intparm != 0)) | 441 | if ((channel == &card->data) && (intparm != 0) && |
442 | (intparm != QETH_RCD_PARM)) | ||
433 | goto out; | 443 | goto out; |
434 | 444 | ||
435 | if (intparm == QETH_CLEAR_CHANNEL_PARM) { | 445 | if (intparm == QETH_CLEAR_CHANNEL_PARM) { |
@@ -453,6 +463,10 @@ qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
453 | HEXDUMP16(WARN,"irb: ",irb); | 463 | HEXDUMP16(WARN,"irb: ",irb); |
454 | HEXDUMP16(WARN,"sense data: ",irb->ecw); | 464 | HEXDUMP16(WARN,"sense data: ",irb->ecw); |
455 | } | 465 | } |
466 | if (intparm == QETH_RCD_PARM) { | ||
467 | channel->state = CH_STATE_DOWN; | ||
468 | goto out; | ||
469 | } | ||
456 | rc = qeth_get_problem(cdev,irb); | 470 | rc = qeth_get_problem(cdev,irb); |
457 | if (rc) { | 471 | if (rc) { |
458 | qeth_schedule_recovery(card); | 472 | qeth_schedule_recovery(card); |
@@ -460,6 +474,10 @@ qeth_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
460 | } | 474 | } |
461 | } | 475 | } |
462 | 476 | ||
477 | if (intparm == QETH_RCD_PARM) { | ||
478 | channel->state = CH_STATE_RCD_DONE; | ||
479 | goto out; | ||
480 | } | ||
463 | if (intparm) { | 481 | if (intparm) { |
464 | buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm); | 482 | buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm); |
465 | buffer->state = BUF_STATE_PROCESSED; | 483 | buffer->state = BUF_STATE_PROCESSED; |
@@ -1204,6 +1222,54 @@ qeth_probe_device(struct ccwgroup_device *gdev) | |||
1204 | } | 1222 | } |
1205 | 1223 | ||
1206 | 1224 | ||
1225 | static int qeth_read_conf_data(struct qeth_card *card, void **buffer, | ||
1226 | int *length) | ||
1227 | { | ||
1228 | struct ciw *ciw; | ||
1229 | char *rcd_buf; | ||
1230 | int ret; | ||
1231 | struct qeth_channel *channel = &card->data; | ||
1232 | unsigned long flags; | ||
1233 | |||
1234 | /* | ||
1235 | * scan for RCD command in extended SenseID data | ||
1236 | */ | ||
1237 | ciw = ccw_device_get_ciw(channel->ccwdev, CIW_TYPE_RCD); | ||
1238 | if (!ciw || ciw->cmd == 0) | ||
1239 | return -EOPNOTSUPP; | ||
1240 | rcd_buf = kzalloc(ciw->count, GFP_KERNEL | GFP_DMA); | ||
1241 | if (!rcd_buf) | ||
1242 | return -ENOMEM; | ||
1243 | |||
1244 | channel->ccw.cmd_code = ciw->cmd; | ||
1245 | channel->ccw.cda = (__u32) __pa (rcd_buf); | ||
1246 | channel->ccw.count = ciw->count; | ||
1247 | channel->ccw.flags = CCW_FLAG_SLI; | ||
1248 | channel->state = CH_STATE_RCD; | ||
1249 | spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); | ||
1250 | ret = ccw_device_start_timeout(channel->ccwdev, &channel->ccw, | ||
1251 | QETH_RCD_PARM, LPM_ANYPATH, 0, | ||
1252 | QETH_RCD_TIMEOUT); | ||
1253 | spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); | ||
1254 | if (!ret) | ||
1255 | wait_event(card->wait_q, | ||
1256 | (channel->state == CH_STATE_RCD_DONE || | ||
1257 | channel->state == CH_STATE_DOWN)); | ||
1258 | if (channel->state == CH_STATE_DOWN) | ||
1259 | ret = -EIO; | ||
1260 | else | ||
1261 | channel->state = CH_STATE_DOWN; | ||
1262 | if (ret) { | ||
1263 | kfree(rcd_buf); | ||
1264 | *buffer = NULL; | ||
1265 | *length = 0; | ||
1266 | } else { | ||
1267 | *length = ciw->count; | ||
1268 | *buffer = rcd_buf; | ||
1269 | } | ||
1270 | return ret; | ||
1271 | } | ||
1272 | |||
1207 | static int | 1273 | static int |
1208 | qeth_get_unitaddr(struct qeth_card *card) | 1274 | qeth_get_unitaddr(struct qeth_card *card) |
1209 | { | 1275 | { |
@@ -1212,9 +1278,9 @@ qeth_get_unitaddr(struct qeth_card *card) | |||
1212 | int rc; | 1278 | int rc; |
1213 | 1279 | ||
1214 | QETH_DBF_TEXT(setup, 2, "getunit"); | 1280 | QETH_DBF_TEXT(setup, 2, "getunit"); |
1215 | rc = read_conf_data(CARD_DDEV(card), (void **) &prcd, &length); | 1281 | rc = qeth_read_conf_data(card, (void **) &prcd, &length); |
1216 | if (rc) { | 1282 | if (rc) { |
1217 | PRINT_ERR("read_conf_data for device %s returned %i\n", | 1283 | PRINT_ERR("qeth_read_conf_data for device %s returned %i\n", |
1218 | CARD_DDEV_ID(card), rc); | 1284 | CARD_DDEV_ID(card), rc); |
1219 | return rc; | 1285 | return rc; |
1220 | } | 1286 | } |
@@ -1223,6 +1289,7 @@ qeth_get_unitaddr(struct qeth_card *card) | |||
1223 | card->info.cula = prcd[63]; | 1289 | card->info.cula = prcd[63]; |
1224 | card->info.guestlan = ((prcd[0x10] == _ascebc['V']) && | 1290 | card->info.guestlan = ((prcd[0x10] == _ascebc['V']) && |
1225 | (prcd[0x11] == _ascebc['M'])); | 1291 | (prcd[0x11] == _ascebc['M'])); |
1292 | kfree(prcd); | ||
1226 | return 0; | 1293 | return 0; |
1227 | } | 1294 | } |
1228 | 1295 | ||
diff --git a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h index 0477c47471c5..d74bc43da72a 100644 --- a/drivers/s390/net/qeth_mpc.h +++ b/drivers/s390/net/qeth_mpc.h | |||
@@ -37,6 +37,7 @@ extern unsigned char IPA_PDU_HEADER[]; | |||
37 | 37 | ||
38 | #define QETH_CLEAR_CHANNEL_PARM -10 | 38 | #define QETH_CLEAR_CHANNEL_PARM -10 |
39 | #define QETH_HALT_CHANNEL_PARM -11 | 39 | #define QETH_HALT_CHANNEL_PARM -11 |
40 | #define QETH_RCD_PARM -12 | ||
40 | 41 | ||
41 | /*****************************************************************************/ | 42 | /*****************************************************************************/ |
42 | /* IP Assist related definitions */ | 43 | /* IP Assist related definitions */ |
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c index eee590a51d8a..002643392d42 100644 --- a/drivers/sbus/sbus.c +++ b/drivers/sbus/sbus.c | |||
@@ -6,7 +6,6 @@ | |||
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
7 | #include <linux/slab.h> | 7 | #include <linux/slab.h> |
8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
9 | #include <linux/pci.h> | ||
10 | #include <linux/device.h> | 9 | #include <linux/device.h> |
11 | 10 | ||
12 | #include <asm/system.h> | 11 | #include <asm/system.h> |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index fcc4cb6c7f46..e1ebed0f0755 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -1649,7 +1649,7 @@ config OKTAGON_SCSI | |||
1649 | 1649 | ||
1650 | config ATARI_SCSI | 1650 | config ATARI_SCSI |
1651 | tristate "Atari native SCSI support" | 1651 | tristate "Atari native SCSI support" |
1652 | depends on ATARI && SCSI && BROKEN | 1652 | depends on ATARI && SCSI |
1653 | select SCSI_SPI_ATTRS | 1653 | select SCSI_SPI_ATTRS |
1654 | ---help--- | 1654 | ---help--- |
1655 | If you have an Atari with built-in NCR5380 SCSI controller (TT, | 1655 | If you have an Atari with built-in NCR5380 SCSI controller (TT, |
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index d38b628be1ad..66aeb57dcc2d 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
33 | #include <linux/init.h> | 33 | #include <linux/init.h> |
34 | #include <linux/types.h> | 34 | #include <linux/types.h> |
35 | #include <linux/pci.h> | ||
36 | #include <linux/spinlock.h> | 35 | #include <linux/spinlock.h> |
37 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
38 | #include <linux/completion.h> | 37 | #include <linux/completion.h> |
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c index 6f1a1780efce..f4b5e9742ab0 100644 --- a/drivers/scsi/aacraid/sa.c +++ b/drivers/scsi/aacraid/sa.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/types.h> | 33 | #include <linux/types.h> |
34 | #include <linux/pci.h> | ||
35 | #include <linux/spinlock.h> | 34 | #include <linux/spinlock.h> |
36 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
37 | #include <linux/blkdev.h> | 36 | #include <linux/blkdev.h> |
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index 1d239f6c0103..cbbfbc9f3e0f 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <linux/proc_fs.h> | 35 | #include <linux/proc_fs.h> |
36 | #include <linux/init.h> | 36 | #include <linux/init.h> |
37 | #include <linux/spinlock.h> | 37 | #include <linux/spinlock.h> |
38 | #include <linux/pci.h> | ||
39 | #include <linux/isapnp.h> | 38 | #include <linux/isapnp.h> |
40 | #include <linux/blkdev.h> | 39 | #include <linux/blkdev.h> |
41 | #include <linux/mca.h> | 40 | #include <linux/mca.h> |
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index 8f43ff772f23..db6ab1a3b81e 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c | |||
@@ -24,7 +24,6 @@ | |||
24 | * | 24 | * |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/pci.h> | ||
28 | #include <scsi/scsi_host.h> | 27 | #include <scsi/scsi_host.h> |
29 | 28 | ||
30 | #include "aic94xx.h" | 29 | #include "aic94xx.h" |
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index 12497da5529d..03bfed61bffc 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c | |||
@@ -49,7 +49,6 @@ | |||
49 | #include <linux/init.h> | 49 | #include <linux/init.h> |
50 | #include <linux/errno.h> | 50 | #include <linux/errno.h> |
51 | #include <linux/delay.h> | 51 | #include <linux/delay.h> |
52 | #include <linux/pci.h> | ||
53 | 52 | ||
54 | #include <scsi/scsi_cmnd.h> | 53 | #include <scsi/scsi_cmnd.h> |
55 | #include <scsi/scsi_device.h> | 54 | #include <scsi/scsi_device.h> |
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 0f920c84ac0f..eff846ae0aff 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c | |||
@@ -1,19 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * NCR 5380 generic driver routines. These should make it *trivial* | 2 | * NCR 5380 generic driver routines. These should make it *trivial* |
3 | * to implement 5380 SCSI drivers under Linux with a non-trantor | 3 | * to implement 5380 SCSI drivers under Linux with a non-trantor |
4 | * architecture. | 4 | * architecture. |
5 | * | 5 | * |
6 | * Note that these routines also work with NR53c400 family chips. | 6 | * Note that these routines also work with NR53c400 family chips. |
7 | * | 7 | * |
8 | * Copyright 1993, Drew Eckhardt | 8 | * Copyright 1993, Drew Eckhardt |
9 | * Visionary Computing | 9 | * Visionary Computing |
10 | * (Unix and Linux consulting and custom programming) | 10 | * (Unix and Linux consulting and custom programming) |
11 | * drew@colorado.edu | 11 | * drew@colorado.edu |
12 | * +1 (303) 666-5836 | 12 | * +1 (303) 666-5836 |
13 | * | 13 | * |
14 | * DISTRIBUTION RELEASE 6. | 14 | * DISTRIBUTION RELEASE 6. |
15 | * | 15 | * |
16 | * For more information, please consult | 16 | * For more information, please consult |
17 | * | 17 | * |
18 | * NCR 5380 Family | 18 | * NCR 5380 Family |
19 | * SCSI Protocol Controller | 19 | * SCSI Protocol Controller |
@@ -57,7 +57,7 @@ | |||
57 | * - I've deleted all the stuff for AUTOPROBE_IRQ, REAL_DMA_POLL, PSEUDO_DMA | 57 | * - I've deleted all the stuff for AUTOPROBE_IRQ, REAL_DMA_POLL, PSEUDO_DMA |
58 | * and USLEEP, because these were messing up readability and will never be | 58 | * and USLEEP, because these were messing up readability and will never be |
59 | * needed for Atari SCSI. | 59 | * needed for Atari SCSI. |
60 | * | 60 | * |
61 | * - I've revised the NCR5380_main() calling scheme (relax the 'main_running' | 61 | * - I've revised the NCR5380_main() calling scheme (relax the 'main_running' |
62 | * stuff), and 'main' is executed in a bottom half if awoken by an | 62 | * stuff), and 'main' is executed in a bottom half if awoken by an |
63 | * interrupt. | 63 | * interrupt. |
@@ -69,21 +69,29 @@ | |||
69 | */ | 69 | */ |
70 | 70 | ||
71 | /* | 71 | /* |
72 | * Further development / testing that should be done : | 72 | * Further development / testing that should be done : |
73 | * 1. Test linked command handling code after Eric is ready with | 73 | * 1. Test linked command handling code after Eric is ready with |
74 | * the high level code. | 74 | * the high level code. |
75 | */ | 75 | */ |
76 | #include <scsi/scsi_dbg.h> | 76 | #include <scsi/scsi_dbg.h> |
77 | #include <scsi/scsi_transport_spi.h> | 77 | #include <scsi/scsi_transport_spi.h> |
78 | 78 | ||
79 | #if (NDEBUG & NDEBUG_LISTS) | 79 | #if (NDEBUG & NDEBUG_LISTS) |
80 | #define LIST(x,y) \ | 80 | #define LIST(x, y) \ |
81 | { printk("LINE:%d Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); \ | 81 | do { \ |
82 | if ((x)==(y)) udelay(5); } | 82 | printk("LINE:%d Adding %p to %p\n", \ |
83 | #define REMOVE(w,x,y,z) \ | 83 | __LINE__, (void*)(x), (void*)(y)); \ |
84 | { printk("LINE:%d Removing: %p->%p %p->%p \n", __LINE__, \ | 84 | if ((x) == (y)) \ |
85 | (void*)(w), (void*)(x), (void*)(y), (void*)(z)); \ | 85 | udelay(5); \ |
86 | if ((x)==(y)) udelay(5); } | 86 | } while (0) |
87 | #define REMOVE(w, x, y, z) \ | ||
88 | do { \ | ||
89 | printk("LINE:%d Removing: %p->%p %p->%p \n", \ | ||
90 | __LINE__, (void*)(w), (void*)(x), \ | ||
91 | (void*)(y), (void*)(z)); \ | ||
92 | if ((x) == (y)) \ | ||
93 | udelay(5); \ | ||
94 | } while (0) | ||
87 | #else | 95 | #else |
88 | #define LIST(x,y) | 96 | #define LIST(x,y) |
89 | #define REMOVE(w,x,y,z) | 97 | #define REMOVE(w,x,y,z) |
@@ -103,62 +111,62 @@ | |||
103 | * more difficult than it has to be. | 111 | * more difficult than it has to be. |
104 | * | 112 | * |
105 | * Also, many of the SCSI drivers were written before the command queuing | 113 | * Also, many of the SCSI drivers were written before the command queuing |
106 | * routines were implemented, meaning their implementations of queued | 114 | * routines were implemented, meaning their implementations of queued |
107 | * commands were hacked on rather than designed in from the start. | 115 | * commands were hacked on rather than designed in from the start. |
108 | * | 116 | * |
109 | * When I designed the Linux SCSI drivers I figured that | 117 | * When I designed the Linux SCSI drivers I figured that |
110 | * while having two different SCSI boards in a system might be useful | 118 | * while having two different SCSI boards in a system might be useful |
111 | * for debugging things, two of the same type wouldn't be used. | 119 | * for debugging things, two of the same type wouldn't be used. |
112 | * Well, I was wrong and a number of users have mailed me about running | 120 | * Well, I was wrong and a number of users have mailed me about running |
113 | * multiple high-performance SCSI boards in a server. | 121 | * multiple high-performance SCSI boards in a server. |
114 | * | 122 | * |
115 | * Finally, when I get questions from users, I have no idea what | 123 | * Finally, when I get questions from users, I have no idea what |
116 | * revision of my driver they are running. | 124 | * revision of my driver they are running. |
117 | * | 125 | * |
118 | * This driver attempts to address these problems : | 126 | * This driver attempts to address these problems : |
119 | * This is a generic 5380 driver. To use it on a different platform, | 127 | * This is a generic 5380 driver. To use it on a different platform, |
120 | * one simply writes appropriate system specific macros (ie, data | 128 | * one simply writes appropriate system specific macros (ie, data |
121 | * transfer - some PC's will use the I/O bus, 68K's must use | 129 | * transfer - some PC's will use the I/O bus, 68K's must use |
122 | * memory mapped) and drops this file in their 'C' wrapper. | 130 | * memory mapped) and drops this file in their 'C' wrapper. |
123 | * | 131 | * |
124 | * As far as command queueing, two queues are maintained for | 132 | * As far as command queueing, two queues are maintained for |
125 | * each 5380 in the system - commands that haven't been issued yet, | 133 | * each 5380 in the system - commands that haven't been issued yet, |
126 | * and commands that are currently executing. This means that an | 134 | * and commands that are currently executing. This means that an |
127 | * unlimited number of commands may be queued, letting | 135 | * unlimited number of commands may be queued, letting |
128 | * more commands propagate from the higher driver levels giving higher | 136 | * more commands propagate from the higher driver levels giving higher |
129 | * throughput. Note that both I_T_L and I_T_L_Q nexuses are supported, | 137 | * throughput. Note that both I_T_L and I_T_L_Q nexuses are supported, |
130 | * allowing multiple commands to propagate all the way to a SCSI-II device | 138 | * allowing multiple commands to propagate all the way to a SCSI-II device |
131 | * while a command is already executing. | 139 | * while a command is already executing. |
132 | * | 140 | * |
133 | * To solve the multiple-boards-in-the-same-system problem, | 141 | * To solve the multiple-boards-in-the-same-system problem, |
134 | * there is a separate instance structure for each instance | 142 | * there is a separate instance structure for each instance |
135 | * of a 5380 in the system. So, multiple NCR5380 drivers will | 143 | * of a 5380 in the system. So, multiple NCR5380 drivers will |
136 | * be able to coexist with appropriate changes to the high level | 144 | * be able to coexist with appropriate changes to the high level |
137 | * SCSI code. | 145 | * SCSI code. |
138 | * | 146 | * |
139 | * A NCR5380_PUBLIC_REVISION macro is provided, with the release | 147 | * A NCR5380_PUBLIC_REVISION macro is provided, with the release |
140 | * number (updated for each public release) printed by the | 148 | * number (updated for each public release) printed by the |
141 | * NCR5380_print_options command, which should be called from the | 149 | * NCR5380_print_options command, which should be called from the |
142 | * wrapper detect function, so that I know what release of the driver | 150 | * wrapper detect function, so that I know what release of the driver |
143 | * users are using. | 151 | * users are using. |
144 | * | 152 | * |
145 | * Issues specific to the NCR5380 : | 153 | * Issues specific to the NCR5380 : |
146 | * | 154 | * |
147 | * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead | 155 | * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead |
148 | * piece of hardware that requires you to sit in a loop polling for | 156 | * piece of hardware that requires you to sit in a loop polling for |
149 | * the REQ signal as long as you are connected. Some devices are | 157 | * the REQ signal as long as you are connected. Some devices are |
150 | * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect | 158 | * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect |
151 | * while doing long seek operations. | 159 | * while doing long seek operations. |
152 | * | 160 | * |
153 | * The workaround for this is to keep track of devices that have | 161 | * The workaround for this is to keep track of devices that have |
154 | * disconnected. If the device hasn't disconnected, for commands that | 162 | * disconnected. If the device hasn't disconnected, for commands that |
155 | * should disconnect, we do something like | 163 | * should disconnect, we do something like |
156 | * | 164 | * |
157 | * while (!REQ is asserted) { sleep for N usecs; poll for M usecs } | 165 | * while (!REQ is asserted) { sleep for N usecs; poll for M usecs } |
158 | * | 166 | * |
159 | * Some tweaking of N and M needs to be done. An algorithm based | 167 | * Some tweaking of N and M needs to be done. An algorithm based |
160 | * on "time to data" would give the best results as long as short time | 168 | * on "time to data" would give the best results as long as short time |
161 | * to datas (ie, on the same track) were considered, however these | 169 | * to datas (ie, on the same track) were considered, however these |
162 | * broken devices are the exception rather than the rule and I'd rather | 170 | * broken devices are the exception rather than the rule and I'd rather |
163 | * spend my time optimizing for the normal case. | 171 | * spend my time optimizing for the normal case. |
164 | * | 172 | * |
@@ -167,9 +175,9 @@ | |||
167 | * At the heart of the design is a coroutine, NCR5380_main, | 175 | * At the heart of the design is a coroutine, NCR5380_main, |
168 | * which is started when not running by the interrupt handler, | 176 | * which is started when not running by the interrupt handler, |
169 | * timer, and queue command function. It attempts to establish | 177 | * timer, and queue command function. It attempts to establish |
170 | * I_T_L or I_T_L_Q nexuses by removing the commands from the | 178 | * I_T_L or I_T_L_Q nexuses by removing the commands from the |
171 | * issue queue and calling NCR5380_select() if a nexus | 179 | * issue queue and calling NCR5380_select() if a nexus |
172 | * is not established. | 180 | * is not established. |
173 | * | 181 | * |
174 | * Once a nexus is established, the NCR5380_information_transfer() | 182 | * Once a nexus is established, the NCR5380_information_transfer() |
175 | * phase goes through the various phases as instructed by the target. | 183 | * phase goes through the various phases as instructed by the target. |
@@ -183,10 +191,10 @@ | |||
183 | * calling NCR5380_intr() which will in turn call NCR5380_reselect | 191 | * calling NCR5380_intr() which will in turn call NCR5380_reselect |
184 | * to reestablish a nexus. This will run main if necessary. | 192 | * to reestablish a nexus. This will run main if necessary. |
185 | * | 193 | * |
186 | * On command termination, the done function will be called as | 194 | * On command termination, the done function will be called as |
187 | * appropriate. | 195 | * appropriate. |
188 | * | 196 | * |
189 | * SCSI pointers are maintained in the SCp field of SCSI command | 197 | * SCSI pointers are maintained in the SCp field of SCSI command |
190 | * structures, being initialized after the command is connected | 198 | * structures, being initialized after the command is connected |
191 | * in NCR5380_select, and set as appropriate in NCR5380_information_transfer. | 199 | * in NCR5380_select, and set as appropriate in NCR5380_information_transfer. |
192 | * Note that in violation of the standard, an implicit SAVE POINTERS operation | 200 | * Note that in violation of the standard, an implicit SAVE POINTERS operation |
@@ -196,12 +204,12 @@ | |||
196 | /* | 204 | /* |
197 | * Using this file : | 205 | * Using this file : |
198 | * This file a skeleton Linux SCSI driver for the NCR 5380 series | 206 | * This file a skeleton Linux SCSI driver for the NCR 5380 series |
199 | * of chips. To use it, you write an architecture specific functions | 207 | * of chips. To use it, you write an architecture specific functions |
200 | * and macros and include this file in your driver. | 208 | * and macros and include this file in your driver. |
201 | * | 209 | * |
202 | * These macros control options : | 210 | * These macros control options : |
203 | * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically | 211 | * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically |
204 | * for commands that return with a CHECK CONDITION status. | 212 | * for commands that return with a CHECK CONDITION status. |
205 | * | 213 | * |
206 | * LINKED - if defined, linked commands are supported. | 214 | * LINKED - if defined, linked commands are supported. |
207 | * | 215 | * |
@@ -210,18 +218,18 @@ | |||
210 | * SUPPORT_TAGS - if defined, SCSI-2 tagged queuing is used where possible | 218 | * SUPPORT_TAGS - if defined, SCSI-2 tagged queuing is used where possible |
211 | * | 219 | * |
212 | * These macros MUST be defined : | 220 | * These macros MUST be defined : |
213 | * | 221 | * |
214 | * NCR5380_read(register) - read from the specified register | 222 | * NCR5380_read(register) - read from the specified register |
215 | * | 223 | * |
216 | * NCR5380_write(register, value) - write to the specific register | 224 | * NCR5380_write(register, value) - write to the specific register |
217 | * | 225 | * |
218 | * Either real DMA *or* pseudo DMA may be implemented | 226 | * Either real DMA *or* pseudo DMA may be implemented |
219 | * REAL functions : | 227 | * REAL functions : |
220 | * NCR5380_REAL_DMA should be defined if real DMA is to be used. | 228 | * NCR5380_REAL_DMA should be defined if real DMA is to be used. |
221 | * Note that the DMA setup functions should return the number of bytes | 229 | * Note that the DMA setup functions should return the number of bytes |
222 | * that they were able to program the controller for. | 230 | * that they were able to program the controller for. |
223 | * | 231 | * |
224 | * Also note that generic i386/PC versions of these macros are | 232 | * Also note that generic i386/PC versions of these macros are |
225 | * available as NCR5380_i386_dma_write_setup, | 233 | * available as NCR5380_i386_dma_write_setup, |
226 | * NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual. | 234 | * NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual. |
227 | * | 235 | * |
@@ -234,14 +242,14 @@ | |||
234 | * NCR5380_pread(instance, dst, count); | 242 | * NCR5380_pread(instance, dst, count); |
235 | * | 243 | * |
236 | * If nothing specific to this implementation needs doing (ie, with external | 244 | * If nothing specific to this implementation needs doing (ie, with external |
237 | * hardware), you must also define | 245 | * hardware), you must also define |
238 | * | 246 | * |
239 | * NCR5380_queue_command | 247 | * NCR5380_queue_command |
240 | * NCR5380_reset | 248 | * NCR5380_reset |
241 | * NCR5380_abort | 249 | * NCR5380_abort |
242 | * NCR5380_proc_info | 250 | * NCR5380_proc_info |
243 | * | 251 | * |
244 | * to be the global entry points into the specific driver, ie | 252 | * to be the global entry points into the specific driver, ie |
245 | * #define NCR5380_queue_command t128_queue_command. | 253 | * #define NCR5380_queue_command t128_queue_command. |
246 | * | 254 | * |
247 | * If this is not done, the routines will be defined as static functions | 255 | * If this is not done, the routines will be defined as static functions |
@@ -249,7 +257,7 @@ | |||
249 | * accessible wrapper function. | 257 | * accessible wrapper function. |
250 | * | 258 | * |
251 | * The generic driver is initialized by calling NCR5380_init(instance), | 259 | * The generic driver is initialized by calling NCR5380_init(instance), |
252 | * after setting the appropriate host specific fields and ID. If the | 260 | * after setting the appropriate host specific fields and ID. If the |
253 | * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance, | 261 | * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance, |
254 | * possible) function may be used. Before the specific driver initialization | 262 | * possible) function may be used. Before the specific driver initialization |
255 | * code finishes, NCR5380_print_options should be called. | 263 | * code finishes, NCR5380_print_options should be called. |
@@ -264,8 +272,9 @@ static struct scsi_host_template *the_template = NULL; | |||
264 | (struct NCR5380_hostdata *)(in)->hostdata | 272 | (struct NCR5380_hostdata *)(in)->hostdata |
265 | #define HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata) | 273 | #define HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata) |
266 | 274 | ||
267 | #define NEXT(cmd) ((Scsi_Cmnd *)((cmd)->host_scribble)) | 275 | #define NEXT(cmd) ((Scsi_Cmnd *)(cmd)->host_scribble) |
268 | #define NEXTADDR(cmd) ((Scsi_Cmnd **)&((cmd)->host_scribble)) | 276 | #define SET_NEXT(cmd,next) ((cmd)->host_scribble = (void *)(next)) |
277 | #define NEXTADDR(cmd) ((Scsi_Cmnd **)&(cmd)->host_scribble) | ||
269 | 278 | ||
270 | #define HOSTNO instance->host_no | 279 | #define HOSTNO instance->host_no |
271 | #define H_NO(cmd) (cmd)->device->host->host_no | 280 | #define H_NO(cmd) (cmd)->device->host->host_no |
@@ -312,34 +321,34 @@ static struct scsi_host_template *the_template = NULL; | |||
312 | #define TAG_NONE 0xff | 321 | #define TAG_NONE 0xff |
313 | 322 | ||
314 | typedef struct { | 323 | typedef struct { |
315 | DECLARE_BITMAP(allocated, MAX_TAGS); | 324 | DECLARE_BITMAP(allocated, MAX_TAGS); |
316 | int nr_allocated; | 325 | int nr_allocated; |
317 | int queue_size; | 326 | int queue_size; |
318 | } TAG_ALLOC; | 327 | } TAG_ALLOC; |
319 | 328 | ||
320 | static TAG_ALLOC TagAlloc[8][8]; /* 8 targets and 8 LUNs */ | 329 | static TAG_ALLOC TagAlloc[8][8]; /* 8 targets and 8 LUNs */ |
321 | 330 | ||
322 | 331 | ||
323 | static void __init init_tags( void ) | 332 | static void __init init_tags(void) |
324 | { | 333 | { |
325 | int target, lun; | 334 | int target, lun; |
326 | TAG_ALLOC *ta; | 335 | TAG_ALLOC *ta; |
327 | 336 | ||
328 | if (!setup_use_tagged_queuing) | 337 | if (!setup_use_tagged_queuing) |
329 | return; | 338 | return; |
330 | 339 | ||
331 | for( target = 0; target < 8; ++target ) { | 340 | for (target = 0; target < 8; ++target) { |
332 | for( lun = 0; lun < 8; ++lun ) { | 341 | for (lun = 0; lun < 8; ++lun) { |
333 | ta = &TagAlloc[target][lun]; | 342 | ta = &TagAlloc[target][lun]; |
334 | bitmap_zero(ta->allocated, MAX_TAGS); | 343 | bitmap_zero(ta->allocated, MAX_TAGS); |
335 | ta->nr_allocated = 0; | 344 | ta->nr_allocated = 0; |
336 | /* At the beginning, assume the maximum queue size we could | 345 | /* At the beginning, assume the maximum queue size we could |
337 | * support (MAX_TAGS). This value will be decreased if the target | 346 | * support (MAX_TAGS). This value will be decreased if the target |
338 | * returns QUEUE_FULL status. | 347 | * returns QUEUE_FULL status. |
339 | */ | 348 | */ |
340 | ta->queue_size = MAX_TAGS; | 349 | ta->queue_size = MAX_TAGS; |
350 | } | ||
341 | } | 351 | } |
342 | } | ||
343 | } | 352 | } |
344 | 353 | ||
345 | 354 | ||
@@ -348,24 +357,24 @@ static void __init init_tags( void ) | |||
348 | * check that there is a free tag and the target's queue won't overflow. This | 357 | * check that there is a free tag and the target's queue won't overflow. This |
349 | * function should be called with interrupts disabled to avoid race | 358 | * function should be called with interrupts disabled to avoid race |
350 | * conditions. | 359 | * conditions. |
351 | */ | 360 | */ |
352 | 361 | ||
353 | static int is_lun_busy( Scsi_Cmnd *cmd, int should_be_tagged ) | 362 | static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged) |
354 | { | 363 | { |
355 | SETUP_HOSTDATA(cmd->device->host); | 364 | SETUP_HOSTDATA(cmd->device->host); |
356 | 365 | ||
357 | if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun)) | 366 | if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun)) |
358 | return( 1 ); | 367 | return 1; |
359 | if (!should_be_tagged || | 368 | if (!should_be_tagged || |
360 | !setup_use_tagged_queuing || !cmd->device->tagged_supported) | 369 | !setup_use_tagged_queuing || !cmd->device->tagged_supported) |
361 | return( 0 ); | 370 | return 0; |
362 | if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >= | 371 | if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >= |
363 | TagAlloc[cmd->device->id][cmd->device->lun].queue_size ) { | 372 | TagAlloc[cmd->device->id][cmd->device->lun].queue_size) { |
364 | TAG_PRINTK( "scsi%d: target %d lun %d: no free tags\n", | 373 | TAG_PRINTK("scsi%d: target %d lun %d: no free tags\n", |
365 | H_NO(cmd), cmd->device->id, cmd->device->lun ); | 374 | H_NO(cmd), cmd->device->id, cmd->device->lun); |
366 | return( 1 ); | 375 | return 1; |
367 | } | 376 | } |
368 | return( 0 ); | 377 | return 0; |
369 | } | 378 | } |
370 | 379 | ||
371 | 380 | ||
@@ -374,31 +383,30 @@ static int is_lun_busy( Scsi_Cmnd *cmd, int should_be_tagged ) | |||
374 | * untagged. | 383 | * untagged. |
375 | */ | 384 | */ |
376 | 385 | ||
377 | static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged ) | 386 | static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged) |
378 | { | 387 | { |
379 | SETUP_HOSTDATA(cmd->device->host); | 388 | SETUP_HOSTDATA(cmd->device->host); |
380 | 389 | ||
381 | /* If we or the target don't support tagged queuing, allocate the LUN for | 390 | /* If we or the target don't support tagged queuing, allocate the LUN for |
382 | * an untagged command. | 391 | * an untagged command. |
383 | */ | 392 | */ |
384 | if (!should_be_tagged || | 393 | if (!should_be_tagged || |
385 | !setup_use_tagged_queuing || !cmd->device->tagged_supported) { | 394 | !setup_use_tagged_queuing || !cmd->device->tagged_supported) { |
386 | cmd->tag = TAG_NONE; | 395 | cmd->tag = TAG_NONE; |
387 | hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); | 396 | hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); |
388 | TAG_PRINTK( "scsi%d: target %d lun %d now allocated by untagged " | 397 | TAG_PRINTK("scsi%d: target %d lun %d now allocated by untagged " |
389 | "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun ); | 398 | "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun); |
390 | } | 399 | } else { |
391 | else { | 400 | TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; |
392 | TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; | 401 | |
393 | 402 | cmd->tag = find_first_zero_bit(ta->allocated, MAX_TAGS); | |
394 | cmd->tag = find_first_zero_bit( ta->allocated, MAX_TAGS ); | 403 | set_bit(cmd->tag, ta->allocated); |
395 | set_bit( cmd->tag, ta->allocated ); | 404 | ta->nr_allocated++; |
396 | ta->nr_allocated++; | 405 | TAG_PRINTK("scsi%d: using tag %d for target %d lun %d " |
397 | TAG_PRINTK( "scsi%d: using tag %d for target %d lun %d " | 406 | "(now %d tags in use)\n", |
398 | "(now %d tags in use)\n", | 407 | H_NO(cmd), cmd->tag, cmd->device->id, |
399 | H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun, | 408 | cmd->device->lun, ta->nr_allocated); |
400 | ta->nr_allocated ); | 409 | } |
401 | } | ||
402 | } | 410 | } |
403 | 411 | ||
404 | 412 | ||
@@ -406,44 +414,42 @@ static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged ) | |||
406 | * unlock the LUN. | 414 | * unlock the LUN. |
407 | */ | 415 | */ |
408 | 416 | ||
409 | static void cmd_free_tag( Scsi_Cmnd *cmd ) | 417 | static void cmd_free_tag(Scsi_Cmnd *cmd) |
410 | { | 418 | { |
411 | SETUP_HOSTDATA(cmd->device->host); | 419 | SETUP_HOSTDATA(cmd->device->host); |
412 | 420 | ||
413 | if (cmd->tag == TAG_NONE) { | 421 | if (cmd->tag == TAG_NONE) { |
414 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); | 422 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); |
415 | TAG_PRINTK( "scsi%d: target %d lun %d untagged cmd finished\n", | 423 | TAG_PRINTK("scsi%d: target %d lun %d untagged cmd finished\n", |
416 | H_NO(cmd), cmd->device->id, cmd->device->lun ); | 424 | H_NO(cmd), cmd->device->id, cmd->device->lun); |
417 | } | 425 | } else if (cmd->tag >= MAX_TAGS) { |
418 | else if (cmd->tag >= MAX_TAGS) { | 426 | printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n", |
419 | printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n", | 427 | H_NO(cmd), cmd->tag); |
420 | H_NO(cmd), cmd->tag ); | 428 | } else { |
421 | } | 429 | TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; |
422 | else { | 430 | clear_bit(cmd->tag, ta->allocated); |
423 | TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; | 431 | ta->nr_allocated--; |
424 | clear_bit( cmd->tag, ta->allocated ); | 432 | TAG_PRINTK("scsi%d: freed tag %d for target %d lun %d\n", |
425 | ta->nr_allocated--; | 433 | H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun); |
426 | TAG_PRINTK( "scsi%d: freed tag %d for target %d lun %d\n", | 434 | } |
427 | H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun ); | ||
428 | } | ||
429 | } | 435 | } |
430 | 436 | ||
431 | 437 | ||
432 | static void free_all_tags( void ) | 438 | static void free_all_tags(void) |
433 | { | 439 | { |
434 | int target, lun; | 440 | int target, lun; |
435 | TAG_ALLOC *ta; | 441 | TAG_ALLOC *ta; |
436 | 442 | ||
437 | if (!setup_use_tagged_queuing) | 443 | if (!setup_use_tagged_queuing) |
438 | return; | 444 | return; |
439 | 445 | ||
440 | for( target = 0; target < 8; ++target ) { | 446 | for (target = 0; target < 8; ++target) { |
441 | for( lun = 0; lun < 8; ++lun ) { | 447 | for (lun = 0; lun < 8; ++lun) { |
442 | ta = &TagAlloc[target][lun]; | 448 | ta = &TagAlloc[target][lun]; |
443 | bitmap_zero(ta->allocated, MAX_TAGS); | 449 | bitmap_zero(ta->allocated, MAX_TAGS); |
444 | ta->nr_allocated = 0; | 450 | ta->nr_allocated = 0; |
451 | } | ||
445 | } | 452 | } |
446 | } | ||
447 | } | 453 | } |
448 | 454 | ||
449 | #endif /* SUPPORT_TAGS */ | 455 | #endif /* SUPPORT_TAGS */ |
@@ -461,89 +467,94 @@ static void free_all_tags( void ) | |||
461 | * assumed to be already transfered into ptr/this_residual. | 467 | * assumed to be already transfered into ptr/this_residual. |
462 | */ | 468 | */ |
463 | 469 | ||
464 | static void merge_contiguous_buffers( Scsi_Cmnd *cmd ) | 470 | static void merge_contiguous_buffers(Scsi_Cmnd *cmd) |
465 | { | 471 | { |
466 | unsigned long endaddr; | 472 | unsigned long endaddr; |
467 | #if (NDEBUG & NDEBUG_MERGING) | 473 | #if (NDEBUG & NDEBUG_MERGING) |
468 | unsigned long oldlen = cmd->SCp.this_residual; | 474 | unsigned long oldlen = cmd->SCp.this_residual; |
469 | int cnt = 1; | 475 | int cnt = 1; |
470 | #endif | 476 | #endif |
471 | 477 | ||
472 | for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1; | 478 | for (endaddr = virt_to_phys(cmd->SCp.ptr + cmd->SCp.this_residual - 1) + 1; |
473 | cmd->SCp.buffers_residual && | 479 | cmd->SCp.buffers_residual && |
474 | virt_to_phys(page_address(cmd->SCp.buffer[1].page)+ | 480 | virt_to_phys(page_address(cmd->SCp.buffer[1].page) + |
475 | cmd->SCp.buffer[1].offset) == endaddr; ) { | 481 | cmd->SCp.buffer[1].offset) == endaddr;) { |
476 | MER_PRINTK("VTOP(%p) == %08lx -> merging\n", | 482 | MER_PRINTK("VTOP(%p) == %08lx -> merging\n", |
477 | cmd->SCp.buffer[1].address, endaddr); | 483 | page_address(cmd->SCp.buffer[1].page), endaddr); |
478 | #if (NDEBUG & NDEBUG_MERGING) | 484 | #if (NDEBUG & NDEBUG_MERGING) |
479 | ++cnt; | 485 | ++cnt; |
480 | #endif | 486 | #endif |
481 | ++cmd->SCp.buffer; | 487 | ++cmd->SCp.buffer; |
482 | --cmd->SCp.buffers_residual; | 488 | --cmd->SCp.buffers_residual; |
483 | cmd->SCp.this_residual += cmd->SCp.buffer->length; | 489 | cmd->SCp.this_residual += cmd->SCp.buffer->length; |
484 | endaddr += cmd->SCp.buffer->length; | 490 | endaddr += cmd->SCp.buffer->length; |
485 | } | 491 | } |
486 | #if (NDEBUG & NDEBUG_MERGING) | 492 | #if (NDEBUG & NDEBUG_MERGING) |
487 | if (oldlen != cmd->SCp.this_residual) | 493 | if (oldlen != cmd->SCp.this_residual) |
488 | MER_PRINTK("merged %d buffers from %p, new length %08x\n", | 494 | MER_PRINTK("merged %d buffers from %p, new length %08x\n", |
489 | cnt, cmd->SCp.ptr, cmd->SCp.this_residual); | 495 | cnt, cmd->SCp.ptr, cmd->SCp.this_residual); |
490 | #endif | 496 | #endif |
491 | } | 497 | } |
492 | 498 | ||
493 | /* | 499 | /* |
494 | * Function : void initialize_SCp(Scsi_Cmnd *cmd) | 500 | * Function : void initialize_SCp(Scsi_Cmnd *cmd) |
495 | * | 501 | * |
496 | * Purpose : initialize the saved data pointers for cmd to point to the | 502 | * Purpose : initialize the saved data pointers for cmd to point to the |
497 | * start of the buffer. | 503 | * start of the buffer. |
498 | * | 504 | * |
499 | * Inputs : cmd - Scsi_Cmnd structure to have pointers reset. | 505 | * Inputs : cmd - Scsi_Cmnd structure to have pointers reset. |
500 | */ | 506 | */ |
501 | 507 | ||
502 | static __inline__ void initialize_SCp(Scsi_Cmnd *cmd) | 508 | static inline void initialize_SCp(Scsi_Cmnd *cmd) |
503 | { | 509 | { |
504 | /* | 510 | /* |
505 | * Initialize the Scsi Pointer field so that all of the commands in the | 511 | * Initialize the Scsi Pointer field so that all of the commands in the |
506 | * various queues are valid. | 512 | * various queues are valid. |
507 | */ | ||
508 | |||
509 | if (cmd->use_sg) { | ||
510 | cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer; | ||
511 | cmd->SCp.buffers_residual = cmd->use_sg - 1; | ||
512 | cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page)+ | ||
513 | cmd->SCp.buffer->offset; | ||
514 | cmd->SCp.this_residual = cmd->SCp.buffer->length; | ||
515 | /* ++roman: Try to merge some scatter-buffers if they are at | ||
516 | * contiguous physical addresses. | ||
517 | */ | 513 | */ |
518 | merge_contiguous_buffers( cmd ); | 514 | |
519 | } else { | 515 | if (cmd->use_sg) { |
520 | cmd->SCp.buffer = NULL; | 516 | cmd->SCp.buffer = (struct scatterlist *)cmd->request_buffer; |
521 | cmd->SCp.buffers_residual = 0; | 517 | cmd->SCp.buffers_residual = cmd->use_sg - 1; |
522 | cmd->SCp.ptr = (char *) cmd->request_buffer; | 518 | cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page) + |
523 | cmd->SCp.this_residual = cmd->request_bufflen; | 519 | cmd->SCp.buffer->offset; |
524 | } | 520 | cmd->SCp.this_residual = cmd->SCp.buffer->length; |
521 | /* ++roman: Try to merge some scatter-buffers if they are at | ||
522 | * contiguous physical addresses. | ||
523 | */ | ||
524 | merge_contiguous_buffers(cmd); | ||
525 | } else { | ||
526 | cmd->SCp.buffer = NULL; | ||
527 | cmd->SCp.buffers_residual = 0; | ||
528 | cmd->SCp.ptr = (char *)cmd->request_buffer; | ||
529 | cmd->SCp.this_residual = cmd->request_bufflen; | ||
530 | } | ||
525 | } | 531 | } |
526 | 532 | ||
527 | #include <linux/delay.h> | 533 | #include <linux/delay.h> |
528 | 534 | ||
529 | #if NDEBUG | 535 | #if NDEBUG |
530 | static struct { | 536 | static struct { |
531 | unsigned char mask; | 537 | unsigned char mask; |
532 | const char * name;} | 538 | const char *name; |
533 | signals[] = {{ SR_DBP, "PARITY"}, { SR_RST, "RST" }, { SR_BSY, "BSY" }, | 539 | } signals[] = { |
534 | { SR_REQ, "REQ" }, { SR_MSG, "MSG" }, { SR_CD, "CD" }, { SR_IO, "IO" }, | 540 | { SR_DBP, "PARITY"}, { SR_RST, "RST" }, { SR_BSY, "BSY" }, |
535 | { SR_SEL, "SEL" }, {0, NULL}}, | 541 | { SR_REQ, "REQ" }, { SR_MSG, "MSG" }, { SR_CD, "CD" }, { SR_IO, "IO" }, |
536 | basrs[] = {{BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL}}, | 542 | { SR_SEL, "SEL" }, {0, NULL} |
537 | icrs[] = {{ICR_ASSERT_RST, "ASSERT RST"},{ICR_ASSERT_ACK, "ASSERT ACK"}, | 543 | }, basrs[] = { |
538 | {ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"}, | 544 | {BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL} |
539 | {ICR_ASSERT_ATN, "ASSERT ATN"}, {ICR_ASSERT_DATA, "ASSERT DATA"}, | 545 | }, icrs[] = { |
540 | {0, NULL}}, | 546 | {ICR_ASSERT_RST, "ASSERT RST"},{ICR_ASSERT_ACK, "ASSERT ACK"}, |
541 | mrs[] = {{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"}, | 547 | {ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"}, |
542 | {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR, | 548 | {ICR_ASSERT_ATN, "ASSERT ATN"}, {ICR_ASSERT_DATA, "ASSERT DATA"}, |
543 | "MODE PARITY INTR"}, {MR_ENABLE_EOP_INTR,"MODE EOP INTR"}, | 549 | {0, NULL} |
544 | {MR_MONITOR_BSY, "MODE MONITOR BSY"}, | 550 | }, mrs[] = { |
545 | {MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"}, | 551 | {MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"}, |
546 | {0, NULL}}; | 552 | {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR, |
553 | "MODE PARITY INTR"}, {MR_ENABLE_EOP_INTR,"MODE EOP INTR"}, | ||
554 | {MR_MONITOR_BSY, "MODE MONITOR BSY"}, | ||
555 | {MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"}, | ||
556 | {0, NULL} | ||
557 | }; | ||
547 | 558 | ||
548 | /* | 559 | /* |
549 | * Function : void NCR5380_print(struct Scsi_Host *instance) | 560 | * Function : void NCR5380_print(struct Scsi_Host *instance) |
@@ -553,45 +564,47 @@ mrs[] = {{MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"}, | |||
553 | * Input : instance - which NCR5380 | 564 | * Input : instance - which NCR5380 |
554 | */ | 565 | */ |
555 | 566 | ||
556 | static void NCR5380_print(struct Scsi_Host *instance) { | 567 | static void NCR5380_print(struct Scsi_Host *instance) |
557 | unsigned char status, data, basr, mr, icr, i; | 568 | { |
558 | unsigned long flags; | 569 | unsigned char status, data, basr, mr, icr, i; |
559 | 570 | unsigned long flags; | |
560 | local_irq_save(flags); | 571 | |
561 | data = NCR5380_read(CURRENT_SCSI_DATA_REG); | 572 | local_irq_save(flags); |
562 | status = NCR5380_read(STATUS_REG); | 573 | data = NCR5380_read(CURRENT_SCSI_DATA_REG); |
563 | mr = NCR5380_read(MODE_REG); | 574 | status = NCR5380_read(STATUS_REG); |
564 | icr = NCR5380_read(INITIATOR_COMMAND_REG); | 575 | mr = NCR5380_read(MODE_REG); |
565 | basr = NCR5380_read(BUS_AND_STATUS_REG); | 576 | icr = NCR5380_read(INITIATOR_COMMAND_REG); |
566 | local_irq_restore(flags); | 577 | basr = NCR5380_read(BUS_AND_STATUS_REG); |
567 | printk("STATUS_REG: %02x ", status); | 578 | local_irq_restore(flags); |
568 | for (i = 0; signals[i].mask ; ++i) | 579 | printk("STATUS_REG: %02x ", status); |
569 | if (status & signals[i].mask) | 580 | for (i = 0; signals[i].mask; ++i) |
570 | printk(",%s", signals[i].name); | 581 | if (status & signals[i].mask) |
571 | printk("\nBASR: %02x ", basr); | 582 | printk(",%s", signals[i].name); |
572 | for (i = 0; basrs[i].mask ; ++i) | 583 | printk("\nBASR: %02x ", basr); |
573 | if (basr & basrs[i].mask) | 584 | for (i = 0; basrs[i].mask; ++i) |
574 | printk(",%s", basrs[i].name); | 585 | if (basr & basrs[i].mask) |
575 | printk("\nICR: %02x ", icr); | 586 | printk(",%s", basrs[i].name); |
576 | for (i = 0; icrs[i].mask; ++i) | 587 | printk("\nICR: %02x ", icr); |
577 | if (icr & icrs[i].mask) | 588 | for (i = 0; icrs[i].mask; ++i) |
578 | printk(",%s", icrs[i].name); | 589 | if (icr & icrs[i].mask) |
579 | printk("\nMODE: %02x ", mr); | 590 | printk(",%s", icrs[i].name); |
580 | for (i = 0; mrs[i].mask; ++i) | 591 | printk("\nMODE: %02x ", mr); |
581 | if (mr & mrs[i].mask) | 592 | for (i = 0; mrs[i].mask; ++i) |
582 | printk(",%s", mrs[i].name); | 593 | if (mr & mrs[i].mask) |
583 | printk("\n"); | 594 | printk(",%s", mrs[i].name); |
595 | printk("\n"); | ||
584 | } | 596 | } |
585 | 597 | ||
586 | static struct { | 598 | static struct { |
587 | unsigned char value; | 599 | unsigned char value; |
588 | const char *name; | 600 | const char *name; |
589 | } phases[] = { | 601 | } phases[] = { |
590 | {PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"}, | 602 | {PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"}, |
591 | {PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"}, | 603 | {PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"}, |
592 | {PHASE_UNKNOWN, "UNKNOWN"}}; | 604 | {PHASE_UNKNOWN, "UNKNOWN"} |
605 | }; | ||
593 | 606 | ||
594 | /* | 607 | /* |
595 | * Function : void NCR5380_print_phase(struct Scsi_Host *instance) | 608 | * Function : void NCR5380_print_phase(struct Scsi_Host *instance) |
596 | * | 609 | * |
597 | * Purpose : print the current SCSI phase for debugging purposes | 610 | * Purpose : print the current SCSI phase for debugging purposes |
@@ -601,30 +614,35 @@ static struct { | |||
601 | 614 | ||
602 | static void NCR5380_print_phase(struct Scsi_Host *instance) | 615 | static void NCR5380_print_phase(struct Scsi_Host *instance) |
603 | { | 616 | { |
604 | unsigned char status; | 617 | unsigned char status; |
605 | int i; | 618 | int i; |
606 | 619 | ||
607 | status = NCR5380_read(STATUS_REG); | 620 | status = NCR5380_read(STATUS_REG); |
608 | if (!(status & SR_REQ)) | 621 | if (!(status & SR_REQ)) |
609 | printk(KERN_DEBUG "scsi%d: REQ not asserted, phase unknown.\n", HOSTNO); | 622 | printk(KERN_DEBUG "scsi%d: REQ not asserted, phase unknown.\n", HOSTNO); |
610 | else { | 623 | else { |
611 | for (i = 0; (phases[i].value != PHASE_UNKNOWN) && | 624 | for (i = 0; (phases[i].value != PHASE_UNKNOWN) && |
612 | (phases[i].value != (status & PHASE_MASK)); ++i); | 625 | (phases[i].value != (status & PHASE_MASK)); ++i) |
613 | printk(KERN_DEBUG "scsi%d: phase %s\n", HOSTNO, phases[i].name); | 626 | ; |
614 | } | 627 | printk(KERN_DEBUG "scsi%d: phase %s\n", HOSTNO, phases[i].name); |
628 | } | ||
615 | } | 629 | } |
616 | 630 | ||
617 | #else /* !NDEBUG */ | 631 | #else /* !NDEBUG */ |
618 | 632 | ||
619 | /* dummies... */ | 633 | /* dummies... */ |
620 | __inline__ void NCR5380_print(struct Scsi_Host *instance) { }; | 634 | static inline void NCR5380_print(struct Scsi_Host *instance) |
621 | __inline__ void NCR5380_print_phase(struct Scsi_Host *instance) { }; | 635 | { |
636 | }; | ||
637 | static inline void NCR5380_print_phase(struct Scsi_Host *instance) | ||
638 | { | ||
639 | }; | ||
622 | 640 | ||
623 | #endif | 641 | #endif |
624 | 642 | ||
625 | /* | 643 | /* |
626 | * ++roman: New scheme of calling NCR5380_main() | 644 | * ++roman: New scheme of calling NCR5380_main() |
627 | * | 645 | * |
628 | * If we're not in an interrupt, we can call our main directly, it cannot be | 646 | * If we're not in an interrupt, we can call our main directly, it cannot be |
629 | * already running. Else, we queue it on a task queue, if not 'main_running' | 647 | * already running. Else, we queue it on a task queue, if not 'main_running' |
630 | * tells us that a lower level is already executing it. This way, | 648 | * tells us that a lower level is already executing it. This way, |
@@ -638,33 +656,33 @@ __inline__ void NCR5380_print_phase(struct Scsi_Host *instance) { }; | |||
638 | #include <linux/workqueue.h> | 656 | #include <linux/workqueue.h> |
639 | #include <linux/interrupt.h> | 657 | #include <linux/interrupt.h> |
640 | 658 | ||
641 | static volatile int main_running = 0; | 659 | static volatile int main_running; |
642 | static DECLARE_WORK(NCR5380_tqueue, (void (*)(void*))NCR5380_main, NULL); | 660 | static DECLARE_WORK(NCR5380_tqueue, NCR5380_main); |
643 | 661 | ||
644 | static __inline__ void queue_main(void) | 662 | static inline void queue_main(void) |
645 | { | 663 | { |
646 | if (!main_running) { | 664 | if (!main_running) { |
647 | /* If in interrupt and NCR5380_main() not already running, | 665 | /* If in interrupt and NCR5380_main() not already running, |
648 | queue it on the 'immediate' task queue, to be processed | 666 | queue it on the 'immediate' task queue, to be processed |
649 | immediately after the current interrupt processing has | 667 | immediately after the current interrupt processing has |
650 | finished. */ | 668 | finished. */ |
651 | schedule_work(&NCR5380_tqueue); | 669 | schedule_work(&NCR5380_tqueue); |
652 | } | 670 | } |
653 | /* else: nothing to do: the running NCR5380_main() will pick up | 671 | /* else: nothing to do: the running NCR5380_main() will pick up |
654 | any newly queued command. */ | 672 | any newly queued command. */ |
655 | } | 673 | } |
656 | 674 | ||
657 | 675 | ||
658 | static inline void NCR5380_all_init (void) | 676 | static inline void NCR5380_all_init(void) |
659 | { | 677 | { |
660 | static int done = 0; | 678 | static int done = 0; |
661 | if (!done) { | 679 | if (!done) { |
662 | INI_PRINTK("scsi : NCR5380_all_init()\n"); | 680 | INI_PRINTK("scsi : NCR5380_all_init()\n"); |
663 | done = 1; | 681 | done = 1; |
664 | } | 682 | } |
665 | } | 683 | } |
666 | 684 | ||
667 | 685 | ||
668 | /* | 686 | /* |
669 | * Function : void NCR58380_print_options (struct Scsi_Host *instance) | 687 | * Function : void NCR58380_print_options (struct Scsi_Host *instance) |
670 | * | 688 | * |
@@ -674,23 +692,23 @@ static inline void NCR5380_all_init (void) | |||
674 | * Inputs : instance, pointer to this instance. Unused. | 692 | * Inputs : instance, pointer to this instance. Unused. |
675 | */ | 693 | */ |
676 | 694 | ||
677 | static void __init NCR5380_print_options (struct Scsi_Host *instance) | 695 | static void __init NCR5380_print_options(struct Scsi_Host *instance) |
678 | { | 696 | { |
679 | printk(" generic options" | 697 | printk(" generic options" |
680 | #ifdef AUTOSENSE | 698 | #ifdef AUTOSENSE |
681 | " AUTOSENSE" | 699 | " AUTOSENSE" |
682 | #endif | 700 | #endif |
683 | #ifdef REAL_DMA | 701 | #ifdef REAL_DMA |
684 | " REAL DMA" | 702 | " REAL DMA" |
685 | #endif | 703 | #endif |
686 | #ifdef PARITY | 704 | #ifdef PARITY |
687 | " PARITY" | 705 | " PARITY" |
688 | #endif | 706 | #endif |
689 | #ifdef SUPPORT_TAGS | 707 | #ifdef SUPPORT_TAGS |
690 | " SCSI-2 TAGGED QUEUING" | 708 | " SCSI-2 TAGGED QUEUING" |
691 | #endif | 709 | #endif |
692 | ); | 710 | ); |
693 | printk(" generic release=%d", NCR5380_PUBLIC_RELEASE); | 711 | printk(" generic release=%d", NCR5380_PUBLIC_RELEASE); |
694 | } | 712 | } |
695 | 713 | ||
696 | /* | 714 | /* |
@@ -699,27 +717,27 @@ static void __init NCR5380_print_options (struct Scsi_Host *instance) | |||
699 | * Purpose : print commands in the various queues, called from | 717 | * Purpose : print commands in the various queues, called from |
700 | * NCR5380_abort and NCR5380_debug to aid debugging. | 718 | * NCR5380_abort and NCR5380_debug to aid debugging. |
701 | * | 719 | * |
702 | * Inputs : instance, pointer to this instance. | 720 | * Inputs : instance, pointer to this instance. |
703 | */ | 721 | */ |
704 | 722 | ||
705 | static void NCR5380_print_status (struct Scsi_Host *instance) | 723 | static void NCR5380_print_status(struct Scsi_Host *instance) |
706 | { | 724 | { |
707 | char *pr_bfr; | 725 | char *pr_bfr; |
708 | char *start; | 726 | char *start; |
709 | int len; | 727 | int len; |
710 | 728 | ||
711 | NCR_PRINT(NDEBUG_ANY); | 729 | NCR_PRINT(NDEBUG_ANY); |
712 | NCR_PRINT_PHASE(NDEBUG_ANY); | 730 | NCR_PRINT_PHASE(NDEBUG_ANY); |
713 | 731 | ||
714 | pr_bfr = (char *) __get_free_page(GFP_ATOMIC); | 732 | pr_bfr = (char *)__get_free_page(GFP_ATOMIC); |
715 | if (!pr_bfr) { | 733 | if (!pr_bfr) { |
716 | printk("NCR5380_print_status: no memory for print buffer\n"); | 734 | printk("NCR5380_print_status: no memory for print buffer\n"); |
717 | return; | 735 | return; |
718 | } | 736 | } |
719 | len = NCR5380_proc_info(pr_bfr, &start, 0, PAGE_SIZE, HOSTNO, 0); | 737 | len = NCR5380_proc_info(instance, pr_bfr, &start, 0, PAGE_SIZE, 0); |
720 | pr_bfr[len] = 0; | 738 | pr_bfr[len] = 0; |
721 | printk("\n%s\n", pr_bfr); | 739 | printk("\n%s\n", pr_bfr); |
722 | free_page((unsigned long) pr_bfr); | 740 | free_page((unsigned long)pr_bfr); |
723 | } | 741 | } |
724 | 742 | ||
725 | 743 | ||
@@ -738,443 +756,478 @@ static void NCR5380_print_status (struct Scsi_Host *instance) | |||
738 | */ | 756 | */ |
739 | 757 | ||
740 | #undef SPRINTF | 758 | #undef SPRINTF |
741 | #define SPRINTF(fmt,args...) \ | 759 | #define SPRINTF(fmt,args...) \ |
742 | do { if (pos + strlen(fmt) + 20 /* slop */ < buffer + length) \ | 760 | do { \ |
743 | pos += sprintf(pos, fmt , ## args); } while(0) | 761 | if (pos + strlen(fmt) + 20 /* slop */ < buffer + length) \ |
744 | static | 762 | pos += sprintf(pos, fmt , ## args); \ |
745 | char *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length); | 763 | } while(0) |
746 | 764 | static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length); | |
747 | static | 765 | |
748 | int NCR5380_proc_info (struct Scsi_Host *instance, char *buffer, char **start, off_t offset, | 766 | static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, |
749 | int length, int inout) | 767 | char **start, off_t offset, int length, int inout) |
750 | { | 768 | { |
751 | char *pos = buffer; | 769 | char *pos = buffer; |
752 | struct NCR5380_hostdata *hostdata; | 770 | struct NCR5380_hostdata *hostdata; |
753 | Scsi_Cmnd *ptr; | 771 | Scsi_Cmnd *ptr; |
754 | unsigned long flags; | 772 | unsigned long flags; |
755 | off_t begin = 0; | 773 | off_t begin = 0; |
756 | #define check_offset() \ | 774 | #define check_offset() \ |
757 | do { \ | 775 | do { \ |
758 | if (pos - buffer < offset - begin) { \ | 776 | if (pos - buffer < offset - begin) { \ |
759 | begin += pos - buffer; \ | 777 | begin += pos - buffer; \ |
760 | pos = buffer; \ | 778 | pos = buffer; \ |
761 | } \ | 779 | } \ |
762 | } while (0) | 780 | } while (0) |
763 | 781 | ||
764 | hostdata = (struct NCR5380_hostdata *)instance->hostdata; | 782 | hostdata = (struct NCR5380_hostdata *)instance->hostdata; |
765 | 783 | ||
766 | if (inout) { /* Has data been written to the file ? */ | 784 | if (inout) /* Has data been written to the file ? */ |
767 | return(-ENOSYS); /* Currently this is a no-op */ | 785 | return -ENOSYS; /* Currently this is a no-op */ |
768 | } | 786 | SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE); |
769 | SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE); | ||
770 | check_offset(); | ||
771 | local_irq_save(flags); | ||
772 | SPRINTF("NCR5380: coroutine is%s running.\n", main_running ? "" : "n't"); | ||
773 | check_offset(); | ||
774 | if (!hostdata->connected) | ||
775 | SPRINTF("scsi%d: no currently connected command\n", HOSTNO); | ||
776 | else | ||
777 | pos = lprint_Scsi_Cmnd ((Scsi_Cmnd *) hostdata->connected, | ||
778 | pos, buffer, length); | ||
779 | SPRINTF("scsi%d: issue_queue\n", HOSTNO); | ||
780 | check_offset(); | ||
781 | for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = NEXT(ptr)) { | ||
782 | pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length); | ||
783 | check_offset(); | 787 | check_offset(); |
784 | } | 788 | local_irq_save(flags); |
789 | SPRINTF("NCR5380: coroutine is%s running.\n", | ||
790 | main_running ? "" : "n't"); | ||
791 | check_offset(); | ||
792 | if (!hostdata->connected) | ||
793 | SPRINTF("scsi%d: no currently connected command\n", HOSTNO); | ||
794 | else | ||
795 | pos = lprint_Scsi_Cmnd((Scsi_Cmnd *) hostdata->connected, | ||
796 | pos, buffer, length); | ||
797 | SPRINTF("scsi%d: issue_queue\n", HOSTNO); | ||
798 | check_offset(); | ||
799 | for (ptr = (Scsi_Cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr)) { | ||
800 | pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length); | ||
801 | check_offset(); | ||
802 | } | ||
785 | 803 | ||
786 | SPRINTF("scsi%d: disconnected_queue\n", HOSTNO); | 804 | SPRINTF("scsi%d: disconnected_queue\n", HOSTNO); |
787 | check_offset(); | ||
788 | for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; | ||
789 | ptr = NEXT(ptr)) { | ||
790 | pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length); | ||
791 | check_offset(); | 805 | check_offset(); |
792 | } | 806 | for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; |
807 | ptr = NEXT(ptr)) { | ||
808 | pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length); | ||
809 | check_offset(); | ||
810 | } | ||
793 | 811 | ||
794 | local_irq_restore(flags); | 812 | local_irq_restore(flags); |
795 | *start = buffer + (offset - begin); | 813 | *start = buffer + (offset - begin); |
796 | if (pos - buffer < offset - begin) | 814 | if (pos - buffer < offset - begin) |
797 | return 0; | 815 | return 0; |
798 | else if (pos - buffer - (offset - begin) < length) | 816 | else if (pos - buffer - (offset - begin) < length) |
799 | return pos - buffer - (offset - begin); | 817 | return pos - buffer - (offset - begin); |
800 | return length; | 818 | return length; |
801 | } | 819 | } |
802 | 820 | ||
803 | static char * | 821 | static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int length) |
804 | lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length) | ||
805 | { | 822 | { |
806 | int i, s; | 823 | int i, s; |
807 | unsigned char *command; | 824 | unsigned char *command; |
808 | SPRINTF("scsi%d: destination target %d, lun %d\n", | 825 | SPRINTF("scsi%d: destination target %d, lun %d\n", |
809 | H_NO(cmd), cmd->device->id, cmd->device->lun); | 826 | H_NO(cmd), cmd->device->id, cmd->device->lun); |
810 | SPRINTF(" command = "); | 827 | SPRINTF(" command = "); |
811 | command = cmd->cmnd; | 828 | command = cmd->cmnd; |
812 | SPRINTF("%2d (0x%02x)", command[0], command[0]); | 829 | SPRINTF("%2d (0x%02x)", command[0], command[0]); |
813 | for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i) | 830 | for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i) |
814 | SPRINTF(" %02x", command[i]); | 831 | SPRINTF(" %02x", command[i]); |
815 | SPRINTF("\n"); | 832 | SPRINTF("\n"); |
816 | return pos; | 833 | return pos; |
817 | } | 834 | } |
818 | 835 | ||
819 | 836 | ||
820 | /* | 837 | /* |
821 | * Function : void NCR5380_init (struct Scsi_Host *instance) | 838 | * Function : void NCR5380_init (struct Scsi_Host *instance) |
822 | * | 839 | * |
823 | * Purpose : initializes *instance and corresponding 5380 chip. | 840 | * Purpose : initializes *instance and corresponding 5380 chip. |
824 | * | 841 | * |
825 | * Inputs : instance - instantiation of the 5380 driver. | 842 | * Inputs : instance - instantiation of the 5380 driver. |
826 | * | 843 | * |
827 | * Notes : I assume that the host, hostno, and id bits have been | 844 | * Notes : I assume that the host, hostno, and id bits have been |
828 | * set correctly. I don't care about the irq and other fields. | 845 | * set correctly. I don't care about the irq and other fields. |
829 | * | 846 | * |
830 | */ | 847 | */ |
831 | 848 | ||
832 | static int NCR5380_init (struct Scsi_Host *instance, int flags) | 849 | static int NCR5380_init(struct Scsi_Host *instance, int flags) |
833 | { | 850 | { |
834 | int i; | 851 | int i; |
835 | SETUP_HOSTDATA(instance); | 852 | SETUP_HOSTDATA(instance); |
836 | 853 | ||
837 | NCR5380_all_init(); | 854 | NCR5380_all_init(); |
838 | 855 | ||
839 | hostdata->aborted = 0; | 856 | hostdata->aborted = 0; |
840 | hostdata->id_mask = 1 << instance->this_id; | 857 | hostdata->id_mask = 1 << instance->this_id; |
841 | hostdata->id_higher_mask = 0; | 858 | hostdata->id_higher_mask = 0; |
842 | for (i = hostdata->id_mask; i <= 0x80; i <<= 1) | 859 | for (i = hostdata->id_mask; i <= 0x80; i <<= 1) |
843 | if (i > hostdata->id_mask) | 860 | if (i > hostdata->id_mask) |
844 | hostdata->id_higher_mask |= i; | 861 | hostdata->id_higher_mask |= i; |
845 | for (i = 0; i < 8; ++i) | 862 | for (i = 0; i < 8; ++i) |
846 | hostdata->busy[i] = 0; | 863 | hostdata->busy[i] = 0; |
847 | #ifdef SUPPORT_TAGS | 864 | #ifdef SUPPORT_TAGS |
848 | init_tags(); | 865 | init_tags(); |
849 | #endif | 866 | #endif |
850 | #if defined (REAL_DMA) | 867 | #if defined (REAL_DMA) |
851 | hostdata->dma_len = 0; | 868 | hostdata->dma_len = 0; |
852 | #endif | 869 | #endif |
853 | hostdata->targets_present = 0; | 870 | hostdata->targets_present = 0; |
854 | hostdata->connected = NULL; | 871 | hostdata->connected = NULL; |
855 | hostdata->issue_queue = NULL; | 872 | hostdata->issue_queue = NULL; |
856 | hostdata->disconnected_queue = NULL; | 873 | hostdata->disconnected_queue = NULL; |
857 | hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT; | 874 | hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT; |
858 | 875 | ||
859 | if (!the_template) { | 876 | if (!the_template) { |
860 | the_template = instance->hostt; | 877 | the_template = instance->hostt; |
861 | first_instance = instance; | 878 | first_instance = instance; |
862 | } | 879 | } |
863 | |||
864 | 880 | ||
865 | #ifndef AUTOSENSE | 881 | #ifndef AUTOSENSE |
866 | if ((instance->cmd_per_lun > 1) || (instance->can_queue > 1)) | 882 | if ((instance->cmd_per_lun > 1) || (instance->can_queue > 1)) |
867 | printk("scsi%d: WARNING : support for multiple outstanding commands enabled\n" | 883 | printk("scsi%d: WARNING : support for multiple outstanding commands enabled\n" |
868 | " without AUTOSENSE option, contingent allegiance conditions may\n" | 884 | " without AUTOSENSE option, contingent allegiance conditions may\n" |
869 | " be incorrectly cleared.\n", HOSTNO); | 885 | " be incorrectly cleared.\n", HOSTNO); |
870 | #endif /* def AUTOSENSE */ | 886 | #endif /* def AUTOSENSE */ |
871 | 887 | ||
872 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 888 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
873 | NCR5380_write(MODE_REG, MR_BASE); | 889 | NCR5380_write(MODE_REG, MR_BASE); |
874 | NCR5380_write(TARGET_COMMAND_REG, 0); | 890 | NCR5380_write(TARGET_COMMAND_REG, 0); |
875 | NCR5380_write(SELECT_ENABLE_REG, 0); | 891 | NCR5380_write(SELECT_ENABLE_REG, 0); |
876 | 892 | ||
877 | return 0; | 893 | return 0; |
878 | } | 894 | } |
879 | 895 | ||
880 | /* | 896 | /* |
881 | * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd, | 897 | * our own old-style timeout update |
882 | * void (*done)(Scsi_Cmnd *)) | 898 | */ |
899 | /* | ||
900 | * The strategy is to cause the timer code to call scsi_times_out() | ||
901 | * when the soonest timeout is pending. | ||
902 | * The arguments are used when we are queueing a new command, because | ||
903 | * we do not want to subtract the time used from this time, but when we | ||
904 | * set the timer, we want to take this value into account. | ||
905 | */ | ||
906 | |||
907 | int atari_scsi_update_timeout(Scsi_Cmnd * SCset, int timeout) | ||
908 | { | ||
909 | int rtn; | ||
910 | |||
911 | /* | ||
912 | * We are using the new error handling code to actually register/deregister | ||
913 | * timers for timeout. | ||
914 | */ | ||
915 | |||
916 | if (!timer_pending(&SCset->eh_timeout)) | ||
917 | rtn = 0; | ||
918 | else | ||
919 | rtn = SCset->eh_timeout.expires - jiffies; | ||
920 | |||
921 | if (timeout == 0) { | ||
922 | del_timer(&SCset->eh_timeout); | ||
923 | SCset->eh_timeout.data = (unsigned long)NULL; | ||
924 | SCset->eh_timeout.expires = 0; | ||
925 | } else { | ||
926 | if (SCset->eh_timeout.data != (unsigned long)NULL) | ||
927 | del_timer(&SCset->eh_timeout); | ||
928 | SCset->eh_timeout.data = (unsigned long)SCset; | ||
929 | SCset->eh_timeout.expires = jiffies + timeout; | ||
930 | add_timer(&SCset->eh_timeout); | ||
931 | } | ||
932 | return rtn; | ||
933 | } | ||
934 | |||
935 | /* | ||
936 | * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd, | ||
937 | * void (*done)(Scsi_Cmnd *)) | ||
883 | * | 938 | * |
884 | * Purpose : enqueues a SCSI command | 939 | * Purpose : enqueues a SCSI command |
885 | * | 940 | * |
886 | * Inputs : cmd - SCSI command, done - function called on completion, with | 941 | * Inputs : cmd - SCSI command, done - function called on completion, with |
887 | * a pointer to the command descriptor. | 942 | * a pointer to the command descriptor. |
888 | * | 943 | * |
889 | * Returns : 0 | 944 | * Returns : 0 |
890 | * | 945 | * |
891 | * Side effects : | 946 | * Side effects : |
892 | * cmd is added to the per instance issue_queue, with minor | 947 | * cmd is added to the per instance issue_queue, with minor |
893 | * twiddling done to the host specific fields of cmd. If the | 948 | * twiddling done to the host specific fields of cmd. If the |
894 | * main coroutine is not running, it is restarted. | 949 | * main coroutine is not running, it is restarted. |
895 | * | 950 | * |
896 | */ | 951 | */ |
897 | 952 | ||
898 | static | 953 | static int NCR5380_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) |
899 | int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) | ||
900 | { | 954 | { |
901 | SETUP_HOSTDATA(cmd->device->host); | 955 | SETUP_HOSTDATA(cmd->device->host); |
902 | Scsi_Cmnd *tmp; | 956 | Scsi_Cmnd *tmp; |
903 | int oldto; | 957 | int oldto; |
904 | unsigned long flags; | 958 | unsigned long flags; |
905 | extern int update_timeout(Scsi_Cmnd * SCset, int timeout); | 959 | // extern int update_timeout(Scsi_Cmnd * SCset, int timeout); |
906 | 960 | ||
907 | #if (NDEBUG & NDEBUG_NO_WRITE) | 961 | #if (NDEBUG & NDEBUG_NO_WRITE) |
908 | switch (cmd->cmnd[0]) { | 962 | switch (cmd->cmnd[0]) { |
909 | case WRITE_6: | 963 | case WRITE_6: |
910 | case WRITE_10: | 964 | case WRITE_10: |
911 | printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n", | 965 | printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n", |
912 | H_NO(cmd)); | 966 | H_NO(cmd)); |
913 | cmd->result = (DID_ERROR << 16); | 967 | cmd->result = (DID_ERROR << 16); |
914 | done(cmd); | 968 | done(cmd); |
915 | return 0; | 969 | return 0; |
916 | } | 970 | } |
917 | #endif /* (NDEBUG & NDEBUG_NO_WRITE) */ | 971 | #endif /* (NDEBUG & NDEBUG_NO_WRITE) */ |
918 | 972 | ||
919 | |||
920 | #ifdef NCR5380_STATS | 973 | #ifdef NCR5380_STATS |
921 | # if 0 | 974 | # if 0 |
922 | if (!hostdata->connected && !hostdata->issue_queue && | 975 | if (!hostdata->connected && !hostdata->issue_queue && |
923 | !hostdata->disconnected_queue) { | 976 | !hostdata->disconnected_queue) { |
924 | hostdata->timebase = jiffies; | 977 | hostdata->timebase = jiffies; |
925 | } | 978 | } |
926 | # endif | 979 | # endif |
927 | # ifdef NCR5380_STAT_LIMIT | 980 | # ifdef NCR5380_STAT_LIMIT |
928 | if (cmd->request_bufflen > NCR5380_STAT_LIMIT) | 981 | if (cmd->request_bufflen > NCR5380_STAT_LIMIT) |
929 | # endif | 982 | # endif |
930 | switch (cmd->cmnd[0]) | 983 | switch (cmd->cmnd[0]) { |
931 | { | 984 | case WRITE: |
932 | case WRITE: | 985 | case WRITE_6: |
933 | case WRITE_6: | 986 | case WRITE_10: |
934 | case WRITE_10: | 987 | hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase); |
935 | hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase); | 988 | hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen; |
936 | hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen; | 989 | hostdata->pendingw++; |
937 | hostdata->pendingw++; | 990 | break; |
938 | break; | 991 | case READ: |
939 | case READ: | 992 | case READ_6: |
940 | case READ_6: | 993 | case READ_10: |
941 | case READ_10: | 994 | hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase); |
942 | hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase); | 995 | hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen; |
943 | hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen; | 996 | hostdata->pendingr++; |
944 | hostdata->pendingr++; | 997 | break; |
945 | break; | 998 | } |
946 | } | ||
947 | #endif | 999 | #endif |
948 | 1000 | ||
949 | /* | 1001 | /* |
950 | * We use the host_scribble field as a pointer to the next command | 1002 | * We use the host_scribble field as a pointer to the next command |
951 | * in a queue | 1003 | * in a queue |
952 | */ | 1004 | */ |
953 | 1005 | ||
954 | NEXT(cmd) = NULL; | 1006 | SET_NEXT(cmd, NULL); |
955 | cmd->scsi_done = done; | 1007 | cmd->scsi_done = done; |
956 | 1008 | ||
957 | cmd->result = 0; | 1009 | cmd->result = 0; |
958 | 1010 | ||
959 | 1011 | /* | |
960 | /* | 1012 | * Insert the cmd into the issue queue. Note that REQUEST SENSE |
961 | * Insert the cmd into the issue queue. Note that REQUEST SENSE | 1013 | * commands are added to the head of the queue since any command will |
962 | * commands are added to the head of the queue since any command will | 1014 | * clear the contingent allegiance condition that exists and the |
963 | * clear the contingent allegiance condition that exists and the | 1015 | * sense data is only guaranteed to be valid while the condition exists. |
964 | * sense data is only guaranteed to be valid while the condition exists. | 1016 | */ |
965 | */ | 1017 | |
966 | 1018 | local_irq_save(flags); | |
967 | local_irq_save(flags); | 1019 | /* ++guenther: now that the issue queue is being set up, we can lock ST-DMA. |
968 | /* ++guenther: now that the issue queue is being set up, we can lock ST-DMA. | 1020 | * Otherwise a running NCR5380_main may steal the lock. |
969 | * Otherwise a running NCR5380_main may steal the lock. | 1021 | * Lock before actually inserting due to fairness reasons explained in |
970 | * Lock before actually inserting due to fairness reasons explained in | 1022 | * atari_scsi.c. If we insert first, then it's impossible for this driver |
971 | * atari_scsi.c. If we insert first, then it's impossible for this driver | 1023 | * to release the lock. |
972 | * to release the lock. | 1024 | * Stop timer for this command while waiting for the lock, or timeouts |
973 | * Stop timer for this command while waiting for the lock, or timeouts | 1025 | * may happen (and they really do), and it's no good if the command doesn't |
974 | * may happen (and they really do), and it's no good if the command doesn't | 1026 | * appear in any of the queues. |
975 | * appear in any of the queues. | 1027 | * ++roman: Just disabling the NCR interrupt isn't sufficient here, |
976 | * ++roman: Just disabling the NCR interrupt isn't sufficient here, | 1028 | * because also a timer int can trigger an abort or reset, which would |
977 | * because also a timer int can trigger an abort or reset, which would | 1029 | * alter queues and touch the lock. |
978 | * alter queues and touch the lock. | 1030 | */ |
979 | */ | 1031 | if (!IS_A_TT()) { |
980 | if (!IS_A_TT()) { | 1032 | oldto = atari_scsi_update_timeout(cmd, 0); |
981 | oldto = update_timeout(cmd, 0); | 1033 | falcon_get_lock(); |
982 | falcon_get_lock(); | 1034 | atari_scsi_update_timeout(cmd, oldto); |
983 | update_timeout(cmd, oldto); | 1035 | } |
984 | } | 1036 | if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { |
985 | if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { | 1037 | LIST(cmd, hostdata->issue_queue); |
986 | LIST(cmd, hostdata->issue_queue); | 1038 | SET_NEXT(cmd, hostdata->issue_queue); |
987 | NEXT(cmd) = hostdata->issue_queue; | 1039 | hostdata->issue_queue = cmd; |
988 | hostdata->issue_queue = cmd; | 1040 | } else { |
989 | } else { | 1041 | for (tmp = (Scsi_Cmnd *)hostdata->issue_queue; |
990 | for (tmp = (Scsi_Cmnd *)hostdata->issue_queue; | 1042 | NEXT(tmp); tmp = NEXT(tmp)) |
991 | NEXT(tmp); tmp = NEXT(tmp)) | 1043 | ; |
992 | ; | 1044 | LIST(cmd, tmp); |
993 | LIST(cmd, tmp); | 1045 | SET_NEXT(tmp, cmd); |
994 | NEXT(tmp) = cmd; | 1046 | } |
995 | } | 1047 | local_irq_restore(flags); |
996 | local_irq_restore(flags); | 1048 | |
997 | 1049 | QU_PRINTK("scsi%d: command added to %s of queue\n", H_NO(cmd), | |
998 | QU_PRINTK("scsi%d: command added to %s of queue\n", H_NO(cmd), | 1050 | (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"); |
999 | (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"); | 1051 | |
1000 | 1052 | /* If queue_command() is called from an interrupt (real one or bottom | |
1001 | /* If queue_command() is called from an interrupt (real one or bottom | 1053 | * half), we let queue_main() do the job of taking care about main. If it |
1002 | * half), we let queue_main() do the job of taking care about main. If it | 1054 | * is already running, this is a no-op, else main will be queued. |
1003 | * is already running, this is a no-op, else main will be queued. | 1055 | * |
1004 | * | 1056 | * If we're not in an interrupt, we can call NCR5380_main() |
1005 | * If we're not in an interrupt, we can call NCR5380_main() | 1057 | * unconditionally, because it cannot be already running. |
1006 | * unconditionally, because it cannot be already running. | 1058 | */ |
1007 | */ | 1059 | if (in_interrupt() || ((flags >> 8) & 7) >= 6) |
1008 | if (in_interrupt() || ((flags >> 8) & 7) >= 6) | 1060 | queue_main(); |
1009 | queue_main(); | 1061 | else |
1010 | else | 1062 | NCR5380_main(NULL); |
1011 | NCR5380_main(NULL); | 1063 | return 0; |
1012 | return 0; | ||
1013 | } | 1064 | } |
1014 | 1065 | ||
1015 | /* | 1066 | /* |
1016 | * Function : NCR5380_main (void) | 1067 | * Function : NCR5380_main (void) |
1017 | * | 1068 | * |
1018 | * Purpose : NCR5380_main is a coroutine that runs as long as more work can | 1069 | * Purpose : NCR5380_main is a coroutine that runs as long as more work can |
1019 | * be done on the NCR5380 host adapters in a system. Both | 1070 | * be done on the NCR5380 host adapters in a system. Both |
1020 | * NCR5380_queue_command() and NCR5380_intr() will try to start it | 1071 | * NCR5380_queue_command() and NCR5380_intr() will try to start it |
1021 | * in case it is not running. | 1072 | * in case it is not running. |
1022 | * | 1073 | * |
1023 | * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should | 1074 | * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should |
1024 | * reenable them. This prevents reentrancy and kernel stack overflow. | 1075 | * reenable them. This prevents reentrancy and kernel stack overflow. |
1025 | */ | 1076 | */ |
1026 | 1077 | ||
1027 | static void NCR5380_main (void *bl) | 1078 | static void NCR5380_main(struct work_struct *work) |
1028 | { | 1079 | { |
1029 | Scsi_Cmnd *tmp, *prev; | 1080 | Scsi_Cmnd *tmp, *prev; |
1030 | struct Scsi_Host *instance = first_instance; | 1081 | struct Scsi_Host *instance = first_instance; |
1031 | struct NCR5380_hostdata *hostdata = HOSTDATA(instance); | 1082 | struct NCR5380_hostdata *hostdata = HOSTDATA(instance); |
1032 | int done; | 1083 | int done; |
1033 | unsigned long flags; | 1084 | unsigned long flags; |
1034 | 1085 | ||
1035 | /* | 1086 | /* |
1036 | * We run (with interrupts disabled) until we're sure that none of | 1087 | * We run (with interrupts disabled) until we're sure that none of |
1037 | * the host adapters have anything that can be done, at which point | 1088 | * the host adapters have anything that can be done, at which point |
1038 | * we set main_running to 0 and exit. | 1089 | * we set main_running to 0 and exit. |
1039 | * | 1090 | * |
1040 | * Interrupts are enabled before doing various other internal | 1091 | * Interrupts are enabled before doing various other internal |
1041 | * instructions, after we've decided that we need to run through | 1092 | * instructions, after we've decided that we need to run through |
1042 | * the loop again. | 1093 | * the loop again. |
1043 | * | 1094 | * |
1044 | * this should prevent any race conditions. | 1095 | * this should prevent any race conditions. |
1045 | * | 1096 | * |
1046 | * ++roman: Just disabling the NCR interrupt isn't sufficient here, | 1097 | * ++roman: Just disabling the NCR interrupt isn't sufficient here, |
1047 | * because also a timer int can trigger an abort or reset, which can | 1098 | * because also a timer int can trigger an abort or reset, which can |
1048 | * alter queues and touch the Falcon lock. | 1099 | * alter queues and touch the Falcon lock. |
1049 | */ | 1100 | */ |
1050 | 1101 | ||
1051 | /* Tell int handlers main() is now already executing. Note that | 1102 | /* Tell int handlers main() is now already executing. Note that |
1052 | no races are possible here. If an int comes in before | 1103 | no races are possible here. If an int comes in before |
1053 | 'main_running' is set here, and queues/executes main via the | 1104 | 'main_running' is set here, and queues/executes main via the |
1054 | task queue, it doesn't do any harm, just this instance of main | 1105 | task queue, it doesn't do any harm, just this instance of main |
1055 | won't find any work left to do. */ | 1106 | won't find any work left to do. */ |
1056 | if (main_running) | 1107 | if (main_running) |
1057 | return; | 1108 | return; |
1058 | main_running = 1; | 1109 | main_running = 1; |
1059 | 1110 | ||
1060 | local_save_flags(flags); | 1111 | local_save_flags(flags); |
1061 | do { | 1112 | do { |
1062 | local_irq_disable(); /* Freeze request queues */ | 1113 | local_irq_disable(); /* Freeze request queues */ |
1063 | done = 1; | 1114 | done = 1; |
1064 | 1115 | ||
1065 | if (!hostdata->connected) { | 1116 | if (!hostdata->connected) { |
1066 | MAIN_PRINTK( "scsi%d: not connected\n", HOSTNO ); | 1117 | MAIN_PRINTK("scsi%d: not connected\n", HOSTNO); |
1067 | /* | 1118 | /* |
1068 | * Search through the issue_queue for a command destined | 1119 | * Search through the issue_queue for a command destined |
1069 | * for a target that's not busy. | 1120 | * for a target that's not busy. |
1070 | */ | 1121 | */ |
1071 | #if (NDEBUG & NDEBUG_LISTS) | 1122 | #if (NDEBUG & NDEBUG_LISTS) |
1072 | for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; | 1123 | for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; |
1073 | tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp)) | 1124 | tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp)) |
1074 | ; | 1125 | ; |
1075 | /*printk("%p ", tmp);*/ | 1126 | /*printk("%p ", tmp);*/ |
1076 | if ((tmp == prev) && tmp) printk(" LOOP\n");/* else printk("\n");*/ | 1127 | if ((tmp == prev) && tmp) |
1128 | printk(" LOOP\n"); | ||
1129 | /* else printk("\n"); */ | ||
1077 | #endif | 1130 | #endif |
1078 | for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, | 1131 | for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, |
1079 | prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp) ) { | 1132 | prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp)) { |
1080 | 1133 | ||
1081 | #if (NDEBUG & NDEBUG_LISTS) | 1134 | #if (NDEBUG & NDEBUG_LISTS) |
1082 | if (prev != tmp) | 1135 | if (prev != tmp) |
1083 | printk("MAIN tmp=%p target=%d busy=%d lun=%d\n", | 1136 | printk("MAIN tmp=%p target=%d busy=%d lun=%d\n", |
1084 | tmp, tmp->device->id, hostdata->busy[tmp->device->id], | 1137 | tmp, tmp->device->id, hostdata->busy[tmp->device->id], |
1085 | tmp->device->lun); | 1138 | tmp->device->lun); |
1086 | #endif | 1139 | #endif |
1087 | /* When we find one, remove it from the issue queue. */ | 1140 | /* When we find one, remove it from the issue queue. */ |
1088 | /* ++guenther: possible race with Falcon locking */ | 1141 | /* ++guenther: possible race with Falcon locking */ |
1089 | if ( | 1142 | if ( |
1090 | #ifdef SUPPORT_TAGS | 1143 | #ifdef SUPPORT_TAGS |
1091 | !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE) | 1144 | !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE) |
1092 | #else | 1145 | #else |
1093 | !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun)) | 1146 | !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun)) |
1094 | #endif | 1147 | #endif |
1095 | ) { | 1148 | ) { |
1096 | /* ++guenther: just to be sure, this must be atomic */ | 1149 | /* ++guenther: just to be sure, this must be atomic */ |
1097 | local_irq_disable(); | 1150 | local_irq_disable(); |
1098 | if (prev) { | 1151 | if (prev) { |
1099 | REMOVE(prev, NEXT(prev), tmp, NEXT(tmp)); | 1152 | REMOVE(prev, NEXT(prev), tmp, NEXT(tmp)); |
1100 | NEXT(prev) = NEXT(tmp); | 1153 | SET_NEXT(prev, NEXT(tmp)); |
1101 | } else { | 1154 | } else { |
1102 | REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp)); | 1155 | REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp)); |
1103 | hostdata->issue_queue = NEXT(tmp); | 1156 | hostdata->issue_queue = NEXT(tmp); |
1104 | } | 1157 | } |
1105 | NEXT(tmp) = NULL; | 1158 | SET_NEXT(tmp, NULL); |
1106 | falcon_dont_release++; | 1159 | falcon_dont_release++; |
1107 | 1160 | ||
1108 | /* reenable interrupts after finding one */ | 1161 | /* reenable interrupts after finding one */ |
1109 | local_irq_restore(flags); | 1162 | local_irq_restore(flags); |
1110 | 1163 | ||
1111 | /* | 1164 | /* |
1112 | * Attempt to establish an I_T_L nexus here. | 1165 | * Attempt to establish an I_T_L nexus here. |
1113 | * On success, instance->hostdata->connected is set. | 1166 | * On success, instance->hostdata->connected is set. |
1114 | * On failure, we must add the command back to the | 1167 | * On failure, we must add the command back to the |
1115 | * issue queue so we can keep trying. | 1168 | * issue queue so we can keep trying. |
1116 | */ | 1169 | */ |
1117 | MAIN_PRINTK("scsi%d: main(): command for target %d " | 1170 | MAIN_PRINTK("scsi%d: main(): command for target %d " |
1118 | "lun %d removed from issue_queue\n", | 1171 | "lun %d removed from issue_queue\n", |
1119 | HOSTNO, tmp->device->id, tmp->device->lun); | 1172 | HOSTNO, tmp->device->id, tmp->device->lun); |
1120 | /* | 1173 | /* |
1121 | * REQUEST SENSE commands are issued without tagged | 1174 | * REQUEST SENSE commands are issued without tagged |
1122 | * queueing, even on SCSI-II devices because the | 1175 | * queueing, even on SCSI-II devices because the |
1123 | * contingent allegiance condition exists for the | 1176 | * contingent allegiance condition exists for the |
1124 | * entire unit. | 1177 | * entire unit. |
1125 | */ | 1178 | */ |
1126 | /* ++roman: ...and the standard also requires that | 1179 | /* ++roman: ...and the standard also requires that |
1127 | * REQUEST SENSE command are untagged. | 1180 | * REQUEST SENSE command are untagged. |
1128 | */ | 1181 | */ |
1129 | 1182 | ||
1130 | #ifdef SUPPORT_TAGS | 1183 | #ifdef SUPPORT_TAGS |
1131 | cmd_get_tag( tmp, tmp->cmnd[0] != REQUEST_SENSE ); | 1184 | cmd_get_tag(tmp, tmp->cmnd[0] != REQUEST_SENSE); |
1132 | #endif | 1185 | #endif |
1133 | if (!NCR5380_select(instance, tmp, | 1186 | if (!NCR5380_select(instance, tmp, |
1134 | (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : | 1187 | (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : |
1135 | TAG_NEXT)) { | 1188 | TAG_NEXT)) { |
1136 | falcon_dont_release--; | 1189 | falcon_dont_release--; |
1137 | /* release if target did not response! */ | 1190 | /* release if target did not response! */ |
1138 | falcon_release_lock_if_possible( hostdata ); | 1191 | falcon_release_lock_if_possible(hostdata); |
1139 | break; | 1192 | break; |
1140 | } else { | 1193 | } else { |
1141 | local_irq_disable(); | 1194 | local_irq_disable(); |
1142 | LIST(tmp, hostdata->issue_queue); | 1195 | LIST(tmp, hostdata->issue_queue); |
1143 | NEXT(tmp) = hostdata->issue_queue; | 1196 | SET_NEXT(tmp, hostdata->issue_queue); |
1144 | hostdata->issue_queue = tmp; | 1197 | hostdata->issue_queue = tmp; |
1145 | #ifdef SUPPORT_TAGS | 1198 | #ifdef SUPPORT_TAGS |
1146 | cmd_free_tag( tmp ); | 1199 | cmd_free_tag(tmp); |
1147 | #endif | 1200 | #endif |
1148 | falcon_dont_release--; | 1201 | falcon_dont_release--; |
1149 | local_irq_restore(flags); | 1202 | local_irq_restore(flags); |
1150 | MAIN_PRINTK("scsi%d: main(): select() failed, " | 1203 | MAIN_PRINTK("scsi%d: main(): select() failed, " |
1151 | "returned to issue_queue\n", HOSTNO); | 1204 | "returned to issue_queue\n", HOSTNO); |
1152 | if (hostdata->connected) | 1205 | if (hostdata->connected) |
1153 | break; | 1206 | break; |
1154 | } | 1207 | } |
1155 | } /* if target/lun/target queue is not busy */ | 1208 | } /* if target/lun/target queue is not busy */ |
1156 | } /* for issue_queue */ | 1209 | } /* for issue_queue */ |
1157 | } /* if (!hostdata->connected) */ | 1210 | } /* if (!hostdata->connected) */ |
1158 | 1211 | ||
1159 | if (hostdata->connected | 1212 | if (hostdata->connected |
1160 | #ifdef REAL_DMA | 1213 | #ifdef REAL_DMA |
1161 | && !hostdata->dma_len | 1214 | && !hostdata->dma_len |
1162 | #endif | 1215 | #endif |
1163 | ) { | 1216 | ) { |
1164 | local_irq_restore(flags); | 1217 | local_irq_restore(flags); |
1165 | MAIN_PRINTK("scsi%d: main: performing information transfer\n", | 1218 | MAIN_PRINTK("scsi%d: main: performing information transfer\n", |
1166 | HOSTNO); | 1219 | HOSTNO); |
1167 | NCR5380_information_transfer(instance); | 1220 | NCR5380_information_transfer(instance); |
1168 | MAIN_PRINTK("scsi%d: main: done set false\n", HOSTNO); | 1221 | MAIN_PRINTK("scsi%d: main: done set false\n", HOSTNO); |
1169 | done = 0; | 1222 | done = 0; |
1170 | } | 1223 | } |
1171 | } while (!done); | 1224 | } while (!done); |
1172 | 1225 | ||
1173 | /* Better allow ints _after_ 'main_running' has been cleared, else | 1226 | /* Better allow ints _after_ 'main_running' has been cleared, else |
1174 | an interrupt could believe we'll pick up the work it left for | 1227 | an interrupt could believe we'll pick up the work it left for |
1175 | us, but we won't see it anymore here... */ | 1228 | us, but we won't see it anymore here... */ |
1176 | main_running = 0; | 1229 | main_running = 0; |
1177 | local_irq_restore(flags); | 1230 | local_irq_restore(flags); |
1178 | } | 1231 | } |
1179 | 1232 | ||
1180 | 1233 | ||
@@ -1183,1441 +1236,1439 @@ static void NCR5380_main (void *bl) | |||
1183 | * Function : void NCR5380_dma_complete (struct Scsi_Host *instance) | 1236 | * Function : void NCR5380_dma_complete (struct Scsi_Host *instance) |
1184 | * | 1237 | * |
1185 | * Purpose : Called by interrupt handler when DMA finishes or a phase | 1238 | * Purpose : Called by interrupt handler when DMA finishes or a phase |
1186 | * mismatch occurs (which would finish the DMA transfer). | 1239 | * mismatch occurs (which would finish the DMA transfer). |
1187 | * | 1240 | * |
1188 | * Inputs : instance - this instance of the NCR5380. | 1241 | * Inputs : instance - this instance of the NCR5380. |
1189 | * | 1242 | * |
1190 | */ | 1243 | */ |
1191 | 1244 | ||
1192 | static void NCR5380_dma_complete( struct Scsi_Host *instance ) | 1245 | static void NCR5380_dma_complete(struct Scsi_Host *instance) |
1193 | { | 1246 | { |
1194 | SETUP_HOSTDATA(instance); | 1247 | SETUP_HOSTDATA(instance); |
1195 | int transfered, saved_data = 0, overrun = 0, cnt, toPIO; | 1248 | int transfered, saved_data = 0, overrun = 0, cnt, toPIO; |
1196 | unsigned char **data, p; | 1249 | unsigned char **data, p; |
1197 | volatile int *count; | 1250 | volatile int *count; |
1198 | 1251 | ||
1199 | if (!hostdata->connected) { | 1252 | if (!hostdata->connected) { |
1200 | printk(KERN_WARNING "scsi%d: received end of DMA interrupt with " | 1253 | printk(KERN_WARNING "scsi%d: received end of DMA interrupt with " |
1201 | "no connected cmd\n", HOSTNO); | 1254 | "no connected cmd\n", HOSTNO); |
1202 | return; | 1255 | return; |
1203 | } | ||
1204 | |||
1205 | if (atari_read_overruns) { | ||
1206 | p = hostdata->connected->SCp.phase; | ||
1207 | if (p & SR_IO) { | ||
1208 | udelay(10); | ||
1209 | if ((((NCR5380_read(BUS_AND_STATUS_REG)) & | ||
1210 | (BASR_PHASE_MATCH|BASR_ACK)) == | ||
1211 | (BASR_PHASE_MATCH|BASR_ACK))) { | ||
1212 | saved_data = NCR5380_read(INPUT_DATA_REG); | ||
1213 | overrun = 1; | ||
1214 | DMA_PRINTK("scsi%d: read overrun handled\n", HOSTNO); | ||
1215 | } | ||
1216 | } | 1256 | } |
1217 | } | 1257 | |
1218 | 1258 | if (atari_read_overruns) { | |
1219 | DMA_PRINTK("scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n", | 1259 | p = hostdata->connected->SCp.phase; |
1220 | HOSTNO, NCR5380_read(BUS_AND_STATUS_REG), | 1260 | if (p & SR_IO) { |
1221 | NCR5380_read(STATUS_REG)); | 1261 | udelay(10); |
1222 | 1262 | if ((NCR5380_read(BUS_AND_STATUS_REG) & | |
1223 | (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); | 1263 | (BASR_PHASE_MATCH|BASR_ACK)) == |
1224 | NCR5380_write(MODE_REG, MR_BASE); | 1264 | (BASR_PHASE_MATCH|BASR_ACK)) { |
1225 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 1265 | saved_data = NCR5380_read(INPUT_DATA_REG); |
1226 | 1266 | overrun = 1; | |
1227 | transfered = hostdata->dma_len - NCR5380_dma_residual(instance); | 1267 | DMA_PRINTK("scsi%d: read overrun handled\n", HOSTNO); |
1228 | hostdata->dma_len = 0; | 1268 | } |
1229 | 1269 | } | |
1230 | data = (unsigned char **) &(hostdata->connected->SCp.ptr); | 1270 | } |
1231 | count = &(hostdata->connected->SCp.this_residual); | 1271 | |
1232 | *data += transfered; | 1272 | DMA_PRINTK("scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n", |
1233 | *count -= transfered; | 1273 | HOSTNO, NCR5380_read(BUS_AND_STATUS_REG), |
1234 | 1274 | NCR5380_read(STATUS_REG)); | |
1235 | if (atari_read_overruns) { | 1275 | |
1236 | if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) { | 1276 | (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); |
1237 | cnt = toPIO = atari_read_overruns; | 1277 | NCR5380_write(MODE_REG, MR_BASE); |
1238 | if (overrun) { | 1278 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
1239 | DMA_PRINTK("Got an input overrun, using saved byte\n"); | 1279 | |
1240 | *(*data)++ = saved_data; | 1280 | transfered = hostdata->dma_len - NCR5380_dma_residual(instance); |
1241 | (*count)--; | 1281 | hostdata->dma_len = 0; |
1242 | cnt--; | 1282 | |
1243 | toPIO--; | 1283 | data = (unsigned char **)&hostdata->connected->SCp.ptr; |
1244 | } | 1284 | count = &hostdata->connected->SCp.this_residual; |
1245 | DMA_PRINTK("Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data); | 1285 | *data += transfered; |
1246 | NCR5380_transfer_pio(instance, &p, &cnt, data); | 1286 | *count -= transfered; |
1247 | *count -= toPIO - cnt; | 1287 | |
1288 | if (atari_read_overruns) { | ||
1289 | if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) { | ||
1290 | cnt = toPIO = atari_read_overruns; | ||
1291 | if (overrun) { | ||
1292 | DMA_PRINTK("Got an input overrun, using saved byte\n"); | ||
1293 | *(*data)++ = saved_data; | ||
1294 | (*count)--; | ||
1295 | cnt--; | ||
1296 | toPIO--; | ||
1297 | } | ||
1298 | DMA_PRINTK("Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data); | ||
1299 | NCR5380_transfer_pio(instance, &p, &cnt, data); | ||
1300 | *count -= toPIO - cnt; | ||
1301 | } | ||
1248 | } | 1302 | } |
1249 | } | ||
1250 | } | 1303 | } |
1251 | #endif /* REAL_DMA */ | 1304 | #endif /* REAL_DMA */ |
1252 | 1305 | ||
1253 | 1306 | ||
1254 | /* | 1307 | /* |
1255 | * Function : void NCR5380_intr (int irq) | 1308 | * Function : void NCR5380_intr (int irq) |
1256 | * | 1309 | * |
1257 | * Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses | 1310 | * Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses |
1258 | * from the disconnected queue, and restarting NCR5380_main() | 1311 | * from the disconnected queue, and restarting NCR5380_main() |
1259 | * as required. | 1312 | * as required. |
1260 | * | 1313 | * |
1261 | * Inputs : int irq, irq that caused this interrupt. | 1314 | * Inputs : int irq, irq that caused this interrupt. |
1262 | * | 1315 | * |
1263 | */ | 1316 | */ |
1264 | 1317 | ||
1265 | static irqreturn_t NCR5380_intr (int irq, void *dev_id) | 1318 | static irqreturn_t NCR5380_intr(int irq, void *dev_id) |
1266 | { | 1319 | { |
1267 | struct Scsi_Host *instance = first_instance; | 1320 | struct Scsi_Host *instance = first_instance; |
1268 | int done = 1, handled = 0; | 1321 | int done = 1, handled = 0; |
1269 | unsigned char basr; | 1322 | unsigned char basr; |
1270 | 1323 | ||
1271 | INT_PRINTK("scsi%d: NCR5380 irq triggered\n", HOSTNO); | 1324 | INT_PRINTK("scsi%d: NCR5380 irq triggered\n", HOSTNO); |
1272 | 1325 | ||
1273 | /* Look for pending interrupts */ | 1326 | /* Look for pending interrupts */ |
1274 | basr = NCR5380_read(BUS_AND_STATUS_REG); | 1327 | basr = NCR5380_read(BUS_AND_STATUS_REG); |
1275 | INT_PRINTK("scsi%d: BASR=%02x\n", HOSTNO, basr); | 1328 | INT_PRINTK("scsi%d: BASR=%02x\n", HOSTNO, basr); |
1276 | /* dispatch to appropriate routine if found and done=0 */ | 1329 | /* dispatch to appropriate routine if found and done=0 */ |
1277 | if (basr & BASR_IRQ) { | 1330 | if (basr & BASR_IRQ) { |
1278 | NCR_PRINT(NDEBUG_INTR); | 1331 | NCR_PRINT(NDEBUG_INTR); |
1279 | if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) { | 1332 | if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) { |
1280 | done = 0; | 1333 | done = 0; |
1281 | ENABLE_IRQ(); | 1334 | ENABLE_IRQ(); |
1282 | INT_PRINTK("scsi%d: SEL interrupt\n", HOSTNO); | 1335 | INT_PRINTK("scsi%d: SEL interrupt\n", HOSTNO); |
1283 | NCR5380_reselect(instance); | 1336 | NCR5380_reselect(instance); |
1284 | (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); | 1337 | (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); |
1285 | } | 1338 | } else if (basr & BASR_PARITY_ERROR) { |
1286 | else if (basr & BASR_PARITY_ERROR) { | 1339 | INT_PRINTK("scsi%d: PARITY interrupt\n", HOSTNO); |
1287 | INT_PRINTK("scsi%d: PARITY interrupt\n", HOSTNO); | 1340 | (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); |
1288 | (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); | 1341 | } else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) { |
1289 | } | 1342 | INT_PRINTK("scsi%d: RESET interrupt\n", HOSTNO); |
1290 | else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) { | 1343 | (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); |
1291 | INT_PRINTK("scsi%d: RESET interrupt\n", HOSTNO); | 1344 | } else { |
1292 | (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); | 1345 | /* |
1293 | } | 1346 | * The rest of the interrupt conditions can occur only during a |
1294 | else { | 1347 | * DMA transfer |
1295 | /* | 1348 | */ |
1296 | * The rest of the interrupt conditions can occur only during a | ||
1297 | * DMA transfer | ||
1298 | */ | ||
1299 | 1349 | ||
1300 | #if defined(REAL_DMA) | 1350 | #if defined(REAL_DMA) |
1301 | /* | 1351 | /* |
1302 | * We should only get PHASE MISMATCH and EOP interrupts if we have | 1352 | * We should only get PHASE MISMATCH and EOP interrupts if we have |
1303 | * DMA enabled, so do a sanity check based on the current setting | 1353 | * DMA enabled, so do a sanity check based on the current setting |
1304 | * of the MODE register. | 1354 | * of the MODE register. |
1305 | */ | 1355 | */ |
1306 | 1356 | ||
1307 | if ((NCR5380_read(MODE_REG) & MR_DMA_MODE) && | 1357 | if ((NCR5380_read(MODE_REG) & MR_DMA_MODE) && |
1308 | ((basr & BASR_END_DMA_TRANSFER) || | 1358 | ((basr & BASR_END_DMA_TRANSFER) || |
1309 | !(basr & BASR_PHASE_MATCH))) { | 1359 | !(basr & BASR_PHASE_MATCH))) { |
1310 | 1360 | ||
1311 | INT_PRINTK("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO); | 1361 | INT_PRINTK("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO); |
1312 | NCR5380_dma_complete( instance ); | 1362 | NCR5380_dma_complete( instance ); |
1313 | done = 0; | 1363 | done = 0; |
1314 | ENABLE_IRQ(); | 1364 | ENABLE_IRQ(); |
1315 | } else | 1365 | } else |
1316 | #endif /* REAL_DMA */ | 1366 | #endif /* REAL_DMA */ |
1317 | { | 1367 | { |
1318 | /* MS: Ignore unknown phase mismatch interrupts (caused by EOP interrupt) */ | 1368 | /* MS: Ignore unknown phase mismatch interrupts (caused by EOP interrupt) */ |
1319 | if (basr & BASR_PHASE_MATCH) | 1369 | if (basr & BASR_PHASE_MATCH) |
1320 | printk(KERN_NOTICE "scsi%d: unknown interrupt, " | 1370 | printk(KERN_NOTICE "scsi%d: unknown interrupt, " |
1321 | "BASR 0x%x, MR 0x%x, SR 0x%x\n", | 1371 | "BASR 0x%x, MR 0x%x, SR 0x%x\n", |
1322 | HOSTNO, basr, NCR5380_read(MODE_REG), | 1372 | HOSTNO, basr, NCR5380_read(MODE_REG), |
1323 | NCR5380_read(STATUS_REG)); | 1373 | NCR5380_read(STATUS_REG)); |
1324 | (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); | 1374 | (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); |
1325 | } | 1375 | } |
1326 | } /* if !(SELECTION || PARITY) */ | 1376 | } /* if !(SELECTION || PARITY) */ |
1327 | handled = 1; | 1377 | handled = 1; |
1328 | } /* BASR & IRQ */ | 1378 | } /* BASR & IRQ */ else { |
1329 | else { | 1379 | printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, " |
1330 | printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, " | 1380 | "BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr, |
1331 | "BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr, | 1381 | NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG)); |
1332 | NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG)); | 1382 | (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); |
1333 | (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); | 1383 | } |
1334 | } | 1384 | |
1335 | 1385 | if (!done) { | |
1336 | if (!done) { | 1386 | INT_PRINTK("scsi%d: in int routine, calling main\n", HOSTNO); |
1337 | INT_PRINTK("scsi%d: in int routine, calling main\n", HOSTNO); | 1387 | /* Put a call to NCR5380_main() on the queue... */ |
1338 | /* Put a call to NCR5380_main() on the queue... */ | 1388 | queue_main(); |
1339 | queue_main(); | 1389 | } |
1340 | } | 1390 | return IRQ_RETVAL(handled); |
1341 | return IRQ_RETVAL(handled); | ||
1342 | } | 1391 | } |
1343 | 1392 | ||
1344 | #ifdef NCR5380_STATS | 1393 | #ifdef NCR5380_STATS |
1345 | static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd* cmd) | 1394 | static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd *cmd) |
1346 | { | 1395 | { |
1347 | # ifdef NCR5380_STAT_LIMIT | 1396 | # ifdef NCR5380_STAT_LIMIT |
1348 | if (cmd->request_bufflen > NCR5380_STAT_LIMIT) | 1397 | if (cmd->request_bufflen > NCR5380_STAT_LIMIT) |
1349 | # endif | 1398 | # endif |
1350 | switch (cmd->cmnd[0]) | 1399 | switch (cmd->cmnd[0]) { |
1351 | { | 1400 | case WRITE: |
1352 | case WRITE: | 1401 | case WRITE_6: |
1353 | case WRITE_6: | 1402 | case WRITE_10: |
1354 | case WRITE_10: | 1403 | hostdata->time_write[cmd->device->id] += (jiffies - hostdata->timebase); |
1355 | hostdata->time_write[cmd->device->id] += (jiffies - hostdata->timebase); | 1404 | /*hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;*/ |
1356 | /*hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;*/ | 1405 | hostdata->pendingw--; |
1357 | hostdata->pendingw--; | 1406 | break; |
1358 | break; | 1407 | case READ: |
1359 | case READ: | 1408 | case READ_6: |
1360 | case READ_6: | 1409 | case READ_10: |
1361 | case READ_10: | 1410 | hostdata->time_read[cmd->device->id] += (jiffies - hostdata->timebase); |
1362 | hostdata->time_read[cmd->device->id] += (jiffies - hostdata->timebase); | 1411 | /*hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;*/ |
1363 | /*hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;*/ | 1412 | hostdata->pendingr--; |
1364 | hostdata->pendingr--; | 1413 | break; |
1365 | break; | 1414 | } |
1366 | } | ||
1367 | } | 1415 | } |
1368 | #endif | 1416 | #endif |
1369 | 1417 | ||
1370 | /* | 1418 | /* |
1371 | * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, | 1419 | * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, |
1372 | * int tag); | 1420 | * int tag); |
1373 | * | 1421 | * |
1374 | * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command, | 1422 | * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command, |
1375 | * including ARBITRATION, SELECTION, and initial message out for | 1423 | * including ARBITRATION, SELECTION, and initial message out for |
1376 | * IDENTIFY and queue messages. | 1424 | * IDENTIFY and queue messages. |
1377 | * | 1425 | * |
1378 | * Inputs : instance - instantiation of the 5380 driver on which this | 1426 | * Inputs : instance - instantiation of the 5380 driver on which this |
1379 | * target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for | 1427 | * target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for |
1380 | * new tag, TAG_NONE for untagged queueing, otherwise set to the tag for | 1428 | * new tag, TAG_NONE for untagged queueing, otherwise set to the tag for |
1381 | * the command that is presently connected. | 1429 | * the command that is presently connected. |
1382 | * | 1430 | * |
1383 | * Returns : -1 if selection could not execute for some reason, | 1431 | * Returns : -1 if selection could not execute for some reason, |
1384 | * 0 if selection succeeded or failed because the target | 1432 | * 0 if selection succeeded or failed because the target |
1385 | * did not respond. | 1433 | * did not respond. |
1386 | * | 1434 | * |
1387 | * Side effects : | 1435 | * Side effects : |
1388 | * If bus busy, arbitration failed, etc, NCR5380_select() will exit | 1436 | * If bus busy, arbitration failed, etc, NCR5380_select() will exit |
1389 | * with registers as they should have been on entry - ie | 1437 | * with registers as they should have been on entry - ie |
1390 | * SELECT_ENABLE will be set appropriately, the NCR5380 | 1438 | * SELECT_ENABLE will be set appropriately, the NCR5380 |
1391 | * will cease to drive any SCSI bus signals. | 1439 | * will cease to drive any SCSI bus signals. |
1392 | * | 1440 | * |
1393 | * If successful : I_T_L or I_T_L_Q nexus will be established, | 1441 | * If successful : I_T_L or I_T_L_Q nexus will be established, |
1394 | * instance->connected will be set to cmd. | 1442 | * instance->connected will be set to cmd. |
1395 | * SELECT interrupt will be disabled. | 1443 | * SELECT interrupt will be disabled. |
1396 | * | 1444 | * |
1397 | * If failed (no target) : cmd->scsi_done() will be called, and the | 1445 | * If failed (no target) : cmd->scsi_done() will be called, and the |
1398 | * cmd->result host byte set to DID_BAD_TARGET. | 1446 | * cmd->result host byte set to DID_BAD_TARGET. |
1399 | */ | 1447 | */ |
1400 | 1448 | ||
1401 | static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) | 1449 | static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) |
1402 | { | 1450 | { |
1403 | SETUP_HOSTDATA(instance); | 1451 | SETUP_HOSTDATA(instance); |
1404 | unsigned char tmp[3], phase; | 1452 | unsigned char tmp[3], phase; |
1405 | unsigned char *data; | 1453 | unsigned char *data; |
1406 | int len; | 1454 | int len; |
1407 | unsigned long timeout; | 1455 | unsigned long timeout; |
1408 | unsigned long flags; | 1456 | unsigned long flags; |
1409 | 1457 | ||
1410 | hostdata->restart_select = 0; | 1458 | hostdata->restart_select = 0; |
1411 | NCR_PRINT(NDEBUG_ARBITRATION); | 1459 | NCR_PRINT(NDEBUG_ARBITRATION); |
1412 | ARB_PRINTK("scsi%d: starting arbitration, id = %d\n", HOSTNO, | 1460 | ARB_PRINTK("scsi%d: starting arbitration, id = %d\n", HOSTNO, |
1413 | instance->this_id); | 1461 | instance->this_id); |
1414 | 1462 | ||
1415 | /* | 1463 | /* |
1416 | * Set the phase bits to 0, otherwise the NCR5380 won't drive the | 1464 | * Set the phase bits to 0, otherwise the NCR5380 won't drive the |
1417 | * data bus during SELECTION. | 1465 | * data bus during SELECTION. |
1418 | */ | 1466 | */ |
1419 | 1467 | ||
1420 | local_irq_save(flags); | 1468 | local_irq_save(flags); |
1421 | if (hostdata->connected) { | 1469 | if (hostdata->connected) { |
1470 | local_irq_restore(flags); | ||
1471 | return -1; | ||
1472 | } | ||
1473 | NCR5380_write(TARGET_COMMAND_REG, 0); | ||
1474 | |||
1475 | /* | ||
1476 | * Start arbitration. | ||
1477 | */ | ||
1478 | |||
1479 | NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); | ||
1480 | NCR5380_write(MODE_REG, MR_ARBITRATE); | ||
1481 | |||
1422 | local_irq_restore(flags); | 1482 | local_irq_restore(flags); |
1423 | return -1; | 1483 | |
1424 | } | 1484 | /* Wait for arbitration logic to complete */ |
1425 | NCR5380_write(TARGET_COMMAND_REG, 0); | 1485 | #if defined(NCR_TIMEOUT) |
1426 | 1486 | { | |
1427 | 1487 | unsigned long timeout = jiffies + 2*NCR_TIMEOUT; | |
1428 | /* | 1488 | |
1429 | * Start arbitration. | 1489 | while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) && |
1430 | */ | 1490 | time_before(jiffies, timeout) && !hostdata->connected) |
1431 | 1491 | ; | |
1432 | NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); | 1492 | if (time_after_eq(jiffies, timeout)) { |
1433 | NCR5380_write(MODE_REG, MR_ARBITRATE); | 1493 | printk("scsi : arbitration timeout at %d\n", __LINE__); |
1434 | 1494 | NCR5380_write(MODE_REG, MR_BASE); | |
1435 | local_irq_restore(flags); | 1495 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); |
1436 | 1496 | return -1; | |
1437 | /* Wait for arbitration logic to complete */ | 1497 | } |
1438 | #if NCR_TIMEOUT | 1498 | } |
1439 | { | ||
1440 | unsigned long timeout = jiffies + 2*NCR_TIMEOUT; | ||
1441 | |||
1442 | while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) | ||
1443 | && time_before(jiffies, timeout) && !hostdata->connected) | ||
1444 | ; | ||
1445 | if (time_after_eq(jiffies, timeout)) | ||
1446 | { | ||
1447 | printk("scsi : arbitration timeout at %d\n", __LINE__); | ||
1448 | NCR5380_write(MODE_REG, MR_BASE); | ||
1449 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | ||
1450 | return -1; | ||
1451 | } | ||
1452 | } | ||
1453 | #else /* NCR_TIMEOUT */ | 1499 | #else /* NCR_TIMEOUT */ |
1454 | while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) | 1500 | while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) && |
1455 | && !hostdata->connected); | 1501 | !hostdata->connected) |
1502 | ; | ||
1456 | #endif | 1503 | #endif |
1457 | 1504 | ||
1458 | ARB_PRINTK("scsi%d: arbitration complete\n", HOSTNO); | 1505 | ARB_PRINTK("scsi%d: arbitration complete\n", HOSTNO); |
1459 | |||
1460 | if (hostdata->connected) { | ||
1461 | NCR5380_write(MODE_REG, MR_BASE); | ||
1462 | return -1; | ||
1463 | } | ||
1464 | /* | ||
1465 | * The arbitration delay is 2.2us, but this is a minimum and there is | ||
1466 | * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate | ||
1467 | * the integral nature of udelay(). | ||
1468 | * | ||
1469 | */ | ||
1470 | |||
1471 | udelay(3); | ||
1472 | |||
1473 | /* Check for lost arbitration */ | ||
1474 | if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || | ||
1475 | (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || | ||
1476 | (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || | ||
1477 | hostdata->connected) { | ||
1478 | NCR5380_write(MODE_REG, MR_BASE); | ||
1479 | ARB_PRINTK("scsi%d: lost arbitration, deasserting MR_ARBITRATE\n", | ||
1480 | HOSTNO); | ||
1481 | return -1; | ||
1482 | } | ||
1483 | |||
1484 | /* after/during arbitration, BSY should be asserted. | ||
1485 | IBM DPES-31080 Version S31Q works now */ | ||
1486 | /* Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) */ | ||
1487 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL | | ||
1488 | ICR_ASSERT_BSY ) ; | ||
1489 | |||
1490 | if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || | ||
1491 | hostdata->connected) { | ||
1492 | NCR5380_write(MODE_REG, MR_BASE); | ||
1493 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | ||
1494 | ARB_PRINTK("scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n", | ||
1495 | HOSTNO); | ||
1496 | return -1; | ||
1497 | } | ||
1498 | 1506 | ||
1499 | /* | 1507 | if (hostdata->connected) { |
1500 | * Again, bus clear + bus settle time is 1.2us, however, this is | 1508 | NCR5380_write(MODE_REG, MR_BASE); |
1501 | * a minimum so we'll udelay ceil(1.2) | 1509 | return -1; |
1502 | */ | 1510 | } |
1511 | /* | ||
1512 | * The arbitration delay is 2.2us, but this is a minimum and there is | ||
1513 | * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate | ||
1514 | * the integral nature of udelay(). | ||
1515 | * | ||
1516 | */ | ||
1517 | |||
1518 | udelay(3); | ||
1519 | |||
1520 | /* Check for lost arbitration */ | ||
1521 | if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || | ||
1522 | (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || | ||
1523 | (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || | ||
1524 | hostdata->connected) { | ||
1525 | NCR5380_write(MODE_REG, MR_BASE); | ||
1526 | ARB_PRINTK("scsi%d: lost arbitration, deasserting MR_ARBITRATE\n", | ||
1527 | HOSTNO); | ||
1528 | return -1; | ||
1529 | } | ||
1530 | |||
1531 | /* after/during arbitration, BSY should be asserted. | ||
1532 | IBM DPES-31080 Version S31Q works now */ | ||
1533 | /* Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) */ | ||
1534 | NCR5380_write(INITIATOR_COMMAND_REG, | ||
1535 | ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY); | ||
1536 | |||
1537 | if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || | ||
1538 | hostdata->connected) { | ||
1539 | NCR5380_write(MODE_REG, MR_BASE); | ||
1540 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | ||
1541 | ARB_PRINTK("scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n", | ||
1542 | HOSTNO); | ||
1543 | return -1; | ||
1544 | } | ||
1545 | |||
1546 | /* | ||
1547 | * Again, bus clear + bus settle time is 1.2us, however, this is | ||
1548 | * a minimum so we'll udelay ceil(1.2) | ||
1549 | */ | ||
1503 | 1550 | ||
1504 | #ifdef CONFIG_ATARI_SCSI_TOSHIBA_DELAY | 1551 | #ifdef CONFIG_ATARI_SCSI_TOSHIBA_DELAY |
1505 | /* ++roman: But some targets (see above :-) seem to need a bit more... */ | 1552 | /* ++roman: But some targets (see above :-) seem to need a bit more... */ |
1506 | udelay(15); | 1553 | udelay(15); |
1507 | #else | 1554 | #else |
1508 | udelay(2); | 1555 | udelay(2); |
1509 | #endif | 1556 | #endif |
1510 | 1557 | ||
1511 | if (hostdata->connected) { | 1558 | if (hostdata->connected) { |
1559 | NCR5380_write(MODE_REG, MR_BASE); | ||
1560 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | ||
1561 | return -1; | ||
1562 | } | ||
1563 | |||
1564 | ARB_PRINTK("scsi%d: won arbitration\n", HOSTNO); | ||
1565 | |||
1566 | /* | ||
1567 | * Now that we have won arbitration, start Selection process, asserting | ||
1568 | * the host and target ID's on the SCSI bus. | ||
1569 | */ | ||
1570 | |||
1571 | NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id))); | ||
1572 | |||
1573 | /* | ||
1574 | * Raise ATN while SEL is true before BSY goes false from arbitration, | ||
1575 | * since this is the only way to guarantee that we'll get a MESSAGE OUT | ||
1576 | * phase immediately after selection. | ||
1577 | */ | ||
1578 | |||
1579 | NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | | ||
1580 | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL )); | ||
1512 | NCR5380_write(MODE_REG, MR_BASE); | 1581 | NCR5380_write(MODE_REG, MR_BASE); |
1513 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | ||
1514 | return -1; | ||
1515 | } | ||
1516 | 1582 | ||
1517 | ARB_PRINTK("scsi%d: won arbitration\n", HOSTNO); | 1583 | /* |
1584 | * Reselect interrupts must be turned off prior to the dropping of BSY, | ||
1585 | * otherwise we will trigger an interrupt. | ||
1586 | */ | ||
1587 | |||
1588 | if (hostdata->connected) { | ||
1589 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | ||
1590 | return -1; | ||
1591 | } | ||
1518 | 1592 | ||
1519 | /* | 1593 | NCR5380_write(SELECT_ENABLE_REG, 0); |
1520 | * Now that we have won arbitration, start Selection process, asserting | 1594 | |
1521 | * the host and target ID's on the SCSI bus. | 1595 | /* |
1522 | */ | 1596 | * The initiator shall then wait at least two deskew delays and release |
1597 | * the BSY signal. | ||
1598 | */ | ||
1599 | udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */ | ||
1600 | |||
1601 | /* Reset BSY */ | ||
1602 | NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | | ||
1603 | ICR_ASSERT_ATN | ICR_ASSERT_SEL)); | ||
1604 | |||
1605 | /* | ||
1606 | * Something weird happens when we cease to drive BSY - looks | ||
1607 | * like the board/chip is letting us do another read before the | ||
1608 | * appropriate propagation delay has expired, and we're confusing | ||
1609 | * a BSY signal from ourselves as the target's response to SELECTION. | ||
1610 | * | ||
1611 | * A small delay (the 'C++' frontend breaks the pipeline with an | ||
1612 | * unnecessary jump, making it work on my 386-33/Trantor T128, the | ||
1613 | * tighter 'C' code breaks and requires this) solves the problem - | ||
1614 | * the 1 us delay is arbitrary, and only used because this delay will | ||
1615 | * be the same on other platforms and since it works here, it should | ||
1616 | * work there. | ||
1617 | * | ||
1618 | * wingel suggests that this could be due to failing to wait | ||
1619 | * one deskew delay. | ||
1620 | */ | ||
1523 | 1621 | ||
1524 | NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id))); | 1622 | udelay(1); |
1525 | 1623 | ||
1526 | /* | 1624 | SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->device->id); |
1527 | * Raise ATN while SEL is true before BSY goes false from arbitration, | ||
1528 | * since this is the only way to guarantee that we'll get a MESSAGE OUT | ||
1529 | * phase immediately after selection. | ||
1530 | */ | ||
1531 | 1625 | ||
1532 | NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | | 1626 | /* |
1533 | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL )); | 1627 | * The SCSI specification calls for a 250 ms timeout for the actual |
1534 | NCR5380_write(MODE_REG, MR_BASE); | 1628 | * selection. |
1629 | */ | ||
1535 | 1630 | ||
1536 | /* | 1631 | timeout = jiffies + 25; |
1537 | * Reselect interrupts must be turned off prior to the dropping of BSY, | ||
1538 | * otherwise we will trigger an interrupt. | ||
1539 | */ | ||
1540 | 1632 | ||
1541 | if (hostdata->connected) { | 1633 | /* |
1542 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 1634 | * XXX very interesting - we're seeing a bounce where the BSY we |
1543 | return -1; | 1635 | * asserted is being reflected / still asserted (propagation delay?) |
1544 | } | 1636 | * and it's detecting as true. Sigh. |
1545 | 1637 | */ | |
1546 | NCR5380_write(SELECT_ENABLE_REG, 0); | ||
1547 | |||
1548 | /* | ||
1549 | * The initiator shall then wait at least two deskew delays and release | ||
1550 | * the BSY signal. | ||
1551 | */ | ||
1552 | udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */ | ||
1553 | |||
1554 | /* Reset BSY */ | ||
1555 | NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | | ||
1556 | ICR_ASSERT_ATN | ICR_ASSERT_SEL)); | ||
1557 | |||
1558 | /* | ||
1559 | * Something weird happens when we cease to drive BSY - looks | ||
1560 | * like the board/chip is letting us do another read before the | ||
1561 | * appropriate propagation delay has expired, and we're confusing | ||
1562 | * a BSY signal from ourselves as the target's response to SELECTION. | ||
1563 | * | ||
1564 | * A small delay (the 'C++' frontend breaks the pipeline with an | ||
1565 | * unnecessary jump, making it work on my 386-33/Trantor T128, the | ||
1566 | * tighter 'C' code breaks and requires this) solves the problem - | ||
1567 | * the 1 us delay is arbitrary, and only used because this delay will | ||
1568 | * be the same on other platforms and since it works here, it should | ||
1569 | * work there. | ||
1570 | * | ||
1571 | * wingel suggests that this could be due to failing to wait | ||
1572 | * one deskew delay. | ||
1573 | */ | ||
1574 | |||
1575 | udelay(1); | ||
1576 | |||
1577 | SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->device->id); | ||
1578 | |||
1579 | /* | ||
1580 | * The SCSI specification calls for a 250 ms timeout for the actual | ||
1581 | * selection. | ||
1582 | */ | ||
1583 | |||
1584 | timeout = jiffies + 25; | ||
1585 | |||
1586 | /* | ||
1587 | * XXX very interesting - we're seeing a bounce where the BSY we | ||
1588 | * asserted is being reflected / still asserted (propagation delay?) | ||
1589 | * and it's detecting as true. Sigh. | ||
1590 | */ | ||
1591 | 1638 | ||
1592 | #if 0 | 1639 | #if 0 |
1593 | /* ++roman: If a target conformed to the SCSI standard, it wouldn't assert | 1640 | /* ++roman: If a target conformed to the SCSI standard, it wouldn't assert |
1594 | * IO while SEL is true. But again, there are some disks out the in the | 1641 | * IO while SEL is true. But again, there are some disks out the in the |
1595 | * world that do that nevertheless. (Somebody claimed that this announces | 1642 | * world that do that nevertheless. (Somebody claimed that this announces |
1596 | * reselection capability of the target.) So we better skip that test and | 1643 | * reselection capability of the target.) So we better skip that test and |
1597 | * only wait for BSY... (Famous german words: Der Klügere gibt nach :-) | 1644 | * only wait for BSY... (Famous german words: Der Klügere gibt nach :-) |
1598 | */ | 1645 | */ |
1599 | 1646 | ||
1600 | while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & | 1647 | while (time_before(jiffies, timeout) && |
1601 | (SR_BSY | SR_IO))); | 1648 | !(NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO))) |
1602 | 1649 | ; | |
1603 | if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == | 1650 | |
1604 | (SR_SEL | SR_IO)) { | 1651 | if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { |
1605 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 1652 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
1606 | NCR5380_reselect(instance); | 1653 | NCR5380_reselect(instance); |
1607 | printk (KERN_ERR "scsi%d: reselection after won arbitration?\n", | 1654 | printk(KERN_ERR "scsi%d: reselection after won arbitration?\n", |
1608 | HOSTNO); | 1655 | HOSTNO); |
1609 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | 1656 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); |
1610 | return -1; | 1657 | return -1; |
1611 | } | 1658 | } |
1612 | #else | 1659 | #else |
1613 | while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY)); | 1660 | while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY)) |
1661 | ; | ||
1614 | #endif | 1662 | #endif |
1615 | 1663 | ||
1616 | /* | 1664 | /* |
1617 | * No less than two deskew delays after the initiator detects the | 1665 | * No less than two deskew delays after the initiator detects the |
1618 | * BSY signal is true, it shall release the SEL signal and may | 1666 | * BSY signal is true, it shall release the SEL signal and may |
1619 | * change the DATA BUS. -wingel | 1667 | * change the DATA BUS. -wingel |
1620 | */ | 1668 | */ |
1621 | 1669 | ||
1622 | udelay(1); | 1670 | udelay(1); |
1623 | 1671 | ||
1624 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); | 1672 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); |
1625 | 1673 | ||
1626 | if (!(NCR5380_read(STATUS_REG) & SR_BSY)) { | 1674 | if (!(NCR5380_read(STATUS_REG) & SR_BSY)) { |
1627 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 1675 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
1628 | if (hostdata->targets_present & (1 << cmd->device->id)) { | 1676 | if (hostdata->targets_present & (1 << cmd->device->id)) { |
1629 | printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO); | 1677 | printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO); |
1630 | if (hostdata->restart_select) | 1678 | if (hostdata->restart_select) |
1631 | printk(KERN_NOTICE "\trestart select\n"); | 1679 | printk(KERN_NOTICE "\trestart select\n"); |
1632 | NCR_PRINT(NDEBUG_ANY); | 1680 | NCR_PRINT(NDEBUG_ANY); |
1633 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | 1681 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); |
1634 | return -1; | 1682 | return -1; |
1635 | } | 1683 | } |
1636 | cmd->result = DID_BAD_TARGET << 16; | 1684 | cmd->result = DID_BAD_TARGET << 16; |
1637 | #ifdef NCR5380_STATS | 1685 | #ifdef NCR5380_STATS |
1638 | collect_stats(hostdata, cmd); | 1686 | collect_stats(hostdata, cmd); |
1639 | #endif | 1687 | #endif |
1640 | #ifdef SUPPORT_TAGS | 1688 | #ifdef SUPPORT_TAGS |
1641 | cmd_free_tag( cmd ); | 1689 | cmd_free_tag(cmd); |
1642 | #endif | 1690 | #endif |
1643 | cmd->scsi_done(cmd); | 1691 | cmd->scsi_done(cmd); |
1644 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | 1692 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); |
1645 | SEL_PRINTK("scsi%d: target did not respond within 250ms\n", HOSTNO); | 1693 | SEL_PRINTK("scsi%d: target did not respond within 250ms\n", HOSTNO); |
1646 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | 1694 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); |
1647 | return 0; | 1695 | return 0; |
1648 | } | 1696 | } |
1649 | 1697 | ||
1650 | hostdata->targets_present |= (1 << cmd->device->id); | 1698 | hostdata->targets_present |= (1 << cmd->device->id); |
1651 | 1699 | ||
1652 | /* | 1700 | /* |
1653 | * Since we followed the SCSI spec, and raised ATN while SEL | 1701 | * Since we followed the SCSI spec, and raised ATN while SEL |
1654 | * was true but before BSY was false during selection, the information | 1702 | * was true but before BSY was false during selection, the information |
1655 | * transfer phase should be a MESSAGE OUT phase so that we can send the | 1703 | * transfer phase should be a MESSAGE OUT phase so that we can send the |
1656 | * IDENTIFY message. | 1704 | * IDENTIFY message. |
1657 | * | 1705 | * |
1658 | * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG | 1706 | * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG |
1659 | * message (2 bytes) with a tag ID that we increment with every command | 1707 | * message (2 bytes) with a tag ID that we increment with every command |
1660 | * until it wraps back to 0. | 1708 | * until it wraps back to 0. |
1661 | * | 1709 | * |
1662 | * XXX - it turns out that there are some broken SCSI-II devices, | 1710 | * XXX - it turns out that there are some broken SCSI-II devices, |
1663 | * which claim to support tagged queuing but fail when more than | 1711 | * which claim to support tagged queuing but fail when more than |
1664 | * some number of commands are issued at once. | 1712 | * some number of commands are issued at once. |
1665 | */ | 1713 | */ |
1666 | 1714 | ||
1667 | /* Wait for start of REQ/ACK handshake */ | 1715 | /* Wait for start of REQ/ACK handshake */ |
1668 | while (!(NCR5380_read(STATUS_REG) & SR_REQ)); | 1716 | while (!(NCR5380_read(STATUS_REG) & SR_REQ)) |
1669 | 1717 | ; | |
1670 | SEL_PRINTK("scsi%d: target %d selected, going into MESSAGE OUT phase.\n", | 1718 | |
1671 | HOSTNO, cmd->device->id); | 1719 | SEL_PRINTK("scsi%d: target %d selected, going into MESSAGE OUT phase.\n", |
1672 | tmp[0] = IDENTIFY(1, cmd->device->lun); | 1720 | HOSTNO, cmd->device->id); |
1721 | tmp[0] = IDENTIFY(1, cmd->device->lun); | ||
1673 | 1722 | ||
1674 | #ifdef SUPPORT_TAGS | 1723 | #ifdef SUPPORT_TAGS |
1675 | if (cmd->tag != TAG_NONE) { | 1724 | if (cmd->tag != TAG_NONE) { |
1676 | tmp[1] = hostdata->last_message = SIMPLE_QUEUE_TAG; | 1725 | tmp[1] = hostdata->last_message = SIMPLE_QUEUE_TAG; |
1677 | tmp[2] = cmd->tag; | 1726 | tmp[2] = cmd->tag; |
1678 | len = 3; | 1727 | len = 3; |
1679 | } else | 1728 | } else |
1680 | len = 1; | 1729 | len = 1; |
1681 | #else | 1730 | #else |
1682 | len = 1; | 1731 | len = 1; |
1683 | cmd->tag=0; | 1732 | cmd->tag = 0; |
1684 | #endif /* SUPPORT_TAGS */ | 1733 | #endif /* SUPPORT_TAGS */ |
1685 | 1734 | ||
1686 | /* Send message(s) */ | 1735 | /* Send message(s) */ |
1687 | data = tmp; | 1736 | data = tmp; |
1688 | phase = PHASE_MSGOUT; | 1737 | phase = PHASE_MSGOUT; |
1689 | NCR5380_transfer_pio(instance, &phase, &len, &data); | 1738 | NCR5380_transfer_pio(instance, &phase, &len, &data); |
1690 | SEL_PRINTK("scsi%d: nexus established.\n", HOSTNO); | 1739 | SEL_PRINTK("scsi%d: nexus established.\n", HOSTNO); |
1691 | /* XXX need to handle errors here */ | 1740 | /* XXX need to handle errors here */ |
1692 | hostdata->connected = cmd; | 1741 | hostdata->connected = cmd; |
1693 | #ifndef SUPPORT_TAGS | 1742 | #ifndef SUPPORT_TAGS |
1694 | hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); | 1743 | hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); |
1695 | #endif | 1744 | #endif |
1696 | |||
1697 | initialize_SCp(cmd); | ||
1698 | 1745 | ||
1746 | initialize_SCp(cmd); | ||
1699 | 1747 | ||
1700 | return 0; | 1748 | return 0; |
1701 | } | 1749 | } |
1702 | 1750 | ||
1703 | /* | 1751 | /* |
1704 | * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance, | 1752 | * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance, |
1705 | * unsigned char *phase, int *count, unsigned char **data) | 1753 | * unsigned char *phase, int *count, unsigned char **data) |
1706 | * | 1754 | * |
1707 | * Purpose : transfers data in given phase using polled I/O | 1755 | * Purpose : transfers data in given phase using polled I/O |
1708 | * | 1756 | * |
1709 | * Inputs : instance - instance of driver, *phase - pointer to | 1757 | * Inputs : instance - instance of driver, *phase - pointer to |
1710 | * what phase is expected, *count - pointer to number of | 1758 | * what phase is expected, *count - pointer to number of |
1711 | * bytes to transfer, **data - pointer to data pointer. | 1759 | * bytes to transfer, **data - pointer to data pointer. |
1712 | * | 1760 | * |
1713 | * Returns : -1 when different phase is entered without transferring | 1761 | * Returns : -1 when different phase is entered without transferring |
1714 | * maximum number of bytes, 0 if all bytes are transfered or exit | 1762 | * maximum number of bytes, 0 if all bytes are transfered or exit |
1715 | * is in same phase. | 1763 | * is in same phase. |
1716 | * | 1764 | * |
1717 | * Also, *phase, *count, *data are modified in place. | 1765 | * Also, *phase, *count, *data are modified in place. |
1718 | * | 1766 | * |
1719 | * XXX Note : handling for bus free may be useful. | 1767 | * XXX Note : handling for bus free may be useful. |
1720 | */ | 1768 | */ |
1721 | 1769 | ||
1722 | /* | 1770 | /* |
1723 | * Note : this code is not as quick as it could be, however it | 1771 | * Note : this code is not as quick as it could be, however it |
1724 | * IS 100% reliable, and for the actual data transfer where speed | 1772 | * IS 100% reliable, and for the actual data transfer where speed |
1725 | * counts, we will always do a pseudo DMA or DMA transfer. | 1773 | * counts, we will always do a pseudo DMA or DMA transfer. |
1726 | */ | 1774 | */ |
1727 | 1775 | ||
1728 | static int NCR5380_transfer_pio( struct Scsi_Host *instance, | 1776 | static int NCR5380_transfer_pio(struct Scsi_Host *instance, |
1729 | unsigned char *phase, int *count, | 1777 | unsigned char *phase, int *count, |
1730 | unsigned char **data) | 1778 | unsigned char **data) |
1731 | { | 1779 | { |
1732 | register unsigned char p = *phase, tmp; | 1780 | register unsigned char p = *phase, tmp; |
1733 | register int c = *count; | 1781 | register int c = *count; |
1734 | register unsigned char *d = *data; | 1782 | register unsigned char *d = *data; |
1735 | 1783 | ||
1736 | /* | 1784 | /* |
1737 | * The NCR5380 chip will only drive the SCSI bus when the | 1785 | * The NCR5380 chip will only drive the SCSI bus when the |
1738 | * phase specified in the appropriate bits of the TARGET COMMAND | 1786 | * phase specified in the appropriate bits of the TARGET COMMAND |
1739 | * REGISTER match the STATUS REGISTER | 1787 | * REGISTER match the STATUS REGISTER |
1740 | */ | ||
1741 | |||
1742 | NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); | ||
1743 | |||
1744 | do { | ||
1745 | /* | ||
1746 | * Wait for assertion of REQ, after which the phase bits will be | ||
1747 | * valid | ||
1748 | */ | 1788 | */ |
1749 | while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ)); | ||
1750 | 1789 | ||
1751 | HSH_PRINTK("scsi%d: REQ detected\n", HOSTNO); | 1790 | NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); |
1752 | 1791 | ||
1753 | /* Check for phase mismatch */ | 1792 | do { |
1754 | if ((tmp & PHASE_MASK) != p) { | 1793 | /* |
1755 | PIO_PRINTK("scsi%d: phase mismatch\n", HOSTNO); | 1794 | * Wait for assertion of REQ, after which the phase bits will be |
1756 | NCR_PRINT_PHASE(NDEBUG_PIO); | 1795 | * valid |
1757 | break; | 1796 | */ |
1758 | } | 1797 | while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ)) |
1798 | ; | ||
1759 | 1799 | ||
1760 | /* Do actual transfer from SCSI bus to / from memory */ | 1800 | HSH_PRINTK("scsi%d: REQ detected\n", HOSTNO); |
1761 | if (!(p & SR_IO)) | ||
1762 | NCR5380_write(OUTPUT_DATA_REG, *d); | ||
1763 | else | ||
1764 | *d = NCR5380_read(CURRENT_SCSI_DATA_REG); | ||
1765 | 1801 | ||
1766 | ++d; | 1802 | /* Check for phase mismatch */ |
1803 | if ((tmp & PHASE_MASK) != p) { | ||
1804 | PIO_PRINTK("scsi%d: phase mismatch\n", HOSTNO); | ||
1805 | NCR_PRINT_PHASE(NDEBUG_PIO); | ||
1806 | break; | ||
1807 | } | ||
1767 | 1808 | ||
1768 | /* | 1809 | /* Do actual transfer from SCSI bus to / from memory */ |
1769 | * The SCSI standard suggests that in MSGOUT phase, the initiator | 1810 | if (!(p & SR_IO)) |
1770 | * should drop ATN on the last byte of the message phase | 1811 | NCR5380_write(OUTPUT_DATA_REG, *d); |
1771 | * after REQ has been asserted for the handshake but before | 1812 | else |
1772 | * the initiator raises ACK. | 1813 | *d = NCR5380_read(CURRENT_SCSI_DATA_REG); |
1773 | */ | ||
1774 | 1814 | ||
1775 | if (!(p & SR_IO)) { | 1815 | ++d; |
1776 | if (!((p & SR_MSG) && c > 1)) { | ||
1777 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | | ||
1778 | ICR_ASSERT_DATA); | ||
1779 | NCR_PRINT(NDEBUG_PIO); | ||
1780 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | | ||
1781 | ICR_ASSERT_DATA | ICR_ASSERT_ACK); | ||
1782 | } else { | ||
1783 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | | ||
1784 | ICR_ASSERT_DATA | ICR_ASSERT_ATN); | ||
1785 | NCR_PRINT(NDEBUG_PIO); | ||
1786 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | | ||
1787 | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK); | ||
1788 | } | ||
1789 | } else { | ||
1790 | NCR_PRINT(NDEBUG_PIO); | ||
1791 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); | ||
1792 | } | ||
1793 | 1816 | ||
1794 | while (NCR5380_read(STATUS_REG) & SR_REQ); | 1817 | /* |
1818 | * The SCSI standard suggests that in MSGOUT phase, the initiator | ||
1819 | * should drop ATN on the last byte of the message phase | ||
1820 | * after REQ has been asserted for the handshake but before | ||
1821 | * the initiator raises ACK. | ||
1822 | */ | ||
1795 | 1823 | ||
1796 | HSH_PRINTK("scsi%d: req false, handshake complete\n", HOSTNO); | 1824 | if (!(p & SR_IO)) { |
1825 | if (!((p & SR_MSG) && c > 1)) { | ||
1826 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA); | ||
1827 | NCR_PRINT(NDEBUG_PIO); | ||
1828 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | | ||
1829 | ICR_ASSERT_DATA | ICR_ASSERT_ACK); | ||
1830 | } else { | ||
1831 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | | ||
1832 | ICR_ASSERT_DATA | ICR_ASSERT_ATN); | ||
1833 | NCR_PRINT(NDEBUG_PIO); | ||
1834 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | | ||
1835 | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK); | ||
1836 | } | ||
1837 | } else { | ||
1838 | NCR_PRINT(NDEBUG_PIO); | ||
1839 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); | ||
1840 | } | ||
1797 | 1841 | ||
1798 | /* | 1842 | while (NCR5380_read(STATUS_REG) & SR_REQ) |
1799 | * We have several special cases to consider during REQ/ACK handshaking : | 1843 | ; |
1800 | * 1. We were in MSGOUT phase, and we are on the last byte of the | 1844 | |
1801 | * message. ATN must be dropped as ACK is dropped. | 1845 | HSH_PRINTK("scsi%d: req false, handshake complete\n", HOSTNO); |
1802 | * | 1846 | |
1803 | * 2. We are in a MSGIN phase, and we are on the last byte of the | 1847 | /* |
1804 | * message. We must exit with ACK asserted, so that the calling | 1848 | * We have several special cases to consider during REQ/ACK handshaking : |
1805 | * code may raise ATN before dropping ACK to reject the message. | 1849 | * 1. We were in MSGOUT phase, and we are on the last byte of the |
1806 | * | 1850 | * message. ATN must be dropped as ACK is dropped. |
1807 | * 3. ACK and ATN are clear and the target may proceed as normal. | 1851 | * |
1808 | */ | 1852 | * 2. We are in a MSGIN phase, and we are on the last byte of the |
1809 | if (!(p == PHASE_MSGIN && c == 1)) { | 1853 | * message. We must exit with ACK asserted, so that the calling |
1810 | if (p == PHASE_MSGOUT && c > 1) | 1854 | * code may raise ATN before dropping ACK to reject the message. |
1811 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); | 1855 | * |
1812 | else | 1856 | * 3. ACK and ATN are clear and the target may proceed as normal. |
1813 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 1857 | */ |
1814 | } | 1858 | if (!(p == PHASE_MSGIN && c == 1)) { |
1815 | } while (--c); | 1859 | if (p == PHASE_MSGOUT && c > 1) |
1816 | 1860 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); | |
1817 | PIO_PRINTK("scsi%d: residual %d\n", HOSTNO, c); | 1861 | else |
1818 | 1862 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | |
1819 | *count = c; | 1863 | } |
1820 | *data = d; | 1864 | } while (--c); |
1821 | tmp = NCR5380_read(STATUS_REG); | 1865 | |
1822 | /* The phase read from the bus is valid if either REQ is (already) | 1866 | PIO_PRINTK("scsi%d: residual %d\n", HOSTNO, c); |
1823 | * asserted or if ACK hasn't been released yet. The latter is the case if | 1867 | |
1824 | * we're in MSGIN and all wanted bytes have been received. */ | 1868 | *count = c; |
1825 | if ((tmp & SR_REQ) || (p == PHASE_MSGIN && c == 0)) | 1869 | *data = d; |
1826 | *phase = tmp & PHASE_MASK; | 1870 | tmp = NCR5380_read(STATUS_REG); |
1827 | else | 1871 | /* The phase read from the bus is valid if either REQ is (already) |
1828 | *phase = PHASE_UNKNOWN; | 1872 | * asserted or if ACK hasn't been released yet. The latter is the case if |
1829 | 1873 | * we're in MSGIN and all wanted bytes have been received. | |
1830 | if (!c || (*phase == p)) | 1874 | */ |
1831 | return 0; | 1875 | if ((tmp & SR_REQ) || (p == PHASE_MSGIN && c == 0)) |
1832 | else | 1876 | *phase = tmp & PHASE_MASK; |
1833 | return -1; | 1877 | else |
1878 | *phase = PHASE_UNKNOWN; | ||
1879 | |||
1880 | if (!c || (*phase == p)) | ||
1881 | return 0; | ||
1882 | else | ||
1883 | return -1; | ||
1834 | } | 1884 | } |
1835 | 1885 | ||
1836 | /* | 1886 | /* |
1837 | * Function : do_abort (Scsi_Host *host) | 1887 | * Function : do_abort (Scsi_Host *host) |
1838 | * | 1888 | * |
1839 | * Purpose : abort the currently established nexus. Should only be | 1889 | * Purpose : abort the currently established nexus. Should only be |
1840 | * called from a routine which can drop into a | 1890 | * called from a routine which can drop into a |
1841 | * | 1891 | * |
1842 | * Returns : 0 on success, -1 on failure. | 1892 | * Returns : 0 on success, -1 on failure. |
1843 | */ | 1893 | */ |
1844 | 1894 | ||
1845 | static int do_abort (struct Scsi_Host *host) | 1895 | static int do_abort(struct Scsi_Host *host) |
1846 | { | 1896 | { |
1847 | unsigned char tmp, *msgptr, phase; | 1897 | unsigned char tmp, *msgptr, phase; |
1848 | int len; | 1898 | int len; |
1849 | 1899 | ||
1850 | /* Request message out phase */ | 1900 | /* Request message out phase */ |
1851 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); | ||
1852 | |||
1853 | /* | ||
1854 | * Wait for the target to indicate a valid phase by asserting | ||
1855 | * REQ. Once this happens, we'll have either a MSGOUT phase | ||
1856 | * and can immediately send the ABORT message, or we'll have some | ||
1857 | * other phase and will have to source/sink data. | ||
1858 | * | ||
1859 | * We really don't care what value was on the bus or what value | ||
1860 | * the target sees, so we just handshake. | ||
1861 | */ | ||
1862 | |||
1863 | while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ); | ||
1864 | |||
1865 | NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); | ||
1866 | |||
1867 | if ((tmp & PHASE_MASK) != PHASE_MSGOUT) { | ||
1868 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | | ||
1869 | ICR_ASSERT_ACK); | ||
1870 | while (NCR5380_read(STATUS_REG) & SR_REQ); | ||
1871 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); | 1901 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); |
1872 | } | 1902 | |
1873 | 1903 | /* | |
1874 | tmp = ABORT; | 1904 | * Wait for the target to indicate a valid phase by asserting |
1875 | msgptr = &tmp; | 1905 | * REQ. Once this happens, we'll have either a MSGOUT phase |
1876 | len = 1; | 1906 | * and can immediately send the ABORT message, or we'll have some |
1877 | phase = PHASE_MSGOUT; | 1907 | * other phase and will have to source/sink data. |
1878 | NCR5380_transfer_pio (host, &phase, &len, &msgptr); | 1908 | * |
1879 | 1909 | * We really don't care what value was on the bus or what value | |
1880 | /* | 1910 | * the target sees, so we just handshake. |
1881 | * If we got here, and the command completed successfully, | 1911 | */ |
1882 | * we're about to go into bus free state. | 1912 | |
1883 | */ | 1913 | while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ) |
1884 | 1914 | ; | |
1885 | return len ? -1 : 0; | 1915 | |
1916 | NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); | ||
1917 | |||
1918 | if ((tmp & PHASE_MASK) != PHASE_MSGOUT) { | ||
1919 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | | ||
1920 | ICR_ASSERT_ACK); | ||
1921 | while (NCR5380_read(STATUS_REG) & SR_REQ) | ||
1922 | ; | ||
1923 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); | ||
1924 | } | ||
1925 | |||
1926 | tmp = ABORT; | ||
1927 | msgptr = &tmp; | ||
1928 | len = 1; | ||
1929 | phase = PHASE_MSGOUT; | ||
1930 | NCR5380_transfer_pio(host, &phase, &len, &msgptr); | ||
1931 | |||
1932 | /* | ||
1933 | * If we got here, and the command completed successfully, | ||
1934 | * we're about to go into bus free state. | ||
1935 | */ | ||
1936 | |||
1937 | return len ? -1 : 0; | ||
1886 | } | 1938 | } |
1887 | 1939 | ||
1888 | #if defined(REAL_DMA) | 1940 | #if defined(REAL_DMA) |
1889 | /* | 1941 | /* |
1890 | * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, | 1942 | * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, |
1891 | * unsigned char *phase, int *count, unsigned char **data) | 1943 | * unsigned char *phase, int *count, unsigned char **data) |
1892 | * | 1944 | * |
1893 | * Purpose : transfers data in given phase using either real | 1945 | * Purpose : transfers data in given phase using either real |
1894 | * or pseudo DMA. | 1946 | * or pseudo DMA. |
1895 | * | 1947 | * |
1896 | * Inputs : instance - instance of driver, *phase - pointer to | 1948 | * Inputs : instance - instance of driver, *phase - pointer to |
1897 | * what phase is expected, *count - pointer to number of | 1949 | * what phase is expected, *count - pointer to number of |
1898 | * bytes to transfer, **data - pointer to data pointer. | 1950 | * bytes to transfer, **data - pointer to data pointer. |
1899 | * | 1951 | * |
1900 | * Returns : -1 when different phase is entered without transferring | 1952 | * Returns : -1 when different phase is entered without transferring |
1901 | * maximum number of bytes, 0 if all bytes or transfered or exit | 1953 | * maximum number of bytes, 0 if all bytes or transfered or exit |
1902 | * is in same phase. | 1954 | * is in same phase. |
1903 | * | 1955 | * |
1904 | * Also, *phase, *count, *data are modified in place. | 1956 | * Also, *phase, *count, *data are modified in place. |
1905 | * | 1957 | * |
1906 | */ | 1958 | */ |
1907 | 1959 | ||
1908 | 1960 | ||
1909 | static int NCR5380_transfer_dma( struct Scsi_Host *instance, | 1961 | static int NCR5380_transfer_dma(struct Scsi_Host *instance, |
1910 | unsigned char *phase, int *count, | 1962 | unsigned char *phase, int *count, |
1911 | unsigned char **data) | 1963 | unsigned char **data) |
1912 | { | 1964 | { |
1913 | SETUP_HOSTDATA(instance); | 1965 | SETUP_HOSTDATA(instance); |
1914 | register int c = *count; | 1966 | register int c = *count; |
1915 | register unsigned char p = *phase; | 1967 | register unsigned char p = *phase; |
1916 | register unsigned char *d = *data; | 1968 | register unsigned char *d = *data; |
1917 | unsigned char tmp; | 1969 | unsigned char tmp; |
1918 | unsigned long flags; | 1970 | unsigned long flags; |
1919 | 1971 | ||
1920 | if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) { | 1972 | if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) { |
1921 | *phase = tmp; | 1973 | *phase = tmp; |
1922 | return -1; | 1974 | return -1; |
1923 | } | 1975 | } |
1924 | 1976 | ||
1925 | if (atari_read_overruns && (p & SR_IO)) { | 1977 | if (atari_read_overruns && (p & SR_IO)) |
1926 | c -= atari_read_overruns; | 1978 | c -= atari_read_overruns; |
1927 | } | ||
1928 | 1979 | ||
1929 | DMA_PRINTK("scsi%d: initializing DMA for %s, %d bytes %s %p\n", | 1980 | DMA_PRINTK("scsi%d: initializing DMA for %s, %d bytes %s %p\n", |
1930 | HOSTNO, (p & SR_IO) ? "reading" : "writing", | 1981 | HOSTNO, (p & SR_IO) ? "reading" : "writing", |
1931 | c, (p & SR_IO) ? "to" : "from", d); | 1982 | c, (p & SR_IO) ? "to" : "from", d); |
1932 | 1983 | ||
1933 | NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); | 1984 | NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); |
1934 | 1985 | ||
1935 | #ifdef REAL_DMA | 1986 | #ifdef REAL_DMA |
1936 | NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY); | 1987 | NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY); |
1937 | #endif /* def REAL_DMA */ | 1988 | #endif /* def REAL_DMA */ |
1938 | 1989 | ||
1939 | if (IS_A_TT()) { | 1990 | if (IS_A_TT()) { |
1940 | /* On the Medusa, it is a must to initialize the DMA before | 1991 | /* On the Medusa, it is a must to initialize the DMA before |
1941 | * starting the NCR. This is also the cleaner way for the TT. | 1992 | * starting the NCR. This is also the cleaner way for the TT. |
1942 | */ | 1993 | */ |
1943 | local_irq_save(flags); | 1994 | local_irq_save(flags); |
1944 | hostdata->dma_len = (p & SR_IO) ? | 1995 | hostdata->dma_len = (p & SR_IO) ? |
1945 | NCR5380_dma_read_setup(instance, d, c) : | 1996 | NCR5380_dma_read_setup(instance, d, c) : |
1946 | NCR5380_dma_write_setup(instance, d, c); | 1997 | NCR5380_dma_write_setup(instance, d, c); |
1947 | local_irq_restore(flags); | 1998 | local_irq_restore(flags); |
1948 | } | 1999 | } |
1949 | 2000 | ||
1950 | if (p & SR_IO) | 2001 | if (p & SR_IO) |
1951 | NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0); | 2002 | NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0); |
1952 | else { | 2003 | else { |
1953 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA); | 2004 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA); |
1954 | NCR5380_write(START_DMA_SEND_REG, 0); | 2005 | NCR5380_write(START_DMA_SEND_REG, 0); |
1955 | } | 2006 | } |
1956 | 2007 | ||
1957 | if (!IS_A_TT()) { | 2008 | if (!IS_A_TT()) { |
1958 | /* On the Falcon, the DMA setup must be done after the last */ | 2009 | /* On the Falcon, the DMA setup must be done after the last */ |
1959 | /* NCR access, else the DMA setup gets trashed! | 2010 | /* NCR access, else the DMA setup gets trashed! |
1960 | */ | 2011 | */ |
1961 | local_irq_save(flags); | 2012 | local_irq_save(flags); |
1962 | hostdata->dma_len = (p & SR_IO) ? | 2013 | hostdata->dma_len = (p & SR_IO) ? |
1963 | NCR5380_dma_read_setup(instance, d, c) : | 2014 | NCR5380_dma_read_setup(instance, d, c) : |
1964 | NCR5380_dma_write_setup(instance, d, c); | 2015 | NCR5380_dma_write_setup(instance, d, c); |
1965 | local_irq_restore(flags); | 2016 | local_irq_restore(flags); |
1966 | } | 2017 | } |
1967 | return 0; | 2018 | return 0; |
1968 | } | 2019 | } |
1969 | #endif /* defined(REAL_DMA) */ | 2020 | #endif /* defined(REAL_DMA) */ |
1970 | 2021 | ||
1971 | /* | 2022 | /* |
1972 | * Function : NCR5380_information_transfer (struct Scsi_Host *instance) | 2023 | * Function : NCR5380_information_transfer (struct Scsi_Host *instance) |
1973 | * | 2024 | * |
1974 | * Purpose : run through the various SCSI phases and do as the target | 2025 | * Purpose : run through the various SCSI phases and do as the target |
1975 | * directs us to. Operates on the currently connected command, | 2026 | * directs us to. Operates on the currently connected command, |
1976 | * instance->connected. | 2027 | * instance->connected. |
1977 | * | 2028 | * |
1978 | * Inputs : instance, instance for which we are doing commands | 2029 | * Inputs : instance, instance for which we are doing commands |
1979 | * | 2030 | * |
1980 | * Side effects : SCSI things happen, the disconnected queue will be | 2031 | * Side effects : SCSI things happen, the disconnected queue will be |
1981 | * modified if a command disconnects, *instance->connected will | 2032 | * modified if a command disconnects, *instance->connected will |
1982 | * change. | 2033 | * change. |
1983 | * | 2034 | * |
1984 | * XXX Note : we need to watch for bus free or a reset condition here | 2035 | * XXX Note : we need to watch for bus free or a reset condition here |
1985 | * to recover from an unexpected bus free condition. | 2036 | * to recover from an unexpected bus free condition. |
1986 | */ | 2037 | */ |
1987 | 2038 | ||
1988 | static void NCR5380_information_transfer (struct Scsi_Host *instance) | 2039 | static void NCR5380_information_transfer(struct Scsi_Host *instance) |
1989 | { | 2040 | { |
1990 | SETUP_HOSTDATA(instance); | 2041 | SETUP_HOSTDATA(instance); |
1991 | unsigned long flags; | 2042 | unsigned long flags; |
1992 | unsigned char msgout = NOP; | 2043 | unsigned char msgout = NOP; |
1993 | int sink = 0; | 2044 | int sink = 0; |
1994 | int len; | 2045 | int len; |
1995 | #if defined(REAL_DMA) | 2046 | #if defined(REAL_DMA) |
1996 | int transfersize; | 2047 | int transfersize; |
1997 | #endif | 2048 | #endif |
1998 | unsigned char *data; | 2049 | unsigned char *data; |
1999 | unsigned char phase, tmp, extended_msg[10], old_phase=0xff; | 2050 | unsigned char phase, tmp, extended_msg[10], old_phase = 0xff; |
2000 | Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected; | 2051 | Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected; |
2052 | |||
2053 | while (1) { | ||
2054 | tmp = NCR5380_read(STATUS_REG); | ||
2055 | /* We only have a valid SCSI phase when REQ is asserted */ | ||
2056 | if (tmp & SR_REQ) { | ||
2057 | phase = (tmp & PHASE_MASK); | ||
2058 | if (phase != old_phase) { | ||
2059 | old_phase = phase; | ||
2060 | NCR_PRINT_PHASE(NDEBUG_INFORMATION); | ||
2061 | } | ||
2001 | 2062 | ||
2002 | while (1) { | 2063 | if (sink && (phase != PHASE_MSGOUT)) { |
2003 | tmp = NCR5380_read(STATUS_REG); | 2064 | NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); |
2004 | /* We only have a valid SCSI phase when REQ is asserted */ | 2065 | |
2005 | if (tmp & SR_REQ) { | 2066 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | |
2006 | phase = (tmp & PHASE_MASK); | 2067 | ICR_ASSERT_ACK); |
2007 | if (phase != old_phase) { | 2068 | while (NCR5380_read(STATUS_REG) & SR_REQ) |
2008 | old_phase = phase; | 2069 | ; |
2009 | NCR_PRINT_PHASE(NDEBUG_INFORMATION); | 2070 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | |
2010 | } | 2071 | ICR_ASSERT_ATN); |
2011 | 2072 | sink = 0; | |
2012 | if (sink && (phase != PHASE_MSGOUT)) { | 2073 | continue; |
2013 | NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); | 2074 | } |
2014 | 2075 | ||
2015 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | | 2076 | switch (phase) { |
2016 | ICR_ASSERT_ACK); | 2077 | case PHASE_DATAOUT: |
2017 | while (NCR5380_read(STATUS_REG) & SR_REQ); | ||
2018 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | | ||
2019 | ICR_ASSERT_ATN); | ||
2020 | sink = 0; | ||
2021 | continue; | ||
2022 | } | ||
2023 | |||
2024 | switch (phase) { | ||
2025 | case PHASE_DATAOUT: | ||
2026 | #if (NDEBUG & NDEBUG_NO_DATAOUT) | 2078 | #if (NDEBUG & NDEBUG_NO_DATAOUT) |
2027 | printk("scsi%d: NDEBUG_NO_DATAOUT set, attempted DATAOUT " | 2079 | printk("scsi%d: NDEBUG_NO_DATAOUT set, attempted DATAOUT " |
2028 | "aborted\n", HOSTNO); | 2080 | "aborted\n", HOSTNO); |
2029 | sink = 1; | 2081 | sink = 1; |
2030 | do_abort(instance); | 2082 | do_abort(instance); |
2031 | cmd->result = DID_ERROR << 16; | 2083 | cmd->result = DID_ERROR << 16; |
2032 | cmd->done(cmd); | 2084 | cmd->done(cmd); |
2033 | return; | 2085 | return; |
2034 | #endif | 2086 | #endif |
2035 | case PHASE_DATAIN: | 2087 | case PHASE_DATAIN: |
2036 | /* | 2088 | /* |
2037 | * If there is no room left in the current buffer in the | 2089 | * If there is no room left in the current buffer in the |
2038 | * scatter-gather list, move onto the next one. | 2090 | * scatter-gather list, move onto the next one. |
2039 | */ | 2091 | */ |
2040 | 2092 | ||
2041 | if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) { | 2093 | if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) { |
2042 | ++cmd->SCp.buffer; | 2094 | ++cmd->SCp.buffer; |
2043 | --cmd->SCp.buffers_residual; | 2095 | --cmd->SCp.buffers_residual; |
2044 | cmd->SCp.this_residual = cmd->SCp.buffer->length; | 2096 | cmd->SCp.this_residual = cmd->SCp.buffer->length; |
2045 | cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+ | 2097 | cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + |
2046 | cmd->SCp.buffer->offset; | 2098 | cmd->SCp.buffer->offset; |
2047 | /* ++roman: Try to merge some scatter-buffers if | 2099 | /* ++roman: Try to merge some scatter-buffers if |
2048 | * they are at contiguous physical addresses. | 2100 | * they are at contiguous physical addresses. |
2049 | */ | 2101 | */ |
2050 | merge_contiguous_buffers( cmd ); | 2102 | merge_contiguous_buffers(cmd); |
2051 | INF_PRINTK("scsi%d: %d bytes and %d buffers left\n", | 2103 | INF_PRINTK("scsi%d: %d bytes and %d buffers left\n", |
2052 | HOSTNO, cmd->SCp.this_residual, | 2104 | HOSTNO, cmd->SCp.this_residual, |
2053 | cmd->SCp.buffers_residual); | 2105 | cmd->SCp.buffers_residual); |
2054 | } | 2106 | } |
2055 | 2107 | ||
2056 | /* | 2108 | /* |
2057 | * The preferred transfer method is going to be | 2109 | * The preferred transfer method is going to be |
2058 | * PSEUDO-DMA for systems that are strictly PIO, | 2110 | * PSEUDO-DMA for systems that are strictly PIO, |
2059 | * since we can let the hardware do the handshaking. | 2111 | * since we can let the hardware do the handshaking. |
2060 | * | 2112 | * |
2061 | * For this to work, we need to know the transfersize | 2113 | * For this to work, we need to know the transfersize |
2062 | * ahead of time, since the pseudo-DMA code will sit | 2114 | * ahead of time, since the pseudo-DMA code will sit |
2063 | * in an unconditional loop. | 2115 | * in an unconditional loop. |
2064 | */ | 2116 | */ |
2065 | 2117 | ||
2066 | /* ++roman: I suggest, this should be | 2118 | /* ++roman: I suggest, this should be |
2067 | * #if def(REAL_DMA) | 2119 | * #if def(REAL_DMA) |
2068 | * instead of leaving REAL_DMA out. | 2120 | * instead of leaving REAL_DMA out. |
2069 | */ | 2121 | */ |
2070 | 2122 | ||
2071 | #if defined(REAL_DMA) | 2123 | #if defined(REAL_DMA) |
2072 | if (!cmd->device->borken && | 2124 | if (!cmd->device->borken && |
2073 | (transfersize = NCR5380_dma_xfer_len(instance,cmd,phase)) > 31) { | 2125 | (transfersize = NCR5380_dma_xfer_len(instance,cmd,phase)) > 31) { |
2074 | len = transfersize; | 2126 | len = transfersize; |
2075 | cmd->SCp.phase = phase; | 2127 | cmd->SCp.phase = phase; |
2076 | if (NCR5380_transfer_dma(instance, &phase, | 2128 | if (NCR5380_transfer_dma(instance, &phase, |
2077 | &len, (unsigned char **) &cmd->SCp.ptr)) { | 2129 | &len, (unsigned char **)&cmd->SCp.ptr)) { |
2078 | /* | 2130 | /* |
2079 | * If the watchdog timer fires, all future | 2131 | * If the watchdog timer fires, all future |
2080 | * accesses to this device will use the | 2132 | * accesses to this device will use the |
2081 | * polled-IO. */ | 2133 | * polled-IO. */ |
2082 | printk(KERN_NOTICE "scsi%d: switching target %d " | 2134 | printk(KERN_NOTICE "scsi%d: switching target %d " |
2083 | "lun %d to slow handshake\n", HOSTNO, | 2135 | "lun %d to slow handshake\n", HOSTNO, |
2084 | cmd->device->id, cmd->device->lun); | 2136 | cmd->device->id, cmd->device->lun); |
2085 | cmd->device->borken = 1; | 2137 | cmd->device->borken = 1; |
2086 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | | 2138 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | |
2087 | ICR_ASSERT_ATN); | 2139 | ICR_ASSERT_ATN); |
2088 | sink = 1; | 2140 | sink = 1; |
2089 | do_abort(instance); | 2141 | do_abort(instance); |
2090 | cmd->result = DID_ERROR << 16; | 2142 | cmd->result = DID_ERROR << 16; |
2091 | cmd->done(cmd); | 2143 | cmd->done(cmd); |
2092 | /* XXX - need to source or sink data here, as appropriate */ | 2144 | /* XXX - need to source or sink data here, as appropriate */ |
2093 | } else { | 2145 | } else { |
2094 | #ifdef REAL_DMA | 2146 | #ifdef REAL_DMA |
2095 | /* ++roman: When using real DMA, | 2147 | /* ++roman: When using real DMA, |
2096 | * information_transfer() should return after | 2148 | * information_transfer() should return after |
2097 | * starting DMA since it has nothing more to | 2149 | * starting DMA since it has nothing more to |
2098 | * do. | 2150 | * do. |
2099 | */ | 2151 | */ |
2100 | return; | 2152 | return; |
2101 | #else | 2153 | #else |
2102 | cmd->SCp.this_residual -= transfersize - len; | 2154 | cmd->SCp.this_residual -= transfersize - len; |
2103 | #endif | 2155 | #endif |
2104 | } | 2156 | } |
2105 | } else | 2157 | } else |
2106 | #endif /* defined(REAL_DMA) */ | 2158 | #endif /* defined(REAL_DMA) */ |
2107 | NCR5380_transfer_pio(instance, &phase, | 2159 | NCR5380_transfer_pio(instance, &phase, |
2108 | (int *) &cmd->SCp.this_residual, (unsigned char **) | 2160 | (int *)&cmd->SCp.this_residual, |
2109 | &cmd->SCp.ptr); | 2161 | (unsigned char **)&cmd->SCp.ptr); |
2110 | break; | 2162 | break; |
2111 | case PHASE_MSGIN: | 2163 | case PHASE_MSGIN: |
2112 | len = 1; | 2164 | len = 1; |
2113 | data = &tmp; | 2165 | data = &tmp; |
2114 | NCR5380_write(SELECT_ENABLE_REG, 0); /* disable reselects */ | 2166 | NCR5380_write(SELECT_ENABLE_REG, 0); /* disable reselects */ |
2115 | NCR5380_transfer_pio(instance, &phase, &len, &data); | 2167 | NCR5380_transfer_pio(instance, &phase, &len, &data); |
2116 | cmd->SCp.Message = tmp; | 2168 | cmd->SCp.Message = tmp; |
2117 | 2169 | ||
2118 | switch (tmp) { | 2170 | switch (tmp) { |
2119 | /* | 2171 | /* |
2120 | * Linking lets us reduce the time required to get the | 2172 | * Linking lets us reduce the time required to get the |
2121 | * next command out to the device, hopefully this will | 2173 | * next command out to the device, hopefully this will |
2122 | * mean we don't waste another revolution due to the delays | 2174 | * mean we don't waste another revolution due to the delays |
2123 | * required by ARBITRATION and another SELECTION. | 2175 | * required by ARBITRATION and another SELECTION. |
2124 | * | 2176 | * |
2125 | * In the current implementation proposal, low level drivers | 2177 | * In the current implementation proposal, low level drivers |
2126 | * merely have to start the next command, pointed to by | 2178 | * merely have to start the next command, pointed to by |
2127 | * next_link, done() is called as with unlinked commands. | 2179 | * next_link, done() is called as with unlinked commands. |
2128 | */ | 2180 | */ |
2129 | #ifdef LINKED | 2181 | #ifdef LINKED |
2130 | case LINKED_CMD_COMPLETE: | 2182 | case LINKED_CMD_COMPLETE: |
2131 | case LINKED_FLG_CMD_COMPLETE: | 2183 | case LINKED_FLG_CMD_COMPLETE: |
2132 | /* Accept message by clearing ACK */ | 2184 | /* Accept message by clearing ACK */ |
2133 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 2185 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
2134 | 2186 | ||
2135 | LNK_PRINTK("scsi%d: target %d lun %d linked command " | 2187 | LNK_PRINTK("scsi%d: target %d lun %d linked command " |
2136 | "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun); | 2188 | "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun); |
2137 | 2189 | ||
2138 | /* Enable reselect interrupts */ | 2190 | /* Enable reselect interrupts */ |
2139 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | 2191 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); |
2140 | /* | 2192 | /* |
2141 | * Sanity check : A linked command should only terminate | 2193 | * Sanity check : A linked command should only terminate |
2142 | * with one of these messages if there are more linked | 2194 | * with one of these messages if there are more linked |
2143 | * commands available. | 2195 | * commands available. |
2144 | */ | 2196 | */ |
2145 | 2197 | ||
2146 | if (!cmd->next_link) { | 2198 | if (!cmd->next_link) { |
2147 | printk(KERN_NOTICE "scsi%d: target %d lun %d " | 2199 | printk(KERN_NOTICE "scsi%d: target %d lun %d " |
2148 | "linked command complete, no next_link\n", | 2200 | "linked command complete, no next_link\n", |
2149 | HOSTNO, cmd->device->id, cmd->device->lun); | 2201 | HOSTNO, cmd->device->id, cmd->device->lun); |
2150 | sink = 1; | 2202 | sink = 1; |
2151 | do_abort (instance); | 2203 | do_abort(instance); |
2152 | return; | 2204 | return; |
2153 | } | 2205 | } |
2154 | 2206 | ||
2155 | initialize_SCp(cmd->next_link); | 2207 | initialize_SCp(cmd->next_link); |
2156 | /* The next command is still part of this process; copy it | 2208 | /* The next command is still part of this process; copy it |
2157 | * and don't free it! */ | 2209 | * and don't free it! */ |
2158 | cmd->next_link->tag = cmd->tag; | 2210 | cmd->next_link->tag = cmd->tag; |
2159 | cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); | 2211 | cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); |
2160 | LNK_PRINTK("scsi%d: target %d lun %d linked request " | 2212 | LNK_PRINTK("scsi%d: target %d lun %d linked request " |
2161 | "done, calling scsi_done().\n", | 2213 | "done, calling scsi_done().\n", |
2162 | HOSTNO, cmd->device->id, cmd->device->lun); | 2214 | HOSTNO, cmd->device->id, cmd->device->lun); |
2163 | #ifdef NCR5380_STATS | 2215 | #ifdef NCR5380_STATS |
2164 | collect_stats(hostdata, cmd); | 2216 | collect_stats(hostdata, cmd); |
2165 | #endif | 2217 | #endif |
2166 | cmd->scsi_done(cmd); | 2218 | cmd->scsi_done(cmd); |
2167 | cmd = hostdata->connected; | 2219 | cmd = hostdata->connected; |
2168 | break; | 2220 | break; |
2169 | #endif /* def LINKED */ | 2221 | #endif /* def LINKED */ |
2170 | case ABORT: | 2222 | case ABORT: |
2171 | case COMMAND_COMPLETE: | 2223 | case COMMAND_COMPLETE: |
2172 | /* Accept message by clearing ACK */ | 2224 | /* Accept message by clearing ACK */ |
2173 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 2225 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
2174 | /* ++guenther: possible race with Falcon locking */ | 2226 | /* ++guenther: possible race with Falcon locking */ |
2175 | falcon_dont_release++; | 2227 | falcon_dont_release++; |
2176 | hostdata->connected = NULL; | 2228 | hostdata->connected = NULL; |
2177 | QU_PRINTK("scsi%d: command for target %d, lun %d " | 2229 | QU_PRINTK("scsi%d: command for target %d, lun %d " |
2178 | "completed\n", HOSTNO, cmd->device->id, cmd->device->lun); | 2230 | "completed\n", HOSTNO, cmd->device->id, cmd->device->lun); |
2179 | #ifdef SUPPORT_TAGS | 2231 | #ifdef SUPPORT_TAGS |
2180 | cmd_free_tag( cmd ); | 2232 | cmd_free_tag(cmd); |
2181 | if (status_byte(cmd->SCp.Status) == QUEUE_FULL) { | 2233 | if (status_byte(cmd->SCp.Status) == QUEUE_FULL) { |
2182 | /* Turn a QUEUE FULL status into BUSY, I think the | 2234 | /* Turn a QUEUE FULL status into BUSY, I think the |
2183 | * mid level cannot handle QUEUE FULL :-( (The | 2235 | * mid level cannot handle QUEUE FULL :-( (The |
2184 | * command is retried after BUSY). Also update our | 2236 | * command is retried after BUSY). Also update our |
2185 | * queue size to the number of currently issued | 2237 | * queue size to the number of currently issued |
2186 | * commands now. | 2238 | * commands now. |
2187 | */ | 2239 | */ |
2188 | /* ++Andreas: the mid level code knows about | 2240 | /* ++Andreas: the mid level code knows about |
2189 | QUEUE_FULL now. */ | 2241 | QUEUE_FULL now. */ |
2190 | TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; | 2242 | TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; |
2191 | TAG_PRINTK("scsi%d: target %d lun %d returned " | 2243 | TAG_PRINTK("scsi%d: target %d lun %d returned " |
2192 | "QUEUE_FULL after %d commands\n", | 2244 | "QUEUE_FULL after %d commands\n", |
2193 | HOSTNO, cmd->device->id, cmd->device->lun, | 2245 | HOSTNO, cmd->device->id, cmd->device->lun, |
2194 | ta->nr_allocated); | 2246 | ta->nr_allocated); |
2195 | if (ta->queue_size > ta->nr_allocated) | 2247 | if (ta->queue_size > ta->nr_allocated) |
2196 | ta->nr_allocated = ta->queue_size; | 2248 | ta->nr_allocated = ta->queue_size; |
2197 | } | 2249 | } |
2198 | #else | 2250 | #else |
2199 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); | 2251 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); |
2200 | #endif | 2252 | #endif |
2201 | /* Enable reselect interrupts */ | 2253 | /* Enable reselect interrupts */ |
2202 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | 2254 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); |
2203 | 2255 | ||
2204 | /* | 2256 | /* |
2205 | * I'm not sure what the correct thing to do here is : | 2257 | * I'm not sure what the correct thing to do here is : |
2206 | * | 2258 | * |
2207 | * If the command that just executed is NOT a request | 2259 | * If the command that just executed is NOT a request |
2208 | * sense, the obvious thing to do is to set the result | 2260 | * sense, the obvious thing to do is to set the result |
2209 | * code to the values of the stored parameters. | 2261 | * code to the values of the stored parameters. |
2210 | * | 2262 | * |
2211 | * If it was a REQUEST SENSE command, we need some way to | 2263 | * If it was a REQUEST SENSE command, we need some way to |
2212 | * differentiate between the failure code of the original | 2264 | * differentiate between the failure code of the original |
2213 | * and the failure code of the REQUEST sense - the obvious | 2265 | * and the failure code of the REQUEST sense - the obvious |
2214 | * case is success, where we fall through and leave the | 2266 | * case is success, where we fall through and leave the |
2215 | * result code unchanged. | 2267 | * result code unchanged. |
2216 | * | 2268 | * |
2217 | * The non-obvious place is where the REQUEST SENSE failed | 2269 | * The non-obvious place is where the REQUEST SENSE failed |
2218 | */ | 2270 | */ |
2219 | 2271 | ||
2220 | if (cmd->cmnd[0] != REQUEST_SENSE) | 2272 | if (cmd->cmnd[0] != REQUEST_SENSE) |
2221 | cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); | 2273 | cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); |
2222 | else if (status_byte(cmd->SCp.Status) != GOOD) | 2274 | else if (status_byte(cmd->SCp.Status) != GOOD) |
2223 | cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); | 2275 | cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); |
2224 | |||
2225 | #ifdef AUTOSENSE | ||
2226 | if ((cmd->cmnd[0] != REQUEST_SENSE) && | ||
2227 | (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { | ||
2228 | ASEN_PRINTK("scsi%d: performing request sense\n", | ||
2229 | HOSTNO); | ||
2230 | cmd->cmnd[0] = REQUEST_SENSE; | ||
2231 | cmd->cmnd[1] &= 0xe0; | ||
2232 | cmd->cmnd[2] = 0; | ||
2233 | cmd->cmnd[3] = 0; | ||
2234 | cmd->cmnd[4] = sizeof(cmd->sense_buffer); | ||
2235 | cmd->cmnd[5] = 0; | ||
2236 | cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); | ||
2237 | |||
2238 | cmd->use_sg = 0; | ||
2239 | /* this is initialized from initialize_SCp | ||
2240 | cmd->SCp.buffer = NULL; | ||
2241 | cmd->SCp.buffers_residual = 0; | ||
2242 | */ | ||
2243 | cmd->request_buffer = (char *) cmd->sense_buffer; | ||
2244 | cmd->request_bufflen = sizeof(cmd->sense_buffer); | ||
2245 | 2276 | ||
2246 | local_irq_save(flags); | 2277 | #ifdef AUTOSENSE |
2247 | LIST(cmd,hostdata->issue_queue); | 2278 | if ((cmd->cmnd[0] != REQUEST_SENSE) && |
2248 | NEXT(cmd) = hostdata->issue_queue; | 2279 | (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { |
2249 | hostdata->issue_queue = (Scsi_Cmnd *) cmd; | 2280 | ASEN_PRINTK("scsi%d: performing request sense\n", HOSTNO); |
2250 | local_irq_restore(flags); | 2281 | cmd->cmnd[0] = REQUEST_SENSE; |
2251 | QU_PRINTK("scsi%d: REQUEST SENSE added to head of " | 2282 | cmd->cmnd[1] &= 0xe0; |
2252 | "issue queue\n", H_NO(cmd)); | 2283 | cmd->cmnd[2] = 0; |
2253 | } else | 2284 | cmd->cmnd[3] = 0; |
2285 | cmd->cmnd[4] = sizeof(cmd->sense_buffer); | ||
2286 | cmd->cmnd[5] = 0; | ||
2287 | cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); | ||
2288 | |||
2289 | cmd->use_sg = 0; | ||
2290 | /* this is initialized from initialize_SCp | ||
2291 | cmd->SCp.buffer = NULL; | ||
2292 | cmd->SCp.buffers_residual = 0; | ||
2293 | */ | ||
2294 | cmd->request_buffer = (char *) cmd->sense_buffer; | ||
2295 | cmd->request_bufflen = sizeof(cmd->sense_buffer); | ||
2296 | |||
2297 | local_irq_save(flags); | ||
2298 | LIST(cmd,hostdata->issue_queue); | ||
2299 | SET_NEXT(cmd, hostdata->issue_queue); | ||
2300 | hostdata->issue_queue = (Scsi_Cmnd *) cmd; | ||
2301 | local_irq_restore(flags); | ||
2302 | QU_PRINTK("scsi%d: REQUEST SENSE added to head of " | ||
2303 | "issue queue\n", H_NO(cmd)); | ||
2304 | } else | ||
2254 | #endif /* def AUTOSENSE */ | 2305 | #endif /* def AUTOSENSE */ |
2255 | { | 2306 | { |
2256 | #ifdef NCR5380_STATS | 2307 | #ifdef NCR5380_STATS |
2257 | collect_stats(hostdata, cmd); | 2308 | collect_stats(hostdata, cmd); |
2258 | #endif | 2309 | #endif |
2259 | cmd->scsi_done(cmd); | 2310 | cmd->scsi_done(cmd); |
2260 | } | 2311 | } |
2261 | 2312 | ||
2262 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | 2313 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); |
2263 | /* | 2314 | /* |
2264 | * Restore phase bits to 0 so an interrupted selection, | 2315 | * Restore phase bits to 0 so an interrupted selection, |
2265 | * arbitration can resume. | 2316 | * arbitration can resume. |
2266 | */ | 2317 | */ |
2267 | NCR5380_write(TARGET_COMMAND_REG, 0); | 2318 | NCR5380_write(TARGET_COMMAND_REG, 0); |
2268 | 2319 | ||
2269 | while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected) | 2320 | while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected) |
2270 | barrier(); | 2321 | barrier(); |
2271 | 2322 | ||
2272 | falcon_dont_release--; | 2323 | falcon_dont_release--; |
2273 | /* ++roman: For Falcon SCSI, release the lock on the | 2324 | /* ++roman: For Falcon SCSI, release the lock on the |
2274 | * ST-DMA here if no other commands are waiting on the | 2325 | * ST-DMA here if no other commands are waiting on the |
2275 | * disconnected queue. | 2326 | * disconnected queue. |
2276 | */ | 2327 | */ |
2277 | falcon_release_lock_if_possible( hostdata ); | 2328 | falcon_release_lock_if_possible(hostdata); |
2278 | return; | 2329 | return; |
2279 | case MESSAGE_REJECT: | 2330 | case MESSAGE_REJECT: |
2280 | /* Accept message by clearing ACK */ | 2331 | /* Accept message by clearing ACK */ |
2281 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 2332 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
2282 | /* Enable reselect interrupts */ | 2333 | /* Enable reselect interrupts */ |
2283 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | 2334 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); |
2284 | switch (hostdata->last_message) { | 2335 | switch (hostdata->last_message) { |
2285 | case HEAD_OF_QUEUE_TAG: | 2336 | case HEAD_OF_QUEUE_TAG: |
2286 | case ORDERED_QUEUE_TAG: | 2337 | case ORDERED_QUEUE_TAG: |
2287 | case SIMPLE_QUEUE_TAG: | 2338 | case SIMPLE_QUEUE_TAG: |
2288 | /* The target obviously doesn't support tagged | 2339 | /* The target obviously doesn't support tagged |
2289 | * queuing, even though it announced this ability in | 2340 | * queuing, even though it announced this ability in |
2290 | * its INQUIRY data ?!? (maybe only this LUN?) Ok, | 2341 | * its INQUIRY data ?!? (maybe only this LUN?) Ok, |
2291 | * clear 'tagged_supported' and lock the LUN, since | 2342 | * clear 'tagged_supported' and lock the LUN, since |
2292 | * the command is treated as untagged further on. | 2343 | * the command is treated as untagged further on. |
2293 | */ | 2344 | */ |
2294 | cmd->device->tagged_supported = 0; | 2345 | cmd->device->tagged_supported = 0; |
2295 | hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); | 2346 | hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); |
2296 | cmd->tag = TAG_NONE; | 2347 | cmd->tag = TAG_NONE; |
2297 | TAG_PRINTK("scsi%d: target %d lun %d rejected " | 2348 | TAG_PRINTK("scsi%d: target %d lun %d rejected " |
2298 | "QUEUE_TAG message; tagged queuing " | 2349 | "QUEUE_TAG message; tagged queuing " |
2299 | "disabled\n", | 2350 | "disabled\n", |
2300 | HOSTNO, cmd->device->id, cmd->device->lun); | 2351 | HOSTNO, cmd->device->id, cmd->device->lun); |
2301 | break; | 2352 | break; |
2302 | } | 2353 | } |
2303 | break; | 2354 | break; |
2304 | case DISCONNECT: | 2355 | case DISCONNECT: |
2305 | /* Accept message by clearing ACK */ | 2356 | /* Accept message by clearing ACK */ |
2306 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 2357 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
2307 | local_irq_save(flags); | 2358 | local_irq_save(flags); |
2308 | cmd->device->disconnect = 1; | 2359 | cmd->device->disconnect = 1; |
2309 | LIST(cmd,hostdata->disconnected_queue); | 2360 | LIST(cmd,hostdata->disconnected_queue); |
2310 | NEXT(cmd) = hostdata->disconnected_queue; | 2361 | SET_NEXT(cmd, hostdata->disconnected_queue); |
2311 | hostdata->connected = NULL; | 2362 | hostdata->connected = NULL; |
2312 | hostdata->disconnected_queue = cmd; | 2363 | hostdata->disconnected_queue = cmd; |
2313 | local_irq_restore(flags); | 2364 | local_irq_restore(flags); |
2314 | QU_PRINTK("scsi%d: command for target %d lun %d was " | 2365 | QU_PRINTK("scsi%d: command for target %d lun %d was " |
2315 | "moved from connected to the " | 2366 | "moved from connected to the " |
2316 | "disconnected_queue\n", HOSTNO, | 2367 | "disconnected_queue\n", HOSTNO, |
2317 | cmd->device->id, cmd->device->lun); | 2368 | cmd->device->id, cmd->device->lun); |
2318 | /* | 2369 | /* |
2319 | * Restore phase bits to 0 so an interrupted selection, | 2370 | * Restore phase bits to 0 so an interrupted selection, |
2320 | * arbitration can resume. | 2371 | * arbitration can resume. |
2321 | */ | 2372 | */ |
2322 | NCR5380_write(TARGET_COMMAND_REG, 0); | 2373 | NCR5380_write(TARGET_COMMAND_REG, 0); |
2323 | 2374 | ||
2324 | /* Enable reselect interrupts */ | 2375 | /* Enable reselect interrupts */ |
2325 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | 2376 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); |
2326 | /* Wait for bus free to avoid nasty timeouts */ | 2377 | /* Wait for bus free to avoid nasty timeouts */ |
2327 | while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected) | 2378 | while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected) |
2328 | barrier(); | 2379 | barrier(); |
2329 | return; | 2380 | return; |
2330 | /* | 2381 | /* |
2331 | * The SCSI data pointer is *IMPLICITLY* saved on a disconnect | 2382 | * The SCSI data pointer is *IMPLICITLY* saved on a disconnect |
2332 | * operation, in violation of the SCSI spec so we can safely | 2383 | * operation, in violation of the SCSI spec so we can safely |
2333 | * ignore SAVE/RESTORE pointers calls. | 2384 | * ignore SAVE/RESTORE pointers calls. |
2334 | * | 2385 | * |
2335 | * Unfortunately, some disks violate the SCSI spec and | 2386 | * Unfortunately, some disks violate the SCSI spec and |
2336 | * don't issue the required SAVE_POINTERS message before | 2387 | * don't issue the required SAVE_POINTERS message before |
2337 | * disconnecting, and we have to break spec to remain | 2388 | * disconnecting, and we have to break spec to remain |
2338 | * compatible. | 2389 | * compatible. |
2339 | */ | 2390 | */ |
2340 | case SAVE_POINTERS: | 2391 | case SAVE_POINTERS: |
2341 | case RESTORE_POINTERS: | 2392 | case RESTORE_POINTERS: |
2342 | /* Accept message by clearing ACK */ | 2393 | /* Accept message by clearing ACK */ |
2343 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 2394 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
2344 | /* Enable reselect interrupts */ | 2395 | /* Enable reselect interrupts */ |
2345 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | 2396 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); |
2346 | break; | 2397 | break; |
2347 | case EXTENDED_MESSAGE: | 2398 | case EXTENDED_MESSAGE: |
2348 | /* | 2399 | /* |
2349 | * Extended messages are sent in the following format : | 2400 | * Extended messages are sent in the following format : |
2350 | * Byte | 2401 | * Byte |
2351 | * 0 EXTENDED_MESSAGE == 1 | 2402 | * 0 EXTENDED_MESSAGE == 1 |
2352 | * 1 length (includes one byte for code, doesn't | 2403 | * 1 length (includes one byte for code, doesn't |
2353 | * include first two bytes) | 2404 | * include first two bytes) |
2354 | * 2 code | 2405 | * 2 code |
2355 | * 3..length+1 arguments | 2406 | * 3..length+1 arguments |
2356 | * | 2407 | * |
2357 | * Start the extended message buffer with the EXTENDED_MESSAGE | 2408 | * Start the extended message buffer with the EXTENDED_MESSAGE |
2358 | * byte, since spi_print_msg() wants the whole thing. | 2409 | * byte, since spi_print_msg() wants the whole thing. |
2359 | */ | 2410 | */ |
2360 | extended_msg[0] = EXTENDED_MESSAGE; | 2411 | extended_msg[0] = EXTENDED_MESSAGE; |
2361 | /* Accept first byte by clearing ACK */ | 2412 | /* Accept first byte by clearing ACK */ |
2362 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 2413 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
2363 | 2414 | ||
2364 | EXT_PRINTK("scsi%d: receiving extended message\n", HOSTNO); | 2415 | EXT_PRINTK("scsi%d: receiving extended message\n", HOSTNO); |
2365 | 2416 | ||
2366 | len = 2; | 2417 | len = 2; |
2367 | data = extended_msg + 1; | 2418 | data = extended_msg + 1; |
2368 | phase = PHASE_MSGIN; | 2419 | phase = PHASE_MSGIN; |
2369 | NCR5380_transfer_pio(instance, &phase, &len, &data); | 2420 | NCR5380_transfer_pio(instance, &phase, &len, &data); |
2370 | EXT_PRINTK("scsi%d: length=%d, code=0x%02x\n", HOSTNO, | 2421 | EXT_PRINTK("scsi%d: length=%d, code=0x%02x\n", HOSTNO, |
2371 | (int)extended_msg[1], (int)extended_msg[2]); | 2422 | (int)extended_msg[1], (int)extended_msg[2]); |
2372 | 2423 | ||
2373 | if (!len && extended_msg[1] <= | 2424 | if (!len && extended_msg[1] <= |
2374 | (sizeof (extended_msg) - 1)) { | 2425 | (sizeof(extended_msg) - 1)) { |
2375 | /* Accept third byte by clearing ACK */ | 2426 | /* Accept third byte by clearing ACK */ |
2376 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 2427 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
2377 | len = extended_msg[1] - 1; | 2428 | len = extended_msg[1] - 1; |
2378 | data = extended_msg + 3; | 2429 | data = extended_msg + 3; |
2379 | phase = PHASE_MSGIN; | 2430 | phase = PHASE_MSGIN; |
2380 | 2431 | ||
2381 | NCR5380_transfer_pio(instance, &phase, &len, &data); | 2432 | NCR5380_transfer_pio(instance, &phase, &len, &data); |
2382 | EXT_PRINTK("scsi%d: message received, residual %d\n", | 2433 | EXT_PRINTK("scsi%d: message received, residual %d\n", |
2383 | HOSTNO, len); | 2434 | HOSTNO, len); |
2384 | 2435 | ||
2385 | switch (extended_msg[2]) { | 2436 | switch (extended_msg[2]) { |
2386 | case EXTENDED_SDTR: | 2437 | case EXTENDED_SDTR: |
2387 | case EXTENDED_WDTR: | 2438 | case EXTENDED_WDTR: |
2388 | case EXTENDED_MODIFY_DATA_POINTER: | 2439 | case EXTENDED_MODIFY_DATA_POINTER: |
2389 | case EXTENDED_EXTENDED_IDENTIFY: | 2440 | case EXTENDED_EXTENDED_IDENTIFY: |
2390 | tmp = 0; | 2441 | tmp = 0; |
2391 | } | 2442 | } |
2392 | } else if (len) { | 2443 | } else if (len) { |
2393 | printk(KERN_NOTICE "scsi%d: error receiving " | 2444 | printk(KERN_NOTICE "scsi%d: error receiving " |
2394 | "extended message\n", HOSTNO); | 2445 | "extended message\n", HOSTNO); |
2395 | tmp = 0; | 2446 | tmp = 0; |
2396 | } else { | 2447 | } else { |
2397 | printk(KERN_NOTICE "scsi%d: extended message " | 2448 | printk(KERN_NOTICE "scsi%d: extended message " |
2398 | "code %02x length %d is too long\n", | 2449 | "code %02x length %d is too long\n", |
2399 | HOSTNO, extended_msg[2], extended_msg[1]); | 2450 | HOSTNO, extended_msg[2], extended_msg[1]); |
2400 | tmp = 0; | 2451 | tmp = 0; |
2401 | } | 2452 | } |
2402 | /* Fall through to reject message */ | 2453 | /* Fall through to reject message */ |
2403 | 2454 | ||
2404 | /* | 2455 | /* |
2405 | * If we get something weird that we aren't expecting, | 2456 | * If we get something weird that we aren't expecting, |
2406 | * reject it. | 2457 | * reject it. |
2407 | */ | 2458 | */ |
2408 | default: | 2459 | default: |
2409 | if (!tmp) { | 2460 | if (!tmp) { |
2410 | printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO); | 2461 | printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO); |
2411 | spi_print_msg(extended_msg); | 2462 | spi_print_msg(extended_msg); |
2412 | printk("\n"); | 2463 | printk("\n"); |
2413 | } else if (tmp != EXTENDED_MESSAGE) | 2464 | } else if (tmp != EXTENDED_MESSAGE) |
2414 | printk(KERN_DEBUG "scsi%d: rejecting unknown " | 2465 | printk(KERN_DEBUG "scsi%d: rejecting unknown " |
2415 | "message %02x from target %d, lun %d\n", | 2466 | "message %02x from target %d, lun %d\n", |
2416 | HOSTNO, tmp, cmd->device->id, cmd->device->lun); | 2467 | HOSTNO, tmp, cmd->device->id, cmd->device->lun); |
2417 | else | 2468 | else |
2418 | printk(KERN_DEBUG "scsi%d: rejecting unknown " | 2469 | printk(KERN_DEBUG "scsi%d: rejecting unknown " |
2419 | "extended message " | 2470 | "extended message " |
2420 | "code %02x, length %d from target %d, lun %d\n", | 2471 | "code %02x, length %d from target %d, lun %d\n", |
2421 | HOSTNO, extended_msg[1], extended_msg[0], | 2472 | HOSTNO, extended_msg[1], extended_msg[0], |
2422 | cmd->device->id, cmd->device->lun); | 2473 | cmd->device->id, cmd->device->lun); |
2423 | 2474 | ||
2424 | 2475 | ||
2425 | msgout = MESSAGE_REJECT; | 2476 | msgout = MESSAGE_REJECT; |
2426 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | | 2477 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); |
2427 | ICR_ASSERT_ATN); | 2478 | break; |
2428 | break; | 2479 | } /* switch (tmp) */ |
2429 | } /* switch (tmp) */ | 2480 | break; |
2430 | break; | 2481 | case PHASE_MSGOUT: |
2431 | case PHASE_MSGOUT: | 2482 | len = 1; |
2432 | len = 1; | 2483 | data = &msgout; |
2433 | data = &msgout; | 2484 | hostdata->last_message = msgout; |
2434 | hostdata->last_message = msgout; | 2485 | NCR5380_transfer_pio(instance, &phase, &len, &data); |
2435 | NCR5380_transfer_pio(instance, &phase, &len, &data); | 2486 | if (msgout == ABORT) { |
2436 | if (msgout == ABORT) { | ||
2437 | #ifdef SUPPORT_TAGS | 2487 | #ifdef SUPPORT_TAGS |
2438 | cmd_free_tag( cmd ); | 2488 | cmd_free_tag(cmd); |
2439 | #else | 2489 | #else |
2440 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); | 2490 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); |
2441 | #endif | 2491 | #endif |
2442 | hostdata->connected = NULL; | 2492 | hostdata->connected = NULL; |
2443 | cmd->result = DID_ERROR << 16; | 2493 | cmd->result = DID_ERROR << 16; |
2444 | #ifdef NCR5380_STATS | 2494 | #ifdef NCR5380_STATS |
2445 | collect_stats(hostdata, cmd); | 2495 | collect_stats(hostdata, cmd); |
2446 | #endif | 2496 | #endif |
2447 | cmd->scsi_done(cmd); | 2497 | cmd->scsi_done(cmd); |
2448 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | 2498 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); |
2449 | falcon_release_lock_if_possible( hostdata ); | 2499 | falcon_release_lock_if_possible(hostdata); |
2450 | return; | 2500 | return; |
2451 | } | 2501 | } |
2452 | msgout = NOP; | 2502 | msgout = NOP; |
2453 | break; | 2503 | break; |
2454 | case PHASE_CMDOUT: | 2504 | case PHASE_CMDOUT: |
2455 | len = cmd->cmd_len; | 2505 | len = cmd->cmd_len; |
2456 | data = cmd->cmnd; | 2506 | data = cmd->cmnd; |
2457 | /* | 2507 | /* |
2458 | * XXX for performance reasons, on machines with a | 2508 | * XXX for performance reasons, on machines with a |
2459 | * PSEUDO-DMA architecture we should probably | 2509 | * PSEUDO-DMA architecture we should probably |
2460 | * use the dma transfer function. | 2510 | * use the dma transfer function. |
2461 | */ | 2511 | */ |
2462 | NCR5380_transfer_pio(instance, &phase, &len, | 2512 | NCR5380_transfer_pio(instance, &phase, &len, &data); |
2463 | &data); | 2513 | break; |
2464 | break; | 2514 | case PHASE_STATIN: |
2465 | case PHASE_STATIN: | 2515 | len = 1; |
2466 | len = 1; | 2516 | data = &tmp; |
2467 | data = &tmp; | 2517 | NCR5380_transfer_pio(instance, &phase, &len, &data); |
2468 | NCR5380_transfer_pio(instance, &phase, &len, &data); | 2518 | cmd->SCp.Status = tmp; |
2469 | cmd->SCp.Status = tmp; | 2519 | break; |
2470 | break; | 2520 | default: |
2471 | default: | 2521 | printk("scsi%d: unknown phase\n", HOSTNO); |
2472 | printk("scsi%d: unknown phase\n", HOSTNO); | 2522 | NCR_PRINT(NDEBUG_ANY); |
2473 | NCR_PRINT(NDEBUG_ANY); | 2523 | } /* switch(phase) */ |
2474 | } /* switch(phase) */ | 2524 | } /* if (tmp * SR_REQ) */ |
2475 | } /* if (tmp * SR_REQ) */ | 2525 | } /* while (1) */ |
2476 | } /* while (1) */ | ||
2477 | } | 2526 | } |
2478 | 2527 | ||
2479 | /* | 2528 | /* |
2480 | * Function : void NCR5380_reselect (struct Scsi_Host *instance) | 2529 | * Function : void NCR5380_reselect (struct Scsi_Host *instance) |
2481 | * | 2530 | * |
2482 | * Purpose : does reselection, initializing the instance->connected | 2531 | * Purpose : does reselection, initializing the instance->connected |
2483 | * field to point to the Scsi_Cmnd for which the I_T_L or I_T_L_Q | 2532 | * field to point to the Scsi_Cmnd for which the I_T_L or I_T_L_Q |
2484 | * nexus has been reestablished, | 2533 | * nexus has been reestablished, |
2485 | * | 2534 | * |
2486 | * Inputs : instance - this instance of the NCR5380. | 2535 | * Inputs : instance - this instance of the NCR5380. |
2487 | * | 2536 | * |
2488 | */ | 2537 | */ |
2489 | 2538 | ||
2490 | 2539 | ||
2491 | static void NCR5380_reselect (struct Scsi_Host *instance) | 2540 | static void NCR5380_reselect(struct Scsi_Host *instance) |
2492 | { | 2541 | { |
2493 | SETUP_HOSTDATA(instance); | 2542 | SETUP_HOSTDATA(instance); |
2494 | unsigned char target_mask; | 2543 | unsigned char target_mask; |
2495 | unsigned char lun, phase; | 2544 | unsigned char lun, phase; |
2496 | int len; | 2545 | int len; |
2497 | #ifdef SUPPORT_TAGS | 2546 | #ifdef SUPPORT_TAGS |
2498 | unsigned char tag; | 2547 | unsigned char tag; |
2499 | #endif | 2548 | #endif |
2500 | unsigned char msg[3]; | 2549 | unsigned char msg[3]; |
2501 | unsigned char *data; | 2550 | unsigned char *data; |
2502 | Scsi_Cmnd *tmp = NULL, *prev; | 2551 | Scsi_Cmnd *tmp = NULL, *prev; |
2503 | /* unsigned long flags; */ | 2552 | /* unsigned long flags; */ |
2504 | 2553 | ||
2505 | /* | 2554 | /* |
2506 | * Disable arbitration, etc. since the host adapter obviously | 2555 | * Disable arbitration, etc. since the host adapter obviously |
2507 | * lost, and tell an interrupted NCR5380_select() to restart. | 2556 | * lost, and tell an interrupted NCR5380_select() to restart. |
2508 | */ | 2557 | */ |
2509 | 2558 | ||
2510 | NCR5380_write(MODE_REG, MR_BASE); | 2559 | NCR5380_write(MODE_REG, MR_BASE); |
2511 | hostdata->restart_select = 1; | 2560 | hostdata->restart_select = 1; |
2512 | 2561 | ||
2513 | target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask); | 2562 | target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask); |
2514 | 2563 | ||
2515 | RSL_PRINTK("scsi%d: reselect\n", HOSTNO); | 2564 | RSL_PRINTK("scsi%d: reselect\n", HOSTNO); |
2516 | 2565 | ||
2517 | /* | 2566 | /* |
2518 | * At this point, we have detected that our SCSI ID is on the bus, | 2567 | * At this point, we have detected that our SCSI ID is on the bus, |
2519 | * SEL is true and BSY was false for at least one bus settle delay | 2568 | * SEL is true and BSY was false for at least one bus settle delay |
2520 | * (400 ns). | 2569 | * (400 ns). |
2521 | * | 2570 | * |
2522 | * We must assert BSY ourselves, until the target drops the SEL | 2571 | * We must assert BSY ourselves, until the target drops the SEL |
2523 | * signal. | 2572 | * signal. |
2524 | */ | 2573 | */ |
2525 | 2574 | ||
2526 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY); | 2575 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY); |
2527 | 2576 | ||
2528 | while (NCR5380_read(STATUS_REG) & SR_SEL); | 2577 | while (NCR5380_read(STATUS_REG) & SR_SEL) |
2529 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 2578 | ; |
2530 | 2579 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | |
2531 | /* | 2580 | |
2532 | * Wait for target to go into MSGIN. | 2581 | /* |
2533 | */ | 2582 | * Wait for target to go into MSGIN. |
2534 | 2583 | */ | |
2535 | while (!(NCR5380_read(STATUS_REG) & SR_REQ)); | 2584 | |
2536 | 2585 | while (!(NCR5380_read(STATUS_REG) & SR_REQ)) | |
2537 | len = 1; | 2586 | ; |
2538 | data = msg; | 2587 | |
2539 | phase = PHASE_MSGIN; | 2588 | len = 1; |
2540 | NCR5380_transfer_pio(instance, &phase, &len, &data); | 2589 | data = msg; |
2541 | 2590 | phase = PHASE_MSGIN; | |
2542 | if (!(msg[0] & 0x80)) { | 2591 | NCR5380_transfer_pio(instance, &phase, &len, &data); |
2543 | printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO); | 2592 | |
2544 | spi_print_msg(msg); | 2593 | if (!(msg[0] & 0x80)) { |
2545 | do_abort(instance); | 2594 | printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO); |
2546 | return; | 2595 | spi_print_msg(msg); |
2547 | } | 2596 | do_abort(instance); |
2548 | lun = (msg[0] & 0x07); | 2597 | return; |
2598 | } | ||
2599 | lun = (msg[0] & 0x07); | ||
2549 | 2600 | ||
2550 | #ifdef SUPPORT_TAGS | 2601 | #ifdef SUPPORT_TAGS |
2551 | /* If the phase is still MSGIN, the target wants to send some more | 2602 | /* If the phase is still MSGIN, the target wants to send some more |
2552 | * messages. In case it supports tagged queuing, this is probably a | 2603 | * messages. In case it supports tagged queuing, this is probably a |
2553 | * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus. | 2604 | * SIMPLE_QUEUE_TAG for the I_T_L_Q nexus. |
2554 | */ | 2605 | */ |
2555 | tag = TAG_NONE; | 2606 | tag = TAG_NONE; |
2556 | if (phase == PHASE_MSGIN && setup_use_tagged_queuing) { | 2607 | if (phase == PHASE_MSGIN && setup_use_tagged_queuing) { |
2557 | /* Accept previous IDENTIFY message by clearing ACK */ | 2608 | /* Accept previous IDENTIFY message by clearing ACK */ |
2558 | NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE ); | 2609 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
2559 | len = 2; | 2610 | len = 2; |
2560 | data = msg+1; | 2611 | data = msg + 1; |
2561 | if (!NCR5380_transfer_pio(instance, &phase, &len, &data) && | 2612 | if (!NCR5380_transfer_pio(instance, &phase, &len, &data) && |
2562 | msg[1] == SIMPLE_QUEUE_TAG) | 2613 | msg[1] == SIMPLE_QUEUE_TAG) |
2563 | tag = msg[2]; | 2614 | tag = msg[2]; |
2564 | TAG_PRINTK("scsi%d: target mask %02x, lun %d sent tag %d at " | 2615 | TAG_PRINTK("scsi%d: target mask %02x, lun %d sent tag %d at " |
2565 | "reselection\n", HOSTNO, target_mask, lun, tag); | 2616 | "reselection\n", HOSTNO, target_mask, lun, tag); |
2566 | } | 2617 | } |
2567 | #endif | 2618 | #endif |
2568 | 2619 | ||
2569 | /* | 2620 | /* |
2570 | * Find the command corresponding to the I_T_L or I_T_L_Q nexus we | 2621 | * Find the command corresponding to the I_T_L or I_T_L_Q nexus we |
2571 | * just reestablished, and remove it from the disconnected queue. | 2622 | * just reestablished, and remove it from the disconnected queue. |
2572 | */ | 2623 | */ |
2573 | 2624 | ||
2574 | for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; | 2625 | for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; |
2575 | tmp; prev = tmp, tmp = NEXT(tmp) ) { | 2626 | tmp; prev = tmp, tmp = NEXT(tmp)) { |
2576 | if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun) | 2627 | if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun) |
2577 | #ifdef SUPPORT_TAGS | 2628 | #ifdef SUPPORT_TAGS |
2578 | && (tag == tmp->tag) | 2629 | && (tag == tmp->tag) |
2579 | #endif | 2630 | #endif |
2580 | ) { | 2631 | ) { |
2581 | /* ++guenther: prevent race with falcon_release_lock */ | 2632 | /* ++guenther: prevent race with falcon_release_lock */ |
2582 | falcon_dont_release++; | 2633 | falcon_dont_release++; |
2583 | if (prev) { | 2634 | if (prev) { |
2584 | REMOVE(prev, NEXT(prev), tmp, NEXT(tmp)); | 2635 | REMOVE(prev, NEXT(prev), tmp, NEXT(tmp)); |
2585 | NEXT(prev) = NEXT(tmp); | 2636 | SET_NEXT(prev, NEXT(tmp)); |
2586 | } else { | 2637 | } else { |
2587 | REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp)); | 2638 | REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp)); |
2588 | hostdata->disconnected_queue = NEXT(tmp); | 2639 | hostdata->disconnected_queue = NEXT(tmp); |
2589 | } | 2640 | } |
2590 | NEXT(tmp) = NULL; | 2641 | SET_NEXT(tmp, NULL); |
2591 | break; | 2642 | break; |
2643 | } | ||
2592 | } | 2644 | } |
2593 | } | 2645 | |
2594 | 2646 | if (!tmp) { | |
2595 | if (!tmp) { | 2647 | printk(KERN_WARNING "scsi%d: warning: target bitmask %02x lun %d " |
2596 | printk(KERN_WARNING "scsi%d: warning: target bitmask %02x lun %d " | ||
2597 | #ifdef SUPPORT_TAGS | 2648 | #ifdef SUPPORT_TAGS |
2598 | "tag %d " | 2649 | "tag %d " |
2599 | #endif | 2650 | #endif |
2600 | "not in disconnected_queue.\n", | 2651 | "not in disconnected_queue.\n", |
2601 | HOSTNO, target_mask, lun | 2652 | HOSTNO, target_mask, lun |
2602 | #ifdef SUPPORT_TAGS | 2653 | #ifdef SUPPORT_TAGS |
2603 | , tag | 2654 | , tag |
2604 | #endif | 2655 | #endif |
2605 | ); | 2656 | ); |
2606 | /* | 2657 | /* |
2607 | * Since we have an established nexus that we can't do anything | 2658 | * Since we have an established nexus that we can't do anything |
2608 | * with, we must abort it. | 2659 | * with, we must abort it. |
2609 | */ | 2660 | */ |
2610 | do_abort(instance); | 2661 | do_abort(instance); |
2611 | return; | 2662 | return; |
2612 | } | 2663 | } |
2613 | 2664 | ||
2614 | /* Accept message by clearing ACK */ | 2665 | /* Accept message by clearing ACK */ |
2615 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 2666 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
2616 | 2667 | ||
2617 | hostdata->connected = tmp; | 2668 | hostdata->connected = tmp; |
2618 | RSL_PRINTK("scsi%d: nexus established, target = %d, lun = %d, tag = %d\n", | 2669 | RSL_PRINTK("scsi%d: nexus established, target = %d, lun = %d, tag = %d\n", |
2619 | HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag); | 2670 | HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag); |
2620 | falcon_dont_release--; | 2671 | falcon_dont_release--; |
2621 | } | 2672 | } |
2622 | 2673 | ||
2623 | 2674 | ||
@@ -2626,362 +2677,361 @@ static void NCR5380_reselect (struct Scsi_Host *instance) | |||
2626 | * | 2677 | * |
2627 | * Purpose : abort a command | 2678 | * Purpose : abort a command |
2628 | * | 2679 | * |
2629 | * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the | 2680 | * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the |
2630 | * host byte of the result field to, if zero DID_ABORTED is | 2681 | * host byte of the result field to, if zero DID_ABORTED is |
2631 | * used. | 2682 | * used. |
2632 | * | 2683 | * |
2633 | * Returns : 0 - success, -1 on failure. | 2684 | * Returns : 0 - success, -1 on failure. |
2634 | * | 2685 | * |
2635 | * XXX - there is no way to abort the command that is currently | 2686 | * XXX - there is no way to abort the command that is currently |
2636 | * connected, you have to wait for it to complete. If this is | 2687 | * connected, you have to wait for it to complete. If this is |
2637 | * a problem, we could implement longjmp() / setjmp(), setjmp() | 2688 | * a problem, we could implement longjmp() / setjmp(), setjmp() |
2638 | * called where the loop started in NCR5380_main(). | 2689 | * called where the loop started in NCR5380_main(). |
2639 | */ | 2690 | */ |
2640 | 2691 | ||
2641 | static | 2692 | static |
2642 | int NCR5380_abort (Scsi_Cmnd *cmd) | 2693 | int NCR5380_abort(Scsi_Cmnd *cmd) |
2643 | { | 2694 | { |
2644 | struct Scsi_Host *instance = cmd->device->host; | 2695 | struct Scsi_Host *instance = cmd->device->host; |
2645 | SETUP_HOSTDATA(instance); | 2696 | SETUP_HOSTDATA(instance); |
2646 | Scsi_Cmnd *tmp, **prev; | 2697 | Scsi_Cmnd *tmp, **prev; |
2647 | unsigned long flags; | 2698 | unsigned long flags; |
2699 | |||
2700 | printk(KERN_NOTICE "scsi%d: aborting command\n", HOSTNO); | ||
2701 | scsi_print_command(cmd); | ||
2648 | 2702 | ||
2649 | printk(KERN_NOTICE "scsi%d: aborting command\n", HOSTNO); | 2703 | NCR5380_print_status(instance); |
2650 | scsi_print_command(cmd); | ||
2651 | 2704 | ||
2652 | NCR5380_print_status (instance); | 2705 | local_irq_save(flags); |
2653 | 2706 | ||
2654 | local_irq_save(flags); | 2707 | if (!IS_A_TT() && !falcon_got_lock) |
2655 | 2708 | printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n", | |
2656 | if (!IS_A_TT() && !falcon_got_lock) | 2709 | HOSTNO); |
2657 | printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n", | ||
2658 | HOSTNO); | ||
2659 | 2710 | ||
2660 | ABRT_PRINTK("scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO, | 2711 | ABRT_PRINTK("scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO, |
2661 | NCR5380_read(BUS_AND_STATUS_REG), | 2712 | NCR5380_read(BUS_AND_STATUS_REG), |
2662 | NCR5380_read(STATUS_REG)); | 2713 | NCR5380_read(STATUS_REG)); |
2663 | 2714 | ||
2664 | #if 1 | 2715 | #if 1 |
2665 | /* | 2716 | /* |
2666 | * Case 1 : If the command is the currently executing command, | 2717 | * Case 1 : If the command is the currently executing command, |
2667 | * we'll set the aborted flag and return control so that | 2718 | * we'll set the aborted flag and return control so that |
2668 | * information transfer routine can exit cleanly. | 2719 | * information transfer routine can exit cleanly. |
2669 | */ | 2720 | */ |
2670 | 2721 | ||
2671 | if (hostdata->connected == cmd) { | 2722 | if (hostdata->connected == cmd) { |
2672 | 2723 | ||
2673 | ABRT_PRINTK("scsi%d: aborting connected command\n", HOSTNO); | 2724 | ABRT_PRINTK("scsi%d: aborting connected command\n", HOSTNO); |
2674 | /* | 2725 | /* |
2675 | * We should perform BSY checking, and make sure we haven't slipped | 2726 | * We should perform BSY checking, and make sure we haven't slipped |
2676 | * into BUS FREE. | 2727 | * into BUS FREE. |
2677 | */ | 2728 | */ |
2678 | 2729 | ||
2679 | /* NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); */ | 2730 | /* NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); */ |
2680 | /* | 2731 | /* |
2681 | * Since we can't change phases until we've completed the current | 2732 | * Since we can't change phases until we've completed the current |
2682 | * handshake, we have to source or sink a byte of data if the current | 2733 | * handshake, we have to source or sink a byte of data if the current |
2683 | * phase is not MSGOUT. | 2734 | * phase is not MSGOUT. |
2684 | */ | 2735 | */ |
2685 | 2736 | ||
2686 | /* | 2737 | /* |
2687 | * Return control to the executing NCR drive so we can clear the | 2738 | * Return control to the executing NCR drive so we can clear the |
2688 | * aborted flag and get back into our main loop. | 2739 | * aborted flag and get back into our main loop. |
2689 | */ | 2740 | */ |
2690 | 2741 | ||
2691 | if (do_abort(instance) == 0) { | 2742 | if (do_abort(instance) == 0) { |
2692 | hostdata->aborted = 1; | 2743 | hostdata->aborted = 1; |
2693 | hostdata->connected = NULL; | 2744 | hostdata->connected = NULL; |
2694 | cmd->result = DID_ABORT << 16; | 2745 | cmd->result = DID_ABORT << 16; |
2695 | #ifdef SUPPORT_TAGS | 2746 | #ifdef SUPPORT_TAGS |
2696 | cmd_free_tag( cmd ); | 2747 | cmd_free_tag(cmd); |
2697 | #else | 2748 | #else |
2698 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); | 2749 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); |
2699 | #endif | 2750 | #endif |
2700 | local_irq_restore(flags); | 2751 | local_irq_restore(flags); |
2701 | cmd->scsi_done(cmd); | 2752 | cmd->scsi_done(cmd); |
2702 | falcon_release_lock_if_possible( hostdata ); | 2753 | falcon_release_lock_if_possible(hostdata); |
2703 | return SCSI_ABORT_SUCCESS; | 2754 | return SCSI_ABORT_SUCCESS; |
2704 | } else { | 2755 | } else { |
2705 | /* local_irq_restore(flags); */ | 2756 | /* local_irq_restore(flags); */ |
2706 | printk("scsi%d: abort of connected command failed!\n", HOSTNO); | 2757 | printk("scsi%d: abort of connected command failed!\n", HOSTNO); |
2707 | return SCSI_ABORT_ERROR; | 2758 | return SCSI_ABORT_ERROR; |
2708 | } | 2759 | } |
2709 | } | 2760 | } |
2710 | #endif | 2761 | #endif |
2711 | 2762 | ||
2712 | /* | 2763 | /* |
2713 | * Case 2 : If the command hasn't been issued yet, we simply remove it | 2764 | * Case 2 : If the command hasn't been issued yet, we simply remove it |
2714 | * from the issue queue. | 2765 | * from the issue queue. |
2715 | */ | 2766 | */ |
2716 | for (prev = (Scsi_Cmnd **) &(hostdata->issue_queue), | 2767 | for (prev = (Scsi_Cmnd **)&(hostdata->issue_queue), |
2717 | tmp = (Scsi_Cmnd *) hostdata->issue_queue; | 2768 | tmp = (Scsi_Cmnd *)hostdata->issue_queue; |
2718 | tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) ) | 2769 | tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) { |
2719 | if (cmd == tmp) { | 2770 | if (cmd == tmp) { |
2720 | REMOVE(5, *prev, tmp, NEXT(tmp)); | 2771 | REMOVE(5, *prev, tmp, NEXT(tmp)); |
2721 | (*prev) = NEXT(tmp); | 2772 | (*prev) = NEXT(tmp); |
2722 | NEXT(tmp) = NULL; | 2773 | SET_NEXT(tmp, NULL); |
2723 | tmp->result = DID_ABORT << 16; | 2774 | tmp->result = DID_ABORT << 16; |
2724 | local_irq_restore(flags); | 2775 | local_irq_restore(flags); |
2725 | ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n", | 2776 | ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n", |
2726 | HOSTNO); | 2777 | HOSTNO); |
2727 | /* Tagged queuing note: no tag to free here, hasn't been assigned | 2778 | /* Tagged queuing note: no tag to free here, hasn't been assigned |
2728 | * yet... */ | 2779 | * yet... */ |
2729 | tmp->scsi_done(tmp); | 2780 | tmp->scsi_done(tmp); |
2730 | falcon_release_lock_if_possible( hostdata ); | 2781 | falcon_release_lock_if_possible(hostdata); |
2731 | return SCSI_ABORT_SUCCESS; | 2782 | return SCSI_ABORT_SUCCESS; |
2783 | } | ||
2732 | } | 2784 | } |
2733 | 2785 | ||
2734 | /* | 2786 | /* |
2735 | * Case 3 : If any commands are connected, we're going to fail the abort | 2787 | * Case 3 : If any commands are connected, we're going to fail the abort |
2736 | * and let the high level SCSI driver retry at a later time or | 2788 | * and let the high level SCSI driver retry at a later time or |
2737 | * issue a reset. | 2789 | * issue a reset. |
2738 | * | 2790 | * |
2739 | * Timeouts, and therefore aborted commands, will be highly unlikely | 2791 | * Timeouts, and therefore aborted commands, will be highly unlikely |
2740 | * and handling them cleanly in this situation would make the common | 2792 | * and handling them cleanly in this situation would make the common |
2741 | * case of noresets less efficient, and would pollute our code. So, | 2793 | * case of noresets less efficient, and would pollute our code. So, |
2742 | * we fail. | 2794 | * we fail. |
2743 | */ | 2795 | */ |
2744 | 2796 | ||
2745 | if (hostdata->connected) { | 2797 | if (hostdata->connected) { |
2746 | local_irq_restore(flags); | 2798 | local_irq_restore(flags); |
2747 | ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO); | 2799 | ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO); |
2748 | return SCSI_ABORT_SNOOZE; | 2800 | return SCSI_ABORT_SNOOZE; |
2749 | } | 2801 | } |
2750 | 2802 | ||
2751 | /* | 2803 | /* |
2752 | * Case 4: If the command is currently disconnected from the bus, and | 2804 | * Case 4: If the command is currently disconnected from the bus, and |
2753 | * there are no connected commands, we reconnect the I_T_L or | 2805 | * there are no connected commands, we reconnect the I_T_L or |
2754 | * I_T_L_Q nexus associated with it, go into message out, and send | 2806 | * I_T_L_Q nexus associated with it, go into message out, and send |
2755 | * an abort message. | 2807 | * an abort message. |
2756 | * | 2808 | * |
2757 | * This case is especially ugly. In order to reestablish the nexus, we | 2809 | * This case is especially ugly. In order to reestablish the nexus, we |
2758 | * need to call NCR5380_select(). The easiest way to implement this | 2810 | * need to call NCR5380_select(). The easiest way to implement this |
2759 | * function was to abort if the bus was busy, and let the interrupt | 2811 | * function was to abort if the bus was busy, and let the interrupt |
2760 | * handler triggered on the SEL for reselect take care of lost arbitrations | 2812 | * handler triggered on the SEL for reselect take care of lost arbitrations |
2761 | * where necessary, meaning interrupts need to be enabled. | 2813 | * where necessary, meaning interrupts need to be enabled. |
2762 | * | 2814 | * |
2763 | * When interrupts are enabled, the queues may change - so we | 2815 | * When interrupts are enabled, the queues may change - so we |
2764 | * can't remove it from the disconnected queue before selecting it | 2816 | * can't remove it from the disconnected queue before selecting it |
2765 | * because that could cause a failure in hashing the nexus if that | 2817 | * because that could cause a failure in hashing the nexus if that |
2766 | * device reselected. | 2818 | * device reselected. |
2767 | * | 2819 | * |
2768 | * Since the queues may change, we can't use the pointers from when we | 2820 | * Since the queues may change, we can't use the pointers from when we |
2769 | * first locate it. | 2821 | * first locate it. |
2770 | * | 2822 | * |
2771 | * So, we must first locate the command, and if NCR5380_select() | 2823 | * So, we must first locate the command, and if NCR5380_select() |
2772 | * succeeds, then issue the abort, relocate the command and remove | 2824 | * succeeds, then issue the abort, relocate the command and remove |
2773 | * it from the disconnected queue. | 2825 | * it from the disconnected queue. |
2774 | */ | 2826 | */ |
2827 | |||
2828 | for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; | ||
2829 | tmp = NEXT(tmp)) { | ||
2830 | if (cmd == tmp) { | ||
2831 | local_irq_restore(flags); | ||
2832 | ABRT_PRINTK("scsi%d: aborting disconnected command.\n", HOSTNO); | ||
2775 | 2833 | ||
2776 | for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; | 2834 | if (NCR5380_select(instance, cmd, (int)cmd->tag)) |
2777 | tmp = NEXT(tmp)) | 2835 | return SCSI_ABORT_BUSY; |
2778 | if (cmd == tmp) { | 2836 | |
2779 | local_irq_restore(flags); | 2837 | ABRT_PRINTK("scsi%d: nexus reestablished.\n", HOSTNO); |
2780 | ABRT_PRINTK("scsi%d: aborting disconnected command.\n", HOSTNO); | 2838 | |
2781 | 2839 | do_abort(instance); | |
2782 | if (NCR5380_select (instance, cmd, (int) cmd->tag)) | 2840 | |
2783 | return SCSI_ABORT_BUSY; | 2841 | local_irq_save(flags); |
2784 | 2842 | for (prev = (Scsi_Cmnd **)&(hostdata->disconnected_queue), | |
2785 | ABRT_PRINTK("scsi%d: nexus reestablished.\n", HOSTNO); | 2843 | tmp = (Scsi_Cmnd *)hostdata->disconnected_queue; |
2786 | 2844 | tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) { | |
2787 | do_abort (instance); | 2845 | if (cmd == tmp) { |
2788 | 2846 | REMOVE(5, *prev, tmp, NEXT(tmp)); | |
2789 | local_irq_save(flags); | 2847 | *prev = NEXT(tmp); |
2790 | for (prev = (Scsi_Cmnd **) &(hostdata->disconnected_queue), | 2848 | SET_NEXT(tmp, NULL); |
2791 | tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; | 2849 | tmp->result = DID_ABORT << 16; |
2792 | tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) ) | 2850 | /* We must unlock the tag/LUN immediately here, since the |
2793 | if (cmd == tmp) { | 2851 | * target goes to BUS FREE and doesn't send us another |
2794 | REMOVE(5, *prev, tmp, NEXT(tmp)); | 2852 | * message (COMMAND_COMPLETE or the like) |
2795 | *prev = NEXT(tmp); | 2853 | */ |
2796 | NEXT(tmp) = NULL; | ||
2797 | tmp->result = DID_ABORT << 16; | ||
2798 | /* We must unlock the tag/LUN immediately here, since the | ||
2799 | * target goes to BUS FREE and doesn't send us another | ||
2800 | * message (COMMAND_COMPLETE or the like) | ||
2801 | */ | ||
2802 | #ifdef SUPPORT_TAGS | 2854 | #ifdef SUPPORT_TAGS |
2803 | cmd_free_tag( tmp ); | 2855 | cmd_free_tag(tmp); |
2804 | #else | 2856 | #else |
2805 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); | 2857 | hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); |
2806 | #endif | 2858 | #endif |
2807 | local_irq_restore(flags); | 2859 | local_irq_restore(flags); |
2808 | tmp->scsi_done(tmp); | 2860 | tmp->scsi_done(tmp); |
2809 | falcon_release_lock_if_possible( hostdata ); | 2861 | falcon_release_lock_if_possible(hostdata); |
2810 | return SCSI_ABORT_SUCCESS; | 2862 | return SCSI_ABORT_SUCCESS; |
2863 | } | ||
2864 | } | ||
2811 | } | 2865 | } |
2812 | } | 2866 | } |
2813 | 2867 | ||
2814 | /* | 2868 | /* |
2815 | * Case 5 : If we reached this point, the command was not found in any of | 2869 | * Case 5 : If we reached this point, the command was not found in any of |
2816 | * the queues. | 2870 | * the queues. |
2817 | * | 2871 | * |
2818 | * We probably reached this point because of an unlikely race condition | 2872 | * We probably reached this point because of an unlikely race condition |
2819 | * between the command completing successfully and the abortion code, | 2873 | * between the command completing successfully and the abortion code, |
2820 | * so we won't panic, but we will notify the user in case something really | 2874 | * so we won't panic, but we will notify the user in case something really |
2821 | * broke. | 2875 | * broke. |
2822 | */ | 2876 | */ |
2823 | 2877 | ||
2824 | local_irq_restore(flags); | 2878 | local_irq_restore(flags); |
2825 | printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n" | 2879 | printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n" |
2826 | KERN_INFO " before abortion\n", HOSTNO); | 2880 | KERN_INFO " before abortion\n", HOSTNO); |
2827 | 2881 | ||
2828 | /* Maybe it is sufficient just to release the ST-DMA lock... (if | 2882 | /* Maybe it is sufficient just to release the ST-DMA lock... (if |
2829 | * possible at all) At least, we should check if the lock could be | 2883 | * possible at all) At least, we should check if the lock could be |
2830 | * released after the abort, in case it is kept due to some bug. | 2884 | * released after the abort, in case it is kept due to some bug. |
2831 | */ | 2885 | */ |
2832 | falcon_release_lock_if_possible( hostdata ); | 2886 | falcon_release_lock_if_possible(hostdata); |
2833 | 2887 | ||
2834 | return SCSI_ABORT_NOT_RUNNING; | 2888 | return SCSI_ABORT_NOT_RUNNING; |
2835 | } | 2889 | } |
2836 | 2890 | ||
2837 | 2891 | ||
2838 | /* | 2892 | /* |
2839 | * Function : int NCR5380_reset (Scsi_Cmnd *cmd) | 2893 | * Function : int NCR5380_reset (Scsi_Cmnd *cmd) |
2840 | * | 2894 | * |
2841 | * Purpose : reset the SCSI bus. | 2895 | * Purpose : reset the SCSI bus. |
2842 | * | 2896 | * |
2843 | * Returns : SCSI_RESET_WAKEUP | 2897 | * Returns : SCSI_RESET_WAKEUP |
2844 | * | 2898 | * |
2845 | */ | 2899 | */ |
2846 | 2900 | ||
2847 | static int NCR5380_bus_reset( Scsi_Cmnd *cmd) | 2901 | static int NCR5380_bus_reset(Scsi_Cmnd *cmd) |
2848 | { | 2902 | { |
2849 | SETUP_HOSTDATA(cmd->device->host); | 2903 | SETUP_HOSTDATA(cmd->device->host); |
2850 | int i; | 2904 | int i; |
2851 | unsigned long flags; | 2905 | unsigned long flags; |
2852 | #if 1 | 2906 | #if 1 |
2853 | Scsi_Cmnd *connected, *disconnected_queue; | 2907 | Scsi_Cmnd *connected, *disconnected_queue; |
2854 | #endif | 2908 | #endif |
2855 | 2909 | ||
2856 | if (!IS_A_TT() && !falcon_got_lock) | 2910 | if (!IS_A_TT() && !falcon_got_lock) |
2857 | printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n", | 2911 | printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n", |
2858 | H_NO(cmd) ); | 2912 | H_NO(cmd)); |
2859 | 2913 | ||
2860 | NCR5380_print_status (cmd->device->host); | 2914 | NCR5380_print_status(cmd->device->host); |
2861 | 2915 | ||
2862 | /* get in phase */ | 2916 | /* get in phase */ |
2863 | NCR5380_write( TARGET_COMMAND_REG, | 2917 | NCR5380_write(TARGET_COMMAND_REG, |
2864 | PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) )); | 2918 | PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG))); |
2865 | /* assert RST */ | 2919 | /* assert RST */ |
2866 | NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST ); | 2920 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST); |
2867 | udelay (40); | 2921 | udelay(40); |
2868 | /* reset NCR registers */ | 2922 | /* reset NCR registers */ |
2869 | NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE ); | 2923 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
2870 | NCR5380_write( MODE_REG, MR_BASE ); | 2924 | NCR5380_write(MODE_REG, MR_BASE); |
2871 | NCR5380_write( TARGET_COMMAND_REG, 0 ); | 2925 | NCR5380_write(TARGET_COMMAND_REG, 0); |
2872 | NCR5380_write( SELECT_ENABLE_REG, 0 ); | 2926 | NCR5380_write(SELECT_ENABLE_REG, 0); |
2873 | /* ++roman: reset interrupt condition! otherwise no interrupts don't get | 2927 | /* ++roman: reset interrupt condition! otherwise no interrupts don't get |
2874 | * through anymore ... */ | 2928 | * through anymore ... */ |
2875 | (void)NCR5380_read( RESET_PARITY_INTERRUPT_REG ); | 2929 | (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); |
2876 | 2930 | ||
2877 | #if 1 /* XXX Should now be done by midlevel code, but it's broken XXX */ | 2931 | #if 1 /* XXX Should now be done by midlevel code, but it's broken XXX */ |
2878 | /* XXX see below XXX */ | 2932 | /* XXX see below XXX */ |
2879 | 2933 | ||
2880 | /* MSch: old-style reset: actually abort all command processing here */ | 2934 | /* MSch: old-style reset: actually abort all command processing here */ |
2881 | 2935 | ||
2882 | /* After the reset, there are no more connected or disconnected commands | 2936 | /* After the reset, there are no more connected or disconnected commands |
2883 | * and no busy units; to avoid problems with re-inserting the commands | 2937 | * and no busy units; to avoid problems with re-inserting the commands |
2884 | * into the issue_queue (via scsi_done()), the aborted commands are | 2938 | * into the issue_queue (via scsi_done()), the aborted commands are |
2885 | * remembered in local variables first. | 2939 | * remembered in local variables first. |
2886 | */ | 2940 | */ |
2887 | local_irq_save(flags); | 2941 | local_irq_save(flags); |
2888 | connected = (Scsi_Cmnd *)hostdata->connected; | 2942 | connected = (Scsi_Cmnd *)hostdata->connected; |
2889 | hostdata->connected = NULL; | 2943 | hostdata->connected = NULL; |
2890 | disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue; | 2944 | disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue; |
2891 | hostdata->disconnected_queue = NULL; | 2945 | hostdata->disconnected_queue = NULL; |
2892 | #ifdef SUPPORT_TAGS | 2946 | #ifdef SUPPORT_TAGS |
2893 | free_all_tags(); | 2947 | free_all_tags(); |
2894 | #endif | 2948 | #endif |
2895 | for( i = 0; i < 8; ++i ) | 2949 | for (i = 0; i < 8; ++i) |
2896 | hostdata->busy[i] = 0; | 2950 | hostdata->busy[i] = 0; |
2897 | #ifdef REAL_DMA | 2951 | #ifdef REAL_DMA |
2898 | hostdata->dma_len = 0; | 2952 | hostdata->dma_len = 0; |
2899 | #endif | 2953 | #endif |
2900 | local_irq_restore(flags); | 2954 | local_irq_restore(flags); |
2901 | 2955 | ||
2902 | /* In order to tell the mid-level code which commands were aborted, | 2956 | /* In order to tell the mid-level code which commands were aborted, |
2903 | * set the command status to DID_RESET and call scsi_done() !!! | 2957 | * set the command status to DID_RESET and call scsi_done() !!! |
2904 | * This ultimately aborts processing of these commands in the mid-level. | 2958 | * This ultimately aborts processing of these commands in the mid-level. |
2905 | */ | 2959 | */ |
2906 | 2960 | ||
2907 | if ((cmd = connected)) { | 2961 | if ((cmd = connected)) { |
2908 | ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd)); | 2962 | ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd)); |
2909 | cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16); | 2963 | cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16); |
2910 | cmd->scsi_done( cmd ); | 2964 | cmd->scsi_done(cmd); |
2911 | } | 2965 | } |
2912 | |||
2913 | for (i = 0; (cmd = disconnected_queue); ++i) { | ||
2914 | disconnected_queue = NEXT(cmd); | ||
2915 | NEXT(cmd) = NULL; | ||
2916 | cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16); | ||
2917 | cmd->scsi_done( cmd ); | ||
2918 | } | ||
2919 | if (i > 0) | ||
2920 | ABRT_PRINTK("scsi: reset aborted %d disconnected command(s)\n", i); | ||
2921 | |||
2922 | /* The Falcon lock should be released after a reset... | ||
2923 | */ | ||
2924 | /* ++guenther: moved to atari_scsi_reset(), to prevent a race between | ||
2925 | * unlocking and enabling dma interrupt. | ||
2926 | */ | ||
2927 | /* falcon_release_lock_if_possible( hostdata );*/ | ||
2928 | 2966 | ||
2929 | /* since all commands have been explicitly terminated, we need to tell | 2967 | for (i = 0; (cmd = disconnected_queue); ++i) { |
2930 | * the midlevel code that the reset was SUCCESSFUL, and there is no | 2968 | disconnected_queue = NEXT(cmd); |
2931 | * need to 'wake up' the commands by a request_sense | 2969 | SET_NEXT(cmd, NULL); |
2932 | */ | 2970 | cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16); |
2933 | return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET; | 2971 | cmd->scsi_done(cmd); |
2972 | } | ||
2973 | if (i > 0) | ||
2974 | ABRT_PRINTK("scsi: reset aborted %d disconnected command(s)\n", i); | ||
2975 | |||
2976 | /* The Falcon lock should be released after a reset... | ||
2977 | */ | ||
2978 | /* ++guenther: moved to atari_scsi_reset(), to prevent a race between | ||
2979 | * unlocking and enabling dma interrupt. | ||
2980 | */ | ||
2981 | /* falcon_release_lock_if_possible( hostdata );*/ | ||
2982 | |||
2983 | /* since all commands have been explicitly terminated, we need to tell | ||
2984 | * the midlevel code that the reset was SUCCESSFUL, and there is no | ||
2985 | * need to 'wake up' the commands by a request_sense | ||
2986 | */ | ||
2987 | return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET; | ||
2934 | #else /* 1 */ | 2988 | #else /* 1 */ |
2935 | 2989 | ||
2936 | /* MSch: new-style reset handling: let the mid-level do what it can */ | 2990 | /* MSch: new-style reset handling: let the mid-level do what it can */ |
2937 | 2991 | ||
2938 | /* ++guenther: MID-LEVEL IS STILL BROKEN. | 2992 | /* ++guenther: MID-LEVEL IS STILL BROKEN. |
2939 | * Mid-level is supposed to requeue all commands that were active on the | 2993 | * Mid-level is supposed to requeue all commands that were active on the |
2940 | * various low-level queues. In fact it does this, but that's not enough | 2994 | * various low-level queues. In fact it does this, but that's not enough |
2941 | * because all these commands are subject to timeout. And if a timeout | 2995 | * because all these commands are subject to timeout. And if a timeout |
2942 | * happens for any removed command, *_abort() is called but all queues | 2996 | * happens for any removed command, *_abort() is called but all queues |
2943 | * are now empty. Abort then gives up the falcon lock, which is fatal, | 2997 | * are now empty. Abort then gives up the falcon lock, which is fatal, |
2944 | * since the mid-level will queue more commands and must have the lock | 2998 | * since the mid-level will queue more commands and must have the lock |
2945 | * (it's all happening inside timer interrupt handler!!). | 2999 | * (it's all happening inside timer interrupt handler!!). |
2946 | * Even worse, abort will return NOT_RUNNING for all those commands not | 3000 | * Even worse, abort will return NOT_RUNNING for all those commands not |
2947 | * on any queue, so they won't be retried ... | 3001 | * on any queue, so they won't be retried ... |
2948 | * | 3002 | * |
2949 | * Conclusion: either scsi.c disables timeout for all resetted commands | 3003 | * Conclusion: either scsi.c disables timeout for all resetted commands |
2950 | * immediately, or we lose! As of linux-2.0.20 it doesn't. | 3004 | * immediately, or we lose! As of linux-2.0.20 it doesn't. |
2951 | */ | 3005 | */ |
2952 | 3006 | ||
2953 | /* After the reset, there are no more connected or disconnected commands | 3007 | /* After the reset, there are no more connected or disconnected commands |
2954 | * and no busy units; so clear the low-level status here to avoid | 3008 | * and no busy units; so clear the low-level status here to avoid |
2955 | * conflicts when the mid-level code tries to wake up the affected | 3009 | * conflicts when the mid-level code tries to wake up the affected |
2956 | * commands! | 3010 | * commands! |
2957 | */ | 3011 | */ |
2958 | 3012 | ||
2959 | if (hostdata->issue_queue) | 3013 | if (hostdata->issue_queue) |
2960 | ABRT_PRINTK("scsi%d: reset aborted issued command(s)\n", H_NO(cmd)); | 3014 | ABRT_PRINTK("scsi%d: reset aborted issued command(s)\n", H_NO(cmd)); |
2961 | if (hostdata->connected) | 3015 | if (hostdata->connected) |
2962 | ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd)); | 3016 | ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd)); |
2963 | if (hostdata->disconnected_queue) | 3017 | if (hostdata->disconnected_queue) |
2964 | ABRT_PRINTK("scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd)); | 3018 | ABRT_PRINTK("scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd)); |
2965 | 3019 | ||
2966 | local_irq_save(flags); | 3020 | local_irq_save(flags); |
2967 | hostdata->issue_queue = NULL; | 3021 | hostdata->issue_queue = NULL; |
2968 | hostdata->connected = NULL; | 3022 | hostdata->connected = NULL; |
2969 | hostdata->disconnected_queue = NULL; | 3023 | hostdata->disconnected_queue = NULL; |
2970 | #ifdef SUPPORT_TAGS | 3024 | #ifdef SUPPORT_TAGS |
2971 | free_all_tags(); | 3025 | free_all_tags(); |
2972 | #endif | 3026 | #endif |
2973 | for( i = 0; i < 8; ++i ) | 3027 | for (i = 0; i < 8; ++i) |
2974 | hostdata->busy[i] = 0; | 3028 | hostdata->busy[i] = 0; |
2975 | #ifdef REAL_DMA | 3029 | #ifdef REAL_DMA |
2976 | hostdata->dma_len = 0; | 3030 | hostdata->dma_len = 0; |
2977 | #endif | 3031 | #endif |
2978 | local_irq_restore(flags); | 3032 | local_irq_restore(flags); |
2979 | 3033 | ||
2980 | /* we did no complete reset of all commands, so a wakeup is required */ | 3034 | /* we did no complete reset of all commands, so a wakeup is required */ |
2981 | return SCSI_RESET_WAKEUP | SCSI_RESET_BUS_RESET; | 3035 | return SCSI_RESET_WAKEUP | SCSI_RESET_BUS_RESET; |
2982 | #endif /* 1 */ | 3036 | #endif /* 1 */ |
2983 | } | 3037 | } |
2984 | |||
2985 | /* Local Variables: */ | ||
2986 | /* tab-width: 8 */ | ||
2987 | /* End: */ | ||
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 642de7b2b7a2..6f8403b82ba1 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c | |||
@@ -69,9 +69,9 @@ | |||
69 | 69 | ||
70 | #define NDEBUG (0) | 70 | #define NDEBUG (0) |
71 | 71 | ||
72 | #define NDEBUG_ABORT 0x800000 | 72 | #define NDEBUG_ABORT 0x00100000 |
73 | #define NDEBUG_TAGS 0x1000000 | 73 | #define NDEBUG_TAGS 0x00200000 |
74 | #define NDEBUG_MERGING 0x2000000 | 74 | #define NDEBUG_MERGING 0x00400000 |
75 | 75 | ||
76 | #define AUTOSENSE | 76 | #define AUTOSENSE |
77 | /* For the Atari version, use only polled IO or REAL_DMA */ | 77 | /* For the Atari version, use only polled IO or REAL_DMA */ |
@@ -186,38 +186,37 @@ static inline void DISABLE_IRQ(void) | |||
186 | /***************************** Prototypes *****************************/ | 186 | /***************************** Prototypes *****************************/ |
187 | 187 | ||
188 | #ifdef REAL_DMA | 188 | #ifdef REAL_DMA |
189 | static int scsi_dma_is_ignored_buserr( unsigned char dma_stat ); | 189 | static int scsi_dma_is_ignored_buserr(unsigned char dma_stat); |
190 | static void atari_scsi_fetch_restbytes( void ); | 190 | static void atari_scsi_fetch_restbytes(void); |
191 | static long atari_scsi_dma_residual( struct Scsi_Host *instance ); | 191 | static long atari_scsi_dma_residual(struct Scsi_Host *instance); |
192 | static int falcon_classify_cmd( Scsi_Cmnd *cmd ); | 192 | static int falcon_classify_cmd(Scsi_Cmnd *cmd); |
193 | static unsigned long atari_dma_xfer_len( unsigned long wanted_len, | 193 | static unsigned long atari_dma_xfer_len(unsigned long wanted_len, |
194 | Scsi_Cmnd *cmd, int write_flag ); | 194 | Scsi_Cmnd *cmd, int write_flag); |
195 | #endif | 195 | #endif |
196 | static irqreturn_t scsi_tt_intr( int irq, void *dummy); | 196 | static irqreturn_t scsi_tt_intr(int irq, void *dummy); |
197 | static irqreturn_t scsi_falcon_intr( int irq, void *dummy); | 197 | static irqreturn_t scsi_falcon_intr(int irq, void *dummy); |
198 | static void falcon_release_lock_if_possible( struct NCR5380_hostdata * | 198 | static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata); |
199 | hostdata ); | 199 | static void falcon_get_lock(void); |
200 | static void falcon_get_lock( void ); | ||
201 | #ifdef CONFIG_ATARI_SCSI_RESET_BOOT | 200 | #ifdef CONFIG_ATARI_SCSI_RESET_BOOT |
202 | static void atari_scsi_reset_boot( void ); | 201 | static void atari_scsi_reset_boot(void); |
203 | #endif | 202 | #endif |
204 | static unsigned char atari_scsi_tt_reg_read( unsigned char reg ); | 203 | static unsigned char atari_scsi_tt_reg_read(unsigned char reg); |
205 | static void atari_scsi_tt_reg_write( unsigned char reg, unsigned char value); | 204 | static void atari_scsi_tt_reg_write(unsigned char reg, unsigned char value); |
206 | static unsigned char atari_scsi_falcon_reg_read( unsigned char reg ); | 205 | static unsigned char atari_scsi_falcon_reg_read(unsigned char reg); |
207 | static void atari_scsi_falcon_reg_write( unsigned char reg, unsigned char value ); | 206 | static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value); |
208 | 207 | ||
209 | /************************* End of Prototypes **************************/ | 208 | /************************* End of Prototypes **************************/ |
210 | 209 | ||
211 | 210 | ||
212 | static struct Scsi_Host *atari_scsi_host = NULL; | 211 | static struct Scsi_Host *atari_scsi_host; |
213 | static unsigned char (*atari_scsi_reg_read)( unsigned char reg ); | 212 | static unsigned char (*atari_scsi_reg_read)(unsigned char reg); |
214 | static void (*atari_scsi_reg_write)( unsigned char reg, unsigned char value ); | 213 | static void (*atari_scsi_reg_write)(unsigned char reg, unsigned char value); |
215 | 214 | ||
216 | #ifdef REAL_DMA | 215 | #ifdef REAL_DMA |
217 | static unsigned long atari_dma_residual, atari_dma_startaddr; | 216 | static unsigned long atari_dma_residual, atari_dma_startaddr; |
218 | static short atari_dma_active; | 217 | static short atari_dma_active; |
219 | /* pointer to the dribble buffer */ | 218 | /* pointer to the dribble buffer */ |
220 | static char *atari_dma_buffer = NULL; | 219 | static char *atari_dma_buffer; |
221 | /* precalculated physical address of the dribble buffer */ | 220 | /* precalculated physical address of the dribble buffer */ |
222 | static unsigned long atari_dma_phys_buffer; | 221 | static unsigned long atari_dma_phys_buffer; |
223 | /* != 0 tells the Falcon int handler to copy data from the dribble buffer */ | 222 | /* != 0 tells the Falcon int handler to copy data from the dribble buffer */ |
@@ -233,7 +232,7 @@ static char *atari_dma_orig_addr; | |||
233 | static unsigned long atari_dma_stram_mask; | 232 | static unsigned long atari_dma_stram_mask; |
234 | #define STRAM_ADDR(a) (((a) & atari_dma_stram_mask) == 0) | 233 | #define STRAM_ADDR(a) (((a) & atari_dma_stram_mask) == 0) |
235 | /* number of bytes to cut from a transfer to handle NCR overruns */ | 234 | /* number of bytes to cut from a transfer to handle NCR overruns */ |
236 | static int atari_read_overruns = 0; | 235 | static int atari_read_overruns; |
237 | #endif | 236 | #endif |
238 | 237 | ||
239 | static int setup_can_queue = -1; | 238 | static int setup_can_queue = -1; |
@@ -256,10 +255,10 @@ module_param(setup_hostid, int, 0); | |||
256 | 255 | ||
257 | #if defined(REAL_DMA) | 256 | #if defined(REAL_DMA) |
258 | 257 | ||
259 | static int scsi_dma_is_ignored_buserr( unsigned char dma_stat ) | 258 | static int scsi_dma_is_ignored_buserr(unsigned char dma_stat) |
260 | { | 259 | { |
261 | int i; | 260 | int i; |
262 | unsigned long addr = SCSI_DMA_READ_P( dma_addr ), end_addr; | 261 | unsigned long addr = SCSI_DMA_READ_P(dma_addr), end_addr; |
263 | 262 | ||
264 | if (dma_stat & 0x01) { | 263 | if (dma_stat & 0x01) { |
265 | 264 | ||
@@ -267,15 +266,14 @@ static int scsi_dma_is_ignored_buserr( unsigned char dma_stat ) | |||
267 | * physical memory chunk (DMA prefetch!), but that doesn't hurt. | 266 | * physical memory chunk (DMA prefetch!), but that doesn't hurt. |
268 | * Check for this case: | 267 | * Check for this case: |
269 | */ | 268 | */ |
270 | 269 | ||
271 | for( i = 0; i < m68k_num_memory; ++i ) { | 270 | for (i = 0; i < m68k_num_memory; ++i) { |
272 | end_addr = m68k_memory[i].addr + | 271 | end_addr = m68k_memory[i].addr + m68k_memory[i].size; |
273 | m68k_memory[i].size; | ||
274 | if (end_addr <= addr && addr <= end_addr + 4) | 272 | if (end_addr <= addr && addr <= end_addr + 4) |
275 | return( 1 ); | 273 | return 1; |
276 | } | 274 | } |
277 | } | 275 | } |
278 | return( 0 ); | 276 | return 0; |
279 | } | 277 | } |
280 | 278 | ||
281 | 279 | ||
@@ -284,28 +282,27 @@ static int scsi_dma_is_ignored_buserr( unsigned char dma_stat ) | |||
284 | * end-of-DMA, both SCSI ints are triggered simultaneously, so the NCR int has | 282 | * end-of-DMA, both SCSI ints are triggered simultaneously, so the NCR int has |
285 | * to clear the DMA int pending bit before it allows other level 6 interrupts. | 283 | * to clear the DMA int pending bit before it allows other level 6 interrupts. |
286 | */ | 284 | */ |
287 | static void scsi_dma_buserr (int irq, void *dummy) | 285 | static void scsi_dma_buserr(int irq, void *dummy) |
288 | { | 286 | { |
289 | unsigned char dma_stat = tt_scsi_dma.dma_ctrl; | 287 | unsigned char dma_stat = tt_scsi_dma.dma_ctrl; |
290 | 288 | ||
291 | /* Don't do anything if a NCR interrupt is pending. Probably it's just | 289 | /* Don't do anything if a NCR interrupt is pending. Probably it's just |
292 | * masked... */ | 290 | * masked... */ |
293 | if (atari_irq_pending( IRQ_TT_MFP_SCSI )) | 291 | if (atari_irq_pending(IRQ_TT_MFP_SCSI)) |
294 | return; | 292 | return; |
295 | 293 | ||
296 | printk("Bad SCSI DMA interrupt! dma_addr=0x%08lx dma_stat=%02x dma_cnt=%08lx\n", | 294 | printk("Bad SCSI DMA interrupt! dma_addr=0x%08lx dma_stat=%02x dma_cnt=%08lx\n", |
297 | SCSI_DMA_READ_P(dma_addr), dma_stat, SCSI_DMA_READ_P(dma_cnt)); | 295 | SCSI_DMA_READ_P(dma_addr), dma_stat, SCSI_DMA_READ_P(dma_cnt)); |
298 | if (dma_stat & 0x80) { | 296 | if (dma_stat & 0x80) { |
299 | if (!scsi_dma_is_ignored_buserr( dma_stat )) | 297 | if (!scsi_dma_is_ignored_buserr(dma_stat)) |
300 | printk( "SCSI DMA bus error -- bad DMA programming!\n" ); | 298 | printk("SCSI DMA bus error -- bad DMA programming!\n"); |
301 | } | 299 | } else { |
302 | else { | ||
303 | /* Under normal circumstances we never should get to this point, | 300 | /* Under normal circumstances we never should get to this point, |
304 | * since both interrupts are triggered simultaneously and the 5380 | 301 | * since both interrupts are triggered simultaneously and the 5380 |
305 | * int has higher priority. When this irq is handled, that DMA | 302 | * int has higher priority. When this irq is handled, that DMA |
306 | * interrupt is cleared. So a warning message is printed here. | 303 | * interrupt is cleared. So a warning message is printed here. |
307 | */ | 304 | */ |
308 | printk( "SCSI DMA intr ?? -- this shouldn't happen!\n" ); | 305 | printk("SCSI DMA intr ?? -- this shouldn't happen!\n"); |
309 | } | 306 | } |
310 | } | 307 | } |
311 | #endif | 308 | #endif |
@@ -313,7 +310,7 @@ static void scsi_dma_buserr (int irq, void *dummy) | |||
313 | #endif | 310 | #endif |
314 | 311 | ||
315 | 312 | ||
316 | static irqreturn_t scsi_tt_intr (int irq, void *dummy) | 313 | static irqreturn_t scsi_tt_intr(int irq, void *dummy) |
317 | { | 314 | { |
318 | #ifdef REAL_DMA | 315 | #ifdef REAL_DMA |
319 | int dma_stat; | 316 | int dma_stat; |
@@ -327,7 +324,7 @@ static irqreturn_t scsi_tt_intr (int irq, void *dummy) | |||
327 | * is that a bus error occurred... | 324 | * is that a bus error occurred... |
328 | */ | 325 | */ |
329 | if (dma_stat & 0x80) { | 326 | if (dma_stat & 0x80) { |
330 | if (!scsi_dma_is_ignored_buserr( dma_stat )) { | 327 | if (!scsi_dma_is_ignored_buserr(dma_stat)) { |
331 | printk(KERN_ERR "SCSI DMA caused bus error near 0x%08lx\n", | 328 | printk(KERN_ERR "SCSI DMA caused bus error near 0x%08lx\n", |
332 | SCSI_DMA_READ_P(dma_addr)); | 329 | SCSI_DMA_READ_P(dma_addr)); |
333 | printk(KERN_CRIT "SCSI DMA bus error -- bad DMA programming!"); | 330 | printk(KERN_CRIT "SCSI DMA bus error -- bad DMA programming!"); |
@@ -344,8 +341,7 @@ static irqreturn_t scsi_tt_intr (int irq, void *dummy) | |||
344 | * data reg! | 341 | * data reg! |
345 | */ | 342 | */ |
346 | if ((dma_stat & 0x02) && !(dma_stat & 0x40)) { | 343 | if ((dma_stat & 0x02) && !(dma_stat & 0x40)) { |
347 | atari_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P( dma_addr ) - | 344 | atari_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P(dma_addr) - atari_dma_startaddr); |
348 | atari_dma_startaddr); | ||
349 | 345 | ||
350 | DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n", | 346 | DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n", |
351 | atari_dma_residual); | 347 | atari_dma_residual); |
@@ -353,28 +349,30 @@ static irqreturn_t scsi_tt_intr (int irq, void *dummy) | |||
353 | if ((signed int)atari_dma_residual < 0) | 349 | if ((signed int)atari_dma_residual < 0) |
354 | atari_dma_residual = 0; | 350 | atari_dma_residual = 0; |
355 | if ((dma_stat & 1) == 0) { | 351 | if ((dma_stat & 1) == 0) { |
356 | /* After read operations, we maybe have to | 352 | /* |
357 | transport some rest bytes */ | 353 | * After read operations, we maybe have to |
354 | * transport some rest bytes | ||
355 | */ | ||
358 | atari_scsi_fetch_restbytes(); | 356 | atari_scsi_fetch_restbytes(); |
359 | } | 357 | } else { |
360 | else { | 358 | /* |
361 | /* There seems to be a nasty bug in some SCSI-DMA/NCR | 359 | * There seems to be a nasty bug in some SCSI-DMA/NCR |
362 | combinations: If a target disconnects while a write | 360 | * combinations: If a target disconnects while a write |
363 | operation is going on, the address register of the | 361 | * operation is going on, the address register of the |
364 | DMA may be a few bytes farer than it actually read. | 362 | * DMA may be a few bytes farer than it actually read. |
365 | This is probably due to DMA prefetching and a delay | 363 | * This is probably due to DMA prefetching and a delay |
366 | between DMA and NCR. Experiments showed that the | 364 | * between DMA and NCR. Experiments showed that the |
367 | dma_addr is 9 bytes to high, but this could vary. | 365 | * dma_addr is 9 bytes to high, but this could vary. |
368 | The problem is, that the residual is thus calculated | 366 | * The problem is, that the residual is thus calculated |
369 | wrong and the next transfer will start behind where | 367 | * wrong and the next transfer will start behind where |
370 | it should. So we round up the residual to the next | 368 | * it should. So we round up the residual to the next |
371 | multiple of a sector size, if it isn't already a | 369 | * multiple of a sector size, if it isn't already a |
372 | multiple and the originally expected transfer size | 370 | * multiple and the originally expected transfer size |
373 | was. The latter condition is there to ensure that | 371 | * was. The latter condition is there to ensure that |
374 | the correction is taken only for "real" data | 372 | * the correction is taken only for "real" data |
375 | transfers and not for, e.g., the parameters of some | 373 | * transfers and not for, e.g., the parameters of some |
376 | other command. These shouldn't disconnect anyway. | 374 | * other command. These shouldn't disconnect anyway. |
377 | */ | 375 | */ |
378 | if (atari_dma_residual & 0x1ff) { | 376 | if (atari_dma_residual & 0x1ff) { |
379 | DMA_PRINTK("SCSI DMA: DMA bug corrected, " | 377 | DMA_PRINTK("SCSI DMA: DMA bug corrected, " |
380 | "difference %ld bytes\n", | 378 | "difference %ld bytes\n", |
@@ -394,18 +392,18 @@ static irqreturn_t scsi_tt_intr (int irq, void *dummy) | |||
394 | } | 392 | } |
395 | 393 | ||
396 | #endif /* REAL_DMA */ | 394 | #endif /* REAL_DMA */ |
397 | 395 | ||
398 | NCR5380_intr (0, 0, 0); | 396 | NCR5380_intr(0, 0); |
399 | 397 | ||
400 | #if 0 | 398 | #if 0 |
401 | /* To be sure the int is not masked */ | 399 | /* To be sure the int is not masked */ |
402 | atari_enable_irq( IRQ_TT_MFP_SCSI ); | 400 | atari_enable_irq(IRQ_TT_MFP_SCSI); |
403 | #endif | 401 | #endif |
404 | return IRQ_HANDLED; | 402 | return IRQ_HANDLED; |
405 | } | 403 | } |
406 | 404 | ||
407 | 405 | ||
408 | static irqreturn_t scsi_falcon_intr (int irq, void *dummy) | 406 | static irqreturn_t scsi_falcon_intr(int irq, void *dummy) |
409 | { | 407 | { |
410 | #ifdef REAL_DMA | 408 | #ifdef REAL_DMA |
411 | int dma_stat; | 409 | int dma_stat; |
@@ -430,7 +428,7 @@ static irqreturn_t scsi_falcon_intr (int irq, void *dummy) | |||
430 | * bytes are stuck in the ST-DMA fifo (there's no way to reach them!) | 428 | * bytes are stuck in the ST-DMA fifo (there's no way to reach them!) |
431 | */ | 429 | */ |
432 | if (atari_dma_active && (dma_stat & 0x02)) { | 430 | if (atari_dma_active && (dma_stat & 0x02)) { |
433 | unsigned long transferred; | 431 | unsigned long transferred; |
434 | 432 | ||
435 | transferred = SCSI_DMA_GETADR() - atari_dma_startaddr; | 433 | transferred = SCSI_DMA_GETADR() - atari_dma_startaddr; |
436 | /* The ST-DMA address is incremented in 2-byte steps, but the | 434 | /* The ST-DMA address is incremented in 2-byte steps, but the |
@@ -445,8 +443,7 @@ static irqreturn_t scsi_falcon_intr (int irq, void *dummy) | |||
445 | atari_dma_residual = HOSTDATA_DMALEN - transferred; | 443 | atari_dma_residual = HOSTDATA_DMALEN - transferred; |
446 | DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n", | 444 | DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n", |
447 | atari_dma_residual); | 445 | atari_dma_residual); |
448 | } | 446 | } else |
449 | else | ||
450 | atari_dma_residual = 0; | 447 | atari_dma_residual = 0; |
451 | atari_dma_active = 0; | 448 | atari_dma_active = 0; |
452 | 449 | ||
@@ -461,13 +458,13 @@ static irqreturn_t scsi_falcon_intr (int irq, void *dummy) | |||
461 | 458 | ||
462 | #endif /* REAL_DMA */ | 459 | #endif /* REAL_DMA */ |
463 | 460 | ||
464 | NCR5380_intr (0, 0, 0); | 461 | NCR5380_intr(0, 0); |
465 | return IRQ_HANDLED; | 462 | return IRQ_HANDLED; |
466 | } | 463 | } |
467 | 464 | ||
468 | 465 | ||
469 | #ifdef REAL_DMA | 466 | #ifdef REAL_DMA |
470 | static void atari_scsi_fetch_restbytes( void ) | 467 | static void atari_scsi_fetch_restbytes(void) |
471 | { | 468 | { |
472 | int nr; | 469 | int nr; |
473 | char *src, *dst; | 470 | char *src, *dst; |
@@ -505,19 +502,17 @@ static int falcon_dont_release = 0; | |||
505 | * again (but others waiting longer more probably will win). | 502 | * again (but others waiting longer more probably will win). |
506 | */ | 503 | */ |
507 | 504 | ||
508 | static void | 505 | static void falcon_release_lock_if_possible(struct NCR5380_hostdata *hostdata) |
509 | falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata ) | ||
510 | { | 506 | { |
511 | unsigned long flags; | 507 | unsigned long flags; |
512 | 508 | ||
513 | if (IS_A_TT()) return; | 509 | if (IS_A_TT()) |
514 | 510 | return; | |
511 | |||
515 | local_irq_save(flags); | 512 | local_irq_save(flags); |
516 | 513 | ||
517 | if (falcon_got_lock && | 514 | if (falcon_got_lock && !hostdata->disconnected_queue && |
518 | !hostdata->disconnected_queue && | 515 | !hostdata->issue_queue && !hostdata->connected) { |
519 | !hostdata->issue_queue && | ||
520 | !hostdata->connected) { | ||
521 | 516 | ||
522 | if (falcon_dont_release) { | 517 | if (falcon_dont_release) { |
523 | #if 0 | 518 | #if 0 |
@@ -528,7 +523,7 @@ falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata ) | |||
528 | } | 523 | } |
529 | falcon_got_lock = 0; | 524 | falcon_got_lock = 0; |
530 | stdma_release(); | 525 | stdma_release(); |
531 | wake_up( &falcon_fairness_wait ); | 526 | wake_up(&falcon_fairness_wait); |
532 | } | 527 | } |
533 | 528 | ||
534 | local_irq_restore(flags); | 529 | local_irq_restore(flags); |
@@ -549,31 +544,31 @@ falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata ) | |||
549 | * Complicated, complicated.... Sigh... | 544 | * Complicated, complicated.... Sigh... |
550 | */ | 545 | */ |
551 | 546 | ||
552 | static void falcon_get_lock( void ) | 547 | static void falcon_get_lock(void) |
553 | { | 548 | { |
554 | unsigned long flags; | 549 | unsigned long flags; |
555 | 550 | ||
556 | if (IS_A_TT()) return; | 551 | if (IS_A_TT()) |
552 | return; | ||
557 | 553 | ||
558 | local_irq_save(flags); | 554 | local_irq_save(flags); |
559 | 555 | ||
560 | while( !in_interrupt() && falcon_got_lock && stdma_others_waiting() ) | 556 | while (!in_irq() && falcon_got_lock && stdma_others_waiting()) |
561 | sleep_on( &falcon_fairness_wait ); | 557 | sleep_on(&falcon_fairness_wait); |
562 | 558 | ||
563 | while (!falcon_got_lock) { | 559 | while (!falcon_got_lock) { |
564 | if (in_interrupt()) | 560 | if (in_irq()) |
565 | panic( "Falcon SCSI hasn't ST-DMA lock in interrupt" ); | 561 | panic("Falcon SCSI hasn't ST-DMA lock in interrupt"); |
566 | if (!falcon_trying_lock) { | 562 | if (!falcon_trying_lock) { |
567 | falcon_trying_lock = 1; | 563 | falcon_trying_lock = 1; |
568 | stdma_lock(scsi_falcon_intr, NULL); | 564 | stdma_lock(scsi_falcon_intr, NULL); |
569 | falcon_got_lock = 1; | 565 | falcon_got_lock = 1; |
570 | falcon_trying_lock = 0; | 566 | falcon_trying_lock = 0; |
571 | wake_up( &falcon_try_wait ); | 567 | wake_up(&falcon_try_wait); |
572 | } | 568 | } else { |
573 | else { | 569 | sleep_on(&falcon_try_wait); |
574 | sleep_on( &falcon_try_wait ); | ||
575 | } | 570 | } |
576 | } | 571 | } |
577 | 572 | ||
578 | local_irq_restore(flags); | 573 | local_irq_restore(flags); |
579 | if (!falcon_got_lock) | 574 | if (!falcon_got_lock) |
@@ -587,18 +582,18 @@ static void falcon_get_lock( void ) | |||
587 | */ | 582 | */ |
588 | 583 | ||
589 | #if 0 | 584 | #if 0 |
590 | int atari_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) | 585 | int atari_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) |
591 | { | 586 | { |
592 | /* falcon_get_lock(); | 587 | /* falcon_get_lock(); |
593 | * ++guenther: moved to NCR5380_queue_command() to prevent | 588 | * ++guenther: moved to NCR5380_queue_command() to prevent |
594 | * race condition, see there for an explanation. | 589 | * race condition, see there for an explanation. |
595 | */ | 590 | */ |
596 | return( NCR5380_queue_command( cmd, done ) ); | 591 | return NCR5380_queue_command(cmd, done); |
597 | } | 592 | } |
598 | #endif | 593 | #endif |
599 | 594 | ||
600 | 595 | ||
601 | int atari_scsi_detect (struct scsi_host_template *host) | 596 | int atari_scsi_detect(struct scsi_host_template *host) |
602 | { | 597 | { |
603 | static int called = 0; | 598 | static int called = 0; |
604 | struct Scsi_Host *instance; | 599 | struct Scsi_Host *instance; |
@@ -606,7 +601,7 @@ int atari_scsi_detect (struct scsi_host_template *host) | |||
606 | if (!MACH_IS_ATARI || | 601 | if (!MACH_IS_ATARI || |
607 | (!ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(TT_SCSI)) || | 602 | (!ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(TT_SCSI)) || |
608 | called) | 603 | called) |
609 | return( 0 ); | 604 | return 0; |
610 | 605 | ||
611 | host->proc_name = "Atari"; | 606 | host->proc_name = "Atari"; |
612 | 607 | ||
@@ -655,32 +650,33 @@ int atari_scsi_detect (struct scsi_host_template *host) | |||
655 | !ATARIHW_PRESENT(EXTD_DMA) && m68k_num_memory > 1) { | 650 | !ATARIHW_PRESENT(EXTD_DMA) && m68k_num_memory > 1) { |
656 | atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI"); | 651 | atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI"); |
657 | if (!atari_dma_buffer) { | 652 | if (!atari_dma_buffer) { |
658 | printk( KERN_ERR "atari_scsi_detect: can't allocate ST-RAM " | 653 | printk(KERN_ERR "atari_scsi_detect: can't allocate ST-RAM " |
659 | "double buffer\n" ); | 654 | "double buffer\n"); |
660 | return( 0 ); | 655 | return 0; |
661 | } | 656 | } |
662 | atari_dma_phys_buffer = virt_to_phys( atari_dma_buffer ); | 657 | atari_dma_phys_buffer = virt_to_phys(atari_dma_buffer); |
663 | atari_dma_orig_addr = 0; | 658 | atari_dma_orig_addr = 0; |
664 | } | 659 | } |
665 | #endif | 660 | #endif |
666 | instance = scsi_register (host, sizeof (struct NCR5380_hostdata)); | 661 | instance = scsi_register(host, sizeof(struct NCR5380_hostdata)); |
667 | if(instance == NULL) | 662 | if (instance == NULL) { |
668 | { | ||
669 | atari_stram_free(atari_dma_buffer); | 663 | atari_stram_free(atari_dma_buffer); |
670 | atari_dma_buffer = 0; | 664 | atari_dma_buffer = 0; |
671 | return 0; | 665 | return 0; |
672 | } | 666 | } |
673 | atari_scsi_host = instance; | 667 | atari_scsi_host = instance; |
674 | /* Set irq to 0, to avoid that the mid-level code disables our interrupt | 668 | /* |
675 | * during queue_command calls. This is completely unnecessary, and even | 669 | * Set irq to 0, to avoid that the mid-level code disables our interrupt |
676 | * worse causes bad problems on the Falcon, where the int is shared with | 670 | * during queue_command calls. This is completely unnecessary, and even |
677 | * IDE and floppy! */ | 671 | * worse causes bad problems on the Falcon, where the int is shared with |
672 | * IDE and floppy! | ||
673 | */ | ||
678 | instance->irq = 0; | 674 | instance->irq = 0; |
679 | 675 | ||
680 | #ifdef CONFIG_ATARI_SCSI_RESET_BOOT | 676 | #ifdef CONFIG_ATARI_SCSI_RESET_BOOT |
681 | atari_scsi_reset_boot(); | 677 | atari_scsi_reset_boot(); |
682 | #endif | 678 | #endif |
683 | NCR5380_init (instance, 0); | 679 | NCR5380_init(instance, 0); |
684 | 680 | ||
685 | if (IS_A_TT()) { | 681 | if (IS_A_TT()) { |
686 | 682 | ||
@@ -727,11 +723,10 @@ int atari_scsi_detect (struct scsi_host_template *host) | |||
727 | * the rest data bug is fixed, this can be lowered to 1. | 723 | * the rest data bug is fixed, this can be lowered to 1. |
728 | */ | 724 | */ |
729 | atari_read_overruns = 4; | 725 | atari_read_overruns = 4; |
730 | } | 726 | } |
731 | #endif /*REAL_DMA*/ | 727 | #endif /*REAL_DMA*/ |
732 | } | 728 | } else { /* ! IS_A_TT */ |
733 | else { /* ! IS_A_TT */ | 729 | |
734 | |||
735 | /* Nothing to do for the interrupt: the ST-DMA is initialized | 730 | /* Nothing to do for the interrupt: the ST-DMA is initialized |
736 | * already by atari_init_INTS() | 731 | * already by atari_init_INTS() |
737 | */ | 732 | */ |
@@ -756,23 +751,21 @@ int atari_scsi_detect (struct scsi_host_template *host) | |||
756 | setup_use_tagged_queuing ? "yes" : "no", | 751 | setup_use_tagged_queuing ? "yes" : "no", |
757 | #endif | 752 | #endif |
758 | instance->hostt->this_id ); | 753 | instance->hostt->this_id ); |
759 | NCR5380_print_options (instance); | 754 | NCR5380_print_options(instance); |
760 | printk ("\n"); | 755 | printk("\n"); |
761 | 756 | ||
762 | called = 1; | 757 | called = 1; |
763 | return( 1 ); | 758 | return 1; |
764 | } | 759 | } |
765 | 760 | ||
766 | #ifdef MODULE | 761 | int atari_scsi_release(struct Scsi_Host *sh) |
767 | int atari_scsi_release (struct Scsi_Host *sh) | ||
768 | { | 762 | { |
769 | if (IS_A_TT()) | 763 | if (IS_A_TT()) |
770 | free_irq(IRQ_TT_MFP_SCSI, scsi_tt_intr); | 764 | free_irq(IRQ_TT_MFP_SCSI, scsi_tt_intr); |
771 | if (atari_dma_buffer) | 765 | if (atari_dma_buffer) |
772 | atari_stram_free (atari_dma_buffer); | 766 | atari_stram_free(atari_dma_buffer); |
773 | return 1; | 767 | return 1; |
774 | } | 768 | } |
775 | #endif | ||
776 | 769 | ||
777 | void __init atari_scsi_setup(char *str, int *ints) | 770 | void __init atari_scsi_setup(char *str, int *ints) |
778 | { | 771 | { |
@@ -781,9 +774,9 @@ void __init atari_scsi_setup(char *str, int *ints) | |||
781 | * Defaults depend on TT or Falcon, hostid determined at run time. | 774 | * Defaults depend on TT or Falcon, hostid determined at run time. |
782 | * Negative values mean don't change. | 775 | * Negative values mean don't change. |
783 | */ | 776 | */ |
784 | 777 | ||
785 | if (ints[0] < 1) { | 778 | if (ints[0] < 1) { |
786 | printk( "atari_scsi_setup: no arguments!\n" ); | 779 | printk("atari_scsi_setup: no arguments!\n"); |
787 | return; | 780 | return; |
788 | } | 781 | } |
789 | 782 | ||
@@ -809,7 +802,7 @@ void __init atari_scsi_setup(char *str, int *ints) | |||
809 | if (ints[4] >= 0 && ints[4] <= 7) | 802 | if (ints[4] >= 0 && ints[4] <= 7) |
810 | setup_hostid = ints[4]; | 803 | setup_hostid = ints[4]; |
811 | else if (ints[4] > 7) | 804 | else if (ints[4] > 7) |
812 | printk( "atari_scsi_setup: invalid host ID %d !\n", ints[4] ); | 805 | printk("atari_scsi_setup: invalid host ID %d !\n", ints[4]); |
813 | } | 806 | } |
814 | #ifdef SUPPORT_TAGS | 807 | #ifdef SUPPORT_TAGS |
815 | if (ints[0] >= 5) { | 808 | if (ints[0] >= 5) { |
@@ -821,7 +814,7 @@ void __init atari_scsi_setup(char *str, int *ints) | |||
821 | 814 | ||
822 | int atari_scsi_bus_reset(Scsi_Cmnd *cmd) | 815 | int atari_scsi_bus_reset(Scsi_Cmnd *cmd) |
823 | { | 816 | { |
824 | int rv; | 817 | int rv; |
825 | struct NCR5380_hostdata *hostdata = | 818 | struct NCR5380_hostdata *hostdata = |
826 | (struct NCR5380_hostdata *)cmd->device->host->hostdata; | 819 | (struct NCR5380_hostdata *)cmd->device->host->hostdata; |
827 | 820 | ||
@@ -831,13 +824,12 @@ int atari_scsi_bus_reset(Scsi_Cmnd *cmd) | |||
831 | */ | 824 | */ |
832 | /* And abort a maybe active DMA transfer */ | 825 | /* And abort a maybe active DMA transfer */ |
833 | if (IS_A_TT()) { | 826 | if (IS_A_TT()) { |
834 | atari_turnoff_irq( IRQ_TT_MFP_SCSI ); | 827 | atari_turnoff_irq(IRQ_TT_MFP_SCSI); |
835 | #ifdef REAL_DMA | 828 | #ifdef REAL_DMA |
836 | tt_scsi_dma.dma_ctrl = 0; | 829 | tt_scsi_dma.dma_ctrl = 0; |
837 | #endif /* REAL_DMA */ | 830 | #endif /* REAL_DMA */ |
838 | } | 831 | } else { |
839 | else { | 832 | atari_turnoff_irq(IRQ_MFP_FSCSI); |
840 | atari_turnoff_irq( IRQ_MFP_FSCSI ); | ||
841 | #ifdef REAL_DMA | 833 | #ifdef REAL_DMA |
842 | st_dma.dma_mode_status = 0x90; | 834 | st_dma.dma_mode_status = 0x90; |
843 | atari_dma_active = 0; | 835 | atari_dma_active = 0; |
@@ -849,52 +841,51 @@ int atari_scsi_bus_reset(Scsi_Cmnd *cmd) | |||
849 | 841 | ||
850 | /* Re-enable ints */ | 842 | /* Re-enable ints */ |
851 | if (IS_A_TT()) { | 843 | if (IS_A_TT()) { |
852 | atari_turnon_irq( IRQ_TT_MFP_SCSI ); | 844 | atari_turnon_irq(IRQ_TT_MFP_SCSI); |
853 | } | 845 | } else { |
854 | else { | 846 | atari_turnon_irq(IRQ_MFP_FSCSI); |
855 | atari_turnon_irq( IRQ_MFP_FSCSI ); | ||
856 | } | 847 | } |
857 | if ((rv & SCSI_RESET_ACTION) == SCSI_RESET_SUCCESS) | 848 | if ((rv & SCSI_RESET_ACTION) == SCSI_RESET_SUCCESS) |
858 | falcon_release_lock_if_possible(hostdata); | 849 | falcon_release_lock_if_possible(hostdata); |
859 | 850 | ||
860 | return( rv ); | 851 | return rv; |
861 | } | 852 | } |
862 | 853 | ||
863 | 854 | ||
864 | #ifdef CONFIG_ATARI_SCSI_RESET_BOOT | 855 | #ifdef CONFIG_ATARI_SCSI_RESET_BOOT |
865 | static void __init atari_scsi_reset_boot(void) | 856 | static void __init atari_scsi_reset_boot(void) |
866 | { | 857 | { |
867 | unsigned long end; | 858 | unsigned long end; |
868 | 859 | ||
869 | /* | 860 | /* |
870 | * Do a SCSI reset to clean up the bus during initialization. No messing | 861 | * Do a SCSI reset to clean up the bus during initialization. No messing |
871 | * with the queues, interrupts, or locks necessary here. | 862 | * with the queues, interrupts, or locks necessary here. |
872 | */ | 863 | */ |
873 | 864 | ||
874 | printk( "Atari SCSI: resetting the SCSI bus..." ); | 865 | printk("Atari SCSI: resetting the SCSI bus..."); |
875 | 866 | ||
876 | /* get in phase */ | 867 | /* get in phase */ |
877 | NCR5380_write( TARGET_COMMAND_REG, | 868 | NCR5380_write(TARGET_COMMAND_REG, |
878 | PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) )); | 869 | PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG))); |
879 | 870 | ||
880 | /* assert RST */ | 871 | /* assert RST */ |
881 | NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST ); | 872 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST); |
882 | /* The min. reset hold time is 25us, so 40us should be enough */ | 873 | /* The min. reset hold time is 25us, so 40us should be enough */ |
883 | udelay( 50 ); | 874 | udelay(50); |
884 | /* reset RST and interrupt */ | 875 | /* reset RST and interrupt */ |
885 | NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE ); | 876 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
886 | NCR5380_read( RESET_PARITY_INTERRUPT_REG ); | 877 | NCR5380_read(RESET_PARITY_INTERRUPT_REG); |
887 | 878 | ||
888 | end = jiffies + AFTER_RESET_DELAY; | 879 | end = jiffies + AFTER_RESET_DELAY; |
889 | while (time_before(jiffies, end)) | 880 | while (time_before(jiffies, end)) |
890 | barrier(); | 881 | barrier(); |
891 | 882 | ||
892 | printk( " done\n" ); | 883 | printk(" done\n"); |
893 | } | 884 | } |
894 | #endif | 885 | #endif |
895 | 886 | ||
896 | 887 | ||
897 | const char * atari_scsi_info (struct Scsi_Host *host) | 888 | const char *atari_scsi_info(struct Scsi_Host *host) |
898 | { | 889 | { |
899 | /* atari_scsi_detect() is verbose enough... */ | 890 | /* atari_scsi_detect() is verbose enough... */ |
900 | static const char string[] = "Atari native SCSI"; | 891 | static const char string[] = "Atari native SCSI"; |
@@ -904,10 +895,10 @@ const char * atari_scsi_info (struct Scsi_Host *host) | |||
904 | 895 | ||
905 | #if defined(REAL_DMA) | 896 | #if defined(REAL_DMA) |
906 | 897 | ||
907 | unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data, | 898 | unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance, void *data, |
908 | unsigned long count, int dir ) | 899 | unsigned long count, int dir) |
909 | { | 900 | { |
910 | unsigned long addr = virt_to_phys( data ); | 901 | unsigned long addr = virt_to_phys(data); |
911 | 902 | ||
912 | DMA_PRINTK("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, " | 903 | DMA_PRINTK("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, " |
913 | "dir = %d\n", instance->host_no, data, addr, count, dir); | 904 | "dir = %d\n", instance->host_no, data, addr, count, dir); |
@@ -919,38 +910,37 @@ unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data, | |||
919 | * wanted address. | 910 | * wanted address. |
920 | */ | 911 | */ |
921 | if (dir) | 912 | if (dir) |
922 | memcpy( atari_dma_buffer, data, count ); | 913 | memcpy(atari_dma_buffer, data, count); |
923 | else | 914 | else |
924 | atari_dma_orig_addr = data; | 915 | atari_dma_orig_addr = data; |
925 | addr = atari_dma_phys_buffer; | 916 | addr = atari_dma_phys_buffer; |
926 | } | 917 | } |
927 | 918 | ||
928 | atari_dma_startaddr = addr; /* Needed for calculating residual later. */ | 919 | atari_dma_startaddr = addr; /* Needed for calculating residual later. */ |
929 | 920 | ||
930 | /* Cache cleanup stuff: On writes, push any dirty cache out before sending | 921 | /* Cache cleanup stuff: On writes, push any dirty cache out before sending |
931 | * it to the peripheral. (Must be done before DMA setup, since at least | 922 | * it to the peripheral. (Must be done before DMA setup, since at least |
932 | * the ST-DMA begins to fill internal buffers right after setup. For | 923 | * the ST-DMA begins to fill internal buffers right after setup. For |
933 | * reads, invalidate any cache, may be altered after DMA without CPU | 924 | * reads, invalidate any cache, may be altered after DMA without CPU |
934 | * knowledge. | 925 | * knowledge. |
935 | * | 926 | * |
936 | * ++roman: For the Medusa, there's no need at all for that cache stuff, | 927 | * ++roman: For the Medusa, there's no need at all for that cache stuff, |
937 | * because the hardware does bus snooping (fine!). | 928 | * because the hardware does bus snooping (fine!). |
938 | */ | 929 | */ |
939 | dma_cache_maintenance( addr, count, dir ); | 930 | dma_cache_maintenance(addr, count, dir); |
940 | 931 | ||
941 | if (count == 0) | 932 | if (count == 0) |
942 | printk(KERN_NOTICE "SCSI warning: DMA programmed for 0 bytes !\n"); | 933 | printk(KERN_NOTICE "SCSI warning: DMA programmed for 0 bytes !\n"); |
943 | 934 | ||
944 | if (IS_A_TT()) { | 935 | if (IS_A_TT()) { |
945 | tt_scsi_dma.dma_ctrl = dir; | 936 | tt_scsi_dma.dma_ctrl = dir; |
946 | SCSI_DMA_WRITE_P( dma_addr, addr ); | 937 | SCSI_DMA_WRITE_P(dma_addr, addr); |
947 | SCSI_DMA_WRITE_P( dma_cnt, count ); | 938 | SCSI_DMA_WRITE_P(dma_cnt, count); |
948 | tt_scsi_dma.dma_ctrl = dir | 2; | 939 | tt_scsi_dma.dma_ctrl = dir | 2; |
949 | } | 940 | } else { /* ! IS_A_TT */ |
950 | else { /* ! IS_A_TT */ | 941 | |
951 | |||
952 | /* set address */ | 942 | /* set address */ |
953 | SCSI_DMA_SETADR( addr ); | 943 | SCSI_DMA_SETADR(addr); |
954 | 944 | ||
955 | /* toggle direction bit to clear FIFO and set DMA direction */ | 945 | /* toggle direction bit to clear FIFO and set DMA direction */ |
956 | dir <<= 8; | 946 | dir <<= 8; |
@@ -968,13 +958,13 @@ unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data, | |||
968 | atari_dma_active = 1; | 958 | atari_dma_active = 1; |
969 | } | 959 | } |
970 | 960 | ||
971 | return( count ); | 961 | return count; |
972 | } | 962 | } |
973 | 963 | ||
974 | 964 | ||
975 | static long atari_scsi_dma_residual( struct Scsi_Host *instance ) | 965 | static long atari_scsi_dma_residual(struct Scsi_Host *instance) |
976 | { | 966 | { |
977 | return( atari_dma_residual ); | 967 | return atari_dma_residual; |
978 | } | 968 | } |
979 | 969 | ||
980 | 970 | ||
@@ -982,13 +972,13 @@ static long atari_scsi_dma_residual( struct Scsi_Host *instance ) | |||
982 | #define CMD_SURELY_BYTE_MODE 1 | 972 | #define CMD_SURELY_BYTE_MODE 1 |
983 | #define CMD_MODE_UNKNOWN 2 | 973 | #define CMD_MODE_UNKNOWN 2 |
984 | 974 | ||
985 | static int falcon_classify_cmd( Scsi_Cmnd *cmd ) | 975 | static int falcon_classify_cmd(Scsi_Cmnd *cmd) |
986 | { | 976 | { |
987 | unsigned char opcode = cmd->cmnd[0]; | 977 | unsigned char opcode = cmd->cmnd[0]; |
988 | 978 | ||
989 | if (opcode == READ_DEFECT_DATA || opcode == READ_LONG || | 979 | if (opcode == READ_DEFECT_DATA || opcode == READ_LONG || |
990 | opcode == READ_BUFFER) | 980 | opcode == READ_BUFFER) |
991 | return( CMD_SURELY_BYTE_MODE ); | 981 | return CMD_SURELY_BYTE_MODE; |
992 | else if (opcode == READ_6 || opcode == READ_10 || | 982 | else if (opcode == READ_6 || opcode == READ_10 || |
993 | opcode == 0xa8 /* READ_12 */ || opcode == READ_REVERSE || | 983 | opcode == 0xa8 /* READ_12 */ || opcode == READ_REVERSE || |
994 | opcode == RECOVER_BUFFERED_DATA) { | 984 | opcode == RECOVER_BUFFERED_DATA) { |
@@ -996,12 +986,11 @@ static int falcon_classify_cmd( Scsi_Cmnd *cmd ) | |||
996 | * needed here: The transfer is block-mode only if the 'fixed' bit is | 986 | * needed here: The transfer is block-mode only if the 'fixed' bit is |
997 | * set! */ | 987 | * set! */ |
998 | if (cmd->device->type == TYPE_TAPE && !(cmd->cmnd[1] & 1)) | 988 | if (cmd->device->type == TYPE_TAPE && !(cmd->cmnd[1] & 1)) |
999 | return( CMD_SURELY_BYTE_MODE ); | 989 | return CMD_SURELY_BYTE_MODE; |
1000 | else | 990 | else |
1001 | return( CMD_SURELY_BLOCK_MODE ); | 991 | return CMD_SURELY_BLOCK_MODE; |
1002 | } | 992 | } else |
1003 | else | 993 | return CMD_MODE_UNKNOWN; |
1004 | return( CMD_MODE_UNKNOWN ); | ||
1005 | } | 994 | } |
1006 | 995 | ||
1007 | 996 | ||
@@ -1014,19 +1003,18 @@ static int falcon_classify_cmd( Scsi_Cmnd *cmd ) | |||
1014 | * the overrun problem, so this question is academic :-) | 1003 | * the overrun problem, so this question is academic :-) |
1015 | */ | 1004 | */ |
1016 | 1005 | ||
1017 | static unsigned long atari_dma_xfer_len( unsigned long wanted_len, | 1006 | static unsigned long atari_dma_xfer_len(unsigned long wanted_len, |
1018 | Scsi_Cmnd *cmd, | 1007 | Scsi_Cmnd *cmd, int write_flag) |
1019 | int write_flag ) | ||
1020 | { | 1008 | { |
1021 | unsigned long possible_len, limit; | 1009 | unsigned long possible_len, limit; |
1022 | #ifndef CONFIG_TT_DMA_EMUL | 1010 | #ifndef CONFIG_TT_DMA_EMUL |
1023 | if (MACH_IS_HADES) | 1011 | if (MACH_IS_HADES) |
1024 | /* Hades has no SCSI DMA at all :-( Always force use of PIO */ | 1012 | /* Hades has no SCSI DMA at all :-( Always force use of PIO */ |
1025 | return( 0 ); | 1013 | return 0; |
1026 | #endif | 1014 | #endif |
1027 | if (IS_A_TT()) | 1015 | if (IS_A_TT()) |
1028 | /* TT SCSI DMA can transfer arbitrary #bytes */ | 1016 | /* TT SCSI DMA can transfer arbitrary #bytes */ |
1029 | return( wanted_len ); | 1017 | return wanted_len; |
1030 | 1018 | ||
1031 | /* ST DMA chip is stupid -- only multiples of 512 bytes! (and max. | 1019 | /* ST DMA chip is stupid -- only multiples of 512 bytes! (and max. |
1032 | * 255*512 bytes, but this should be enough) | 1020 | * 255*512 bytes, but this should be enough) |
@@ -1062,8 +1050,7 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len, | |||
1062 | * this). | 1050 | * this). |
1063 | */ | 1051 | */ |
1064 | possible_len = wanted_len; | 1052 | possible_len = wanted_len; |
1065 | } | 1053 | } else { |
1066 | else { | ||
1067 | /* Read operations: if the wanted transfer length is not a multiple of | 1054 | /* Read operations: if the wanted transfer length is not a multiple of |
1068 | * 512, we cannot use DMA, since the ST-DMA cannot split transfers | 1055 | * 512, we cannot use DMA, since the ST-DMA cannot split transfers |
1069 | * (no interrupt on DMA finished!) | 1056 | * (no interrupt on DMA finished!) |
@@ -1073,15 +1060,15 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len, | |||
1073 | else { | 1060 | else { |
1074 | /* Now classify the command (see above) and decide whether it is | 1061 | /* Now classify the command (see above) and decide whether it is |
1075 | * allowed to do DMA at all */ | 1062 | * allowed to do DMA at all */ |
1076 | switch( falcon_classify_cmd( cmd )) { | 1063 | switch (falcon_classify_cmd(cmd)) { |
1077 | case CMD_SURELY_BLOCK_MODE: | 1064 | case CMD_SURELY_BLOCK_MODE: |
1078 | possible_len = wanted_len; | 1065 | possible_len = wanted_len; |
1079 | break; | 1066 | break; |
1080 | case CMD_SURELY_BYTE_MODE: | 1067 | case CMD_SURELY_BYTE_MODE: |
1081 | possible_len = 0; /* DMA prohibited */ | 1068 | possible_len = 0; /* DMA prohibited */ |
1082 | break; | 1069 | break; |
1083 | case CMD_MODE_UNKNOWN: | 1070 | case CMD_MODE_UNKNOWN: |
1084 | default: | 1071 | default: |
1085 | /* For unknown commands assume block transfers if the transfer | 1072 | /* For unknown commands assume block transfers if the transfer |
1086 | * size/allocation length is >= 1024 */ | 1073 | * size/allocation length is >= 1024 */ |
1087 | possible_len = (wanted_len < 1024) ? 0 : wanted_len; | 1074 | possible_len = (wanted_len < 1024) ? 0 : wanted_len; |
@@ -1089,9 +1076,9 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len, | |||
1089 | } | 1076 | } |
1090 | } | 1077 | } |
1091 | } | 1078 | } |
1092 | 1079 | ||
1093 | /* Last step: apply the hard limit on DMA transfers */ | 1080 | /* Last step: apply the hard limit on DMA transfers */ |
1094 | limit = (atari_dma_buffer && !STRAM_ADDR( virt_to_phys(cmd->SCp.ptr) )) ? | 1081 | limit = (atari_dma_buffer && !STRAM_ADDR(virt_to_phys(cmd->SCp.ptr))) ? |
1095 | STRAM_BUFFER_SIZE : 255*512; | 1082 | STRAM_BUFFER_SIZE : 255*512; |
1096 | if (possible_len > limit) | 1083 | if (possible_len > limit) |
1097 | possible_len = limit; | 1084 | possible_len = limit; |
@@ -1100,7 +1087,7 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len, | |||
1100 | DMA_PRINTK("Sorry, must cut DMA transfer size to %ld bytes " | 1087 | DMA_PRINTK("Sorry, must cut DMA transfer size to %ld bytes " |
1101 | "instead of %ld\n", possible_len, wanted_len); | 1088 | "instead of %ld\n", possible_len, wanted_len); |
1102 | 1089 | ||
1103 | return( possible_len ); | 1090 | return possible_len; |
1104 | } | 1091 | } |
1105 | 1092 | ||
1106 | 1093 | ||
@@ -1114,23 +1101,23 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len, | |||
1114 | * NCR5380_write call these functions via function pointers. | 1101 | * NCR5380_write call these functions via function pointers. |
1115 | */ | 1102 | */ |
1116 | 1103 | ||
1117 | static unsigned char atari_scsi_tt_reg_read( unsigned char reg ) | 1104 | static unsigned char atari_scsi_tt_reg_read(unsigned char reg) |
1118 | { | 1105 | { |
1119 | return( tt_scsi_regp[reg * 2] ); | 1106 | return tt_scsi_regp[reg * 2]; |
1120 | } | 1107 | } |
1121 | 1108 | ||
1122 | static void atari_scsi_tt_reg_write( unsigned char reg, unsigned char value ) | 1109 | static void atari_scsi_tt_reg_write(unsigned char reg, unsigned char value) |
1123 | { | 1110 | { |
1124 | tt_scsi_regp[reg * 2] = value; | 1111 | tt_scsi_regp[reg * 2] = value; |
1125 | } | 1112 | } |
1126 | 1113 | ||
1127 | static unsigned char atari_scsi_falcon_reg_read( unsigned char reg ) | 1114 | static unsigned char atari_scsi_falcon_reg_read(unsigned char reg) |
1128 | { | 1115 | { |
1129 | dma_wd.dma_mode_status= (u_short)(0x88 + reg); | 1116 | dma_wd.dma_mode_status= (u_short)(0x88 + reg); |
1130 | return( (u_char)dma_wd.fdc_acces_seccount ); | 1117 | return (u_char)dma_wd.fdc_acces_seccount; |
1131 | } | 1118 | } |
1132 | 1119 | ||
1133 | static void atari_scsi_falcon_reg_write( unsigned char reg, unsigned char value ) | 1120 | static void atari_scsi_falcon_reg_write(unsigned char reg, unsigned char value) |
1134 | { | 1121 | { |
1135 | dma_wd.dma_mode_status = (u_short)(0x88 + reg); | 1122 | dma_wd.dma_mode_status = (u_short)(0x88 + reg); |
1136 | dma_wd.fdc_acces_seccount = (u_short)value; | 1123 | dma_wd.fdc_acces_seccount = (u_short)value; |
diff --git a/drivers/scsi/atari_scsi.h b/drivers/scsi/atari_scsi.h index f917bdd09b41..efadb8d567c2 100644 --- a/drivers/scsi/atari_scsi.h +++ b/drivers/scsi/atari_scsi.h | |||
@@ -21,11 +21,7 @@ | |||
21 | int atari_scsi_detect (struct scsi_host_template *); | 21 | int atari_scsi_detect (struct scsi_host_template *); |
22 | const char *atari_scsi_info (struct Scsi_Host *); | 22 | const char *atari_scsi_info (struct Scsi_Host *); |
23 | int atari_scsi_reset (Scsi_Cmnd *, unsigned int); | 23 | int atari_scsi_reset (Scsi_Cmnd *, unsigned int); |
24 | #ifdef MODULE | ||
25 | int atari_scsi_release (struct Scsi_Host *); | 24 | int atari_scsi_release (struct Scsi_Host *); |
26 | #else | ||
27 | #define atari_scsi_release NULL | ||
28 | #endif | ||
29 | 25 | ||
30 | /* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary. Higher | 26 | /* The values for CMD_PER_LUN and CAN_QUEUE are somehow arbitrary. Higher |
31 | * values should work, too; try it! (but cmd_per_lun costs memory!) */ | 27 | * values should work, too; try it! (but cmd_per_lun costs memory!) */ |
@@ -63,6 +59,32 @@ int atari_scsi_release (struct Scsi_Host *); | |||
63 | #define NCR5380_dma_xfer_len(i,cmd,phase) \ | 59 | #define NCR5380_dma_xfer_len(i,cmd,phase) \ |
64 | atari_dma_xfer_len(cmd->SCp.this_residual,cmd,((phase) & SR_IO) ? 0 : 1) | 60 | atari_dma_xfer_len(cmd->SCp.this_residual,cmd,((phase) & SR_IO) ? 0 : 1) |
65 | 61 | ||
62 | /* former generic SCSI error handling stuff */ | ||
63 | |||
64 | #define SCSI_ABORT_SNOOZE 0 | ||
65 | #define SCSI_ABORT_SUCCESS 1 | ||
66 | #define SCSI_ABORT_PENDING 2 | ||
67 | #define SCSI_ABORT_BUSY 3 | ||
68 | #define SCSI_ABORT_NOT_RUNNING 4 | ||
69 | #define SCSI_ABORT_ERROR 5 | ||
70 | |||
71 | #define SCSI_RESET_SNOOZE 0 | ||
72 | #define SCSI_RESET_PUNT 1 | ||
73 | #define SCSI_RESET_SUCCESS 2 | ||
74 | #define SCSI_RESET_PENDING 3 | ||
75 | #define SCSI_RESET_WAKEUP 4 | ||
76 | #define SCSI_RESET_NOT_RUNNING 5 | ||
77 | #define SCSI_RESET_ERROR 6 | ||
78 | |||
79 | #define SCSI_RESET_SYNCHRONOUS 0x01 | ||
80 | #define SCSI_RESET_ASYNCHRONOUS 0x02 | ||
81 | #define SCSI_RESET_SUGGEST_BUS_RESET 0x04 | ||
82 | #define SCSI_RESET_SUGGEST_HOST_RESET 0x08 | ||
83 | |||
84 | #define SCSI_RESET_BUS_RESET 0x100 | ||
85 | #define SCSI_RESET_HOST_RESET 0x200 | ||
86 | #define SCSI_RESET_ACTION 0xff | ||
87 | |||
66 | /* Debugging printk definitions: | 88 | /* Debugging printk definitions: |
67 | * | 89 | * |
68 | * ARB -> arbitration | 90 | * ARB -> arbitration |
@@ -91,144 +113,58 @@ int atari_scsi_release (struct Scsi_Host *); | |||
91 | * | 113 | * |
92 | */ | 114 | */ |
93 | 115 | ||
94 | #if NDEBUG & NDEBUG_ARBITRATION | 116 | #define dprint(flg, format...) \ |
117 | ({ \ | ||
118 | if (NDEBUG & (flg)) \ | ||
119 | printk(KERN_DEBUG format); \ | ||
120 | }) | ||
121 | |||
95 | #define ARB_PRINTK(format, args...) \ | 122 | #define ARB_PRINTK(format, args...) \ |
96 | printk(KERN_DEBUG format , ## args) | 123 | dprint(NDEBUG_ARBITRATION, format , ## args) |
97 | #else | ||
98 | #define ARB_PRINTK(format, args...) | ||
99 | #endif | ||
100 | #if NDEBUG & NDEBUG_AUTOSENSE | ||
101 | #define ASEN_PRINTK(format, args...) \ | 124 | #define ASEN_PRINTK(format, args...) \ |
102 | printk(KERN_DEBUG format , ## args) | 125 | dprint(NDEBUG_AUTOSENSE, format , ## args) |
103 | #else | ||
104 | #define ASEN_PRINTK(format, args...) | ||
105 | #endif | ||
106 | #if NDEBUG & NDEBUG_DMA | ||
107 | #define DMA_PRINTK(format, args...) \ | 126 | #define DMA_PRINTK(format, args...) \ |
108 | printk(KERN_DEBUG format , ## args) | 127 | dprint(NDEBUG_DMA, format , ## args) |
109 | #else | ||
110 | #define DMA_PRINTK(format, args...) | ||
111 | #endif | ||
112 | #if NDEBUG & NDEBUG_HANDSHAKE | ||
113 | #define HSH_PRINTK(format, args...) \ | 128 | #define HSH_PRINTK(format, args...) \ |
114 | printk(KERN_DEBUG format , ## args) | 129 | dprint(NDEBUG_HANDSHAKE, format , ## args) |
115 | #else | ||
116 | #define HSH_PRINTK(format, args...) | ||
117 | #endif | ||
118 | #if NDEBUG & NDEBUG_INFORMATION | ||
119 | #define INF_PRINTK(format, args...) \ | 130 | #define INF_PRINTK(format, args...) \ |
120 | printk(KERN_DEBUG format , ## args) | 131 | dprint(NDEBUG_INFORMATION, format , ## args) |
121 | #else | ||
122 | #define INF_PRINTK(format, args...) | ||
123 | #endif | ||
124 | #if NDEBUG & NDEBUG_INIT | ||
125 | #define INI_PRINTK(format, args...) \ | 132 | #define INI_PRINTK(format, args...) \ |
126 | printk(KERN_DEBUG format , ## args) | 133 | dprint(NDEBUG_INIT, format , ## args) |
127 | #else | ||
128 | #define INI_PRINTK(format, args...) | ||
129 | #endif | ||
130 | #if NDEBUG & NDEBUG_INTR | ||
131 | #define INT_PRINTK(format, args...) \ | 134 | #define INT_PRINTK(format, args...) \ |
132 | printk(KERN_DEBUG format , ## args) | 135 | dprint(NDEBUG_INTR, format , ## args) |
133 | #else | ||
134 | #define INT_PRINTK(format, args...) | ||
135 | #endif | ||
136 | #if NDEBUG & NDEBUG_LINKED | ||
137 | #define LNK_PRINTK(format, args...) \ | 136 | #define LNK_PRINTK(format, args...) \ |
138 | printk(KERN_DEBUG format , ## args) | 137 | dprint(NDEBUG_LINKED, format , ## args) |
139 | #else | ||
140 | #define LNK_PRINTK(format, args...) | ||
141 | #endif | ||
142 | #if NDEBUG & NDEBUG_MAIN | ||
143 | #define MAIN_PRINTK(format, args...) \ | 138 | #define MAIN_PRINTK(format, args...) \ |
144 | printk(KERN_DEBUG format , ## args) | 139 | dprint(NDEBUG_MAIN, format , ## args) |
145 | #else | ||
146 | #define MAIN_PRINTK(format, args...) | ||
147 | #endif | ||
148 | #if NDEBUG & NDEBUG_NO_DATAOUT | ||
149 | #define NDAT_PRINTK(format, args...) \ | 140 | #define NDAT_PRINTK(format, args...) \ |
150 | printk(KERN_DEBUG format , ## args) | 141 | dprint(NDEBUG_NO_DATAOUT, format , ## args) |
151 | #else | ||
152 | #define NDAT_PRINTK(format, args...) | ||
153 | #endif | ||
154 | #if NDEBUG & NDEBUG_NO_WRITE | ||
155 | #define NWR_PRINTK(format, args...) \ | 142 | #define NWR_PRINTK(format, args...) \ |
156 | printk(KERN_DEBUG format , ## args) | 143 | dprint(NDEBUG_NO_WRITE, format , ## args) |
157 | #else | ||
158 | #define NWR_PRINTK(format, args...) | ||
159 | #endif | ||
160 | #if NDEBUG & NDEBUG_PIO | ||
161 | #define PIO_PRINTK(format, args...) \ | 144 | #define PIO_PRINTK(format, args...) \ |
162 | printk(KERN_DEBUG format , ## args) | 145 | dprint(NDEBUG_PIO, format , ## args) |
163 | #else | ||
164 | #define PIO_PRINTK(format, args...) | ||
165 | #endif | ||
166 | #if NDEBUG & NDEBUG_PSEUDO_DMA | ||
167 | #define PDMA_PRINTK(format, args...) \ | 146 | #define PDMA_PRINTK(format, args...) \ |
168 | printk(KERN_DEBUG format , ## args) | 147 | dprint(NDEBUG_PSEUDO_DMA, format , ## args) |
169 | #else | ||
170 | #define PDMA_PRINTK(format, args...) | ||
171 | #endif | ||
172 | #if NDEBUG & NDEBUG_QUEUES | ||
173 | #define QU_PRINTK(format, args...) \ | 148 | #define QU_PRINTK(format, args...) \ |
174 | printk(KERN_DEBUG format , ## args) | 149 | dprint(NDEBUG_QUEUES, format , ## args) |
175 | #else | ||
176 | #define QU_PRINTK(format, args...) | ||
177 | #endif | ||
178 | #if NDEBUG & NDEBUG_RESELECTION | ||
179 | #define RSL_PRINTK(format, args...) \ | 150 | #define RSL_PRINTK(format, args...) \ |
180 | printk(KERN_DEBUG format , ## args) | 151 | dprint(NDEBUG_RESELECTION, format , ## args) |
181 | #else | ||
182 | #define RSL_PRINTK(format, args...) | ||
183 | #endif | ||
184 | #if NDEBUG & NDEBUG_SELECTION | ||
185 | #define SEL_PRINTK(format, args...) \ | 152 | #define SEL_PRINTK(format, args...) \ |
186 | printk(KERN_DEBUG format , ## args) | 153 | dprint(NDEBUG_SELECTION, format , ## args) |
187 | #else | ||
188 | #define SEL_PRINTK(format, args...) | ||
189 | #endif | ||
190 | #if NDEBUG & NDEBUG_USLEEP | ||
191 | #define USL_PRINTK(format, args...) \ | 154 | #define USL_PRINTK(format, args...) \ |
192 | printk(KERN_DEBUG format , ## args) | 155 | dprint(NDEBUG_USLEEP, format , ## args) |
193 | #else | ||
194 | #define USL_PRINTK(format, args...) | ||
195 | #endif | ||
196 | #if NDEBUG & NDEBUG_LAST_BYTE_SENT | ||
197 | #define LBS_PRINTK(format, args...) \ | 156 | #define LBS_PRINTK(format, args...) \ |
198 | printk(KERN_DEBUG format , ## args) | 157 | dprint(NDEBUG_LAST_BYTE_SENT, format , ## args) |
199 | #else | ||
200 | #define LBS_PRINTK(format, args...) | ||
201 | #endif | ||
202 | #if NDEBUG & NDEBUG_RESTART_SELECT | ||
203 | #define RSS_PRINTK(format, args...) \ | 158 | #define RSS_PRINTK(format, args...) \ |
204 | printk(KERN_DEBUG format , ## args) | 159 | dprint(NDEBUG_RESTART_SELECT, format , ## args) |
205 | #else | ||
206 | #define RSS_PRINTK(format, args...) | ||
207 | #endif | ||
208 | #if NDEBUG & NDEBUG_EXTENDED | ||
209 | #define EXT_PRINTK(format, args...) \ | 160 | #define EXT_PRINTK(format, args...) \ |
210 | printk(KERN_DEBUG format , ## args) | 161 | dprint(NDEBUG_EXTENDED, format , ## args) |
211 | #else | ||
212 | #define EXT_PRINTK(format, args...) | ||
213 | #endif | ||
214 | #if NDEBUG & NDEBUG_ABORT | ||
215 | #define ABRT_PRINTK(format, args...) \ | 162 | #define ABRT_PRINTK(format, args...) \ |
216 | printk(KERN_DEBUG format , ## args) | 163 | dprint(NDEBUG_ABORT, format , ## args) |
217 | #else | ||
218 | #define ABRT_PRINTK(format, args...) | ||
219 | #endif | ||
220 | #if NDEBUG & NDEBUG_TAGS | ||
221 | #define TAG_PRINTK(format, args...) \ | 164 | #define TAG_PRINTK(format, args...) \ |
222 | printk(KERN_DEBUG format , ## args) | 165 | dprint(NDEBUG_TAGS, format , ## args) |
223 | #else | ||
224 | #define TAG_PRINTK(format, args...) | ||
225 | #endif | ||
226 | #if NDEBUG & NDEBUG_MERGING | ||
227 | #define MER_PRINTK(format, args...) \ | 166 | #define MER_PRINTK(format, args...) \ |
228 | printk(KERN_DEBUG format , ## args) | 167 | dprint(NDEBUG_MERGING, format , ## args) |
229 | #else | ||
230 | #define MER_PRINTK(format, args...) | ||
231 | #endif | ||
232 | 168 | ||
233 | /* conditional macros for NCR5380_print_{,phase,status} */ | 169 | /* conditional macros for NCR5380_print_{,phase,status} */ |
234 | 170 | ||
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index dc70c180e115..e34442e405e8 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c | |||
@@ -22,7 +22,6 @@ | |||
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/pci.h> | ||
26 | #include <linux/scatterlist.h> | 25 | #include <linux/scatterlist.h> |
27 | 26 | ||
28 | #include "sas_internal.h" | 27 | #include "sas_internal.h" |
diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c index 89403b00e042..6335830df810 100644 --- a/drivers/scsi/libsrp.c +++ b/drivers/scsi/libsrp.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/kfifo.h> | 22 | #include <linux/kfifo.h> |
23 | #include <linux/scatterlist.h> | 23 | #include <linux/scatterlist.h> |
24 | #include <linux/dma-mapping.h> | 24 | #include <linux/dma-mapping.h> |
25 | #include <linux/pci.h> | ||
26 | #include <scsi/scsi.h> | 25 | #include <scsi/scsi.h> |
27 | #include <scsi/scsi_cmnd.h> | 26 | #include <scsi/scsi_cmnd.h> |
28 | #include <scsi/scsi_tcq.h> | 27 | #include <scsi/scsi_tcq.h> |
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 0aa3304f6b9b..7fc6e06ea7e1 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c | |||
@@ -2088,7 +2088,7 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor) | |||
2088 | static inline int | 2088 | static inline int |
2089 | make_local_pdev(adapter_t *adapter, struct pci_dev **pdev) | 2089 | make_local_pdev(adapter_t *adapter, struct pci_dev **pdev) |
2090 | { | 2090 | { |
2091 | *pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); | 2091 | *pdev = alloc_pci_dev(); |
2092 | 2092 | ||
2093 | if( *pdev == NULL ) return -1; | 2093 | if( *pdev == NULL ) return -1; |
2094 | 2094 | ||
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index a0cc05d21a6a..60d29440f316 100644 --- a/drivers/usb/net/kaweth.c +++ b/drivers/usb/net/kaweth.c | |||
@@ -55,7 +55,6 @@ | |||
55 | #include <linux/usb.h> | 55 | #include <linux/usb.h> |
56 | #include <linux/types.h> | 56 | #include <linux/types.h> |
57 | #include <linux/ethtool.h> | 57 | #include <linux/ethtool.h> |
58 | #include <linux/pci.h> | ||
59 | #include <linux/dma-mapping.h> | 58 | #include <linux/dma-mapping.h> |
60 | #include <linux/wait.h> | 59 | #include <linux/wait.h> |
61 | #include <asm/uaccess.h> | 60 | #include <asm/uaccess.h> |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index b1cb72c3780f..d18b51f989c9 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -389,7 +389,10 @@ config FB_ARC | |||
389 | 389 | ||
390 | config FB_ATARI | 390 | config FB_ATARI |
391 | bool "Atari native chipset support" | 391 | bool "Atari native chipset support" |
392 | depends on (FB = y) && ATARI && BROKEN | 392 | depends on (FB = y) && ATARI |
393 | select FB_CFB_FILLRECT | ||
394 | select FB_CFB_COPYAREA | ||
395 | select FB_CFB_IMAGEBLIT | ||
393 | help | 396 | help |
394 | This is the frame buffer device driver for the builtin graphics | 397 | This is the frame buffer device driver for the builtin graphics |
395 | chipset found in Ataris. | 398 | chipset found in Ataris. |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 760305c8a841..869351785ee8 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -63,7 +63,8 @@ obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o | |||
63 | obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o | 63 | obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o |
64 | obj-$(CONFIG_FB_SGIVW) += sgivwfb.o | 64 | obj-$(CONFIG_FB_SGIVW) += sgivwfb.o |
65 | obj-$(CONFIG_FB_ACORN) += acornfb.o | 65 | obj-$(CONFIG_FB_ACORN) += acornfb.o |
66 | obj-$(CONFIG_FB_ATARI) += atafb.o | 66 | obj-$(CONFIG_FB_ATARI) += atafb.o c2p.o atafb_mfb.o \ |
67 | atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o | ||
67 | obj-$(CONFIG_FB_MAC) += macfb.o | 68 | obj-$(CONFIG_FB_MAC) += macfb.o |
68 | obj-$(CONFIG_FB_HGA) += hgafb.o | 69 | obj-$(CONFIG_FB_HGA) += hgafb.o |
69 | obj-$(CONFIG_FB_IGA) += igafb.o | 70 | obj-$(CONFIG_FB_IGA) += igafb.o |
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index bffe2b946344..0038a0541c7e 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device | 2 | * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device |
3 | * | 3 | * |
4 | * Copyright (C) 1994 Martin Schaller & Roman Hodek | 4 | * Copyright (C) 1994 Martin Schaller & Roman Hodek |
5 | * | 5 | * |
6 | * This file is subject to the terms and conditions of the GNU General Public | 6 | * This file is subject to the terms and conditions of the GNU General Public |
7 | * License. See the file COPYING in the main directory of this archive | 7 | * License. See the file COPYING in the main directory of this archive |
8 | * for more details. | 8 | * for more details. |
@@ -70,14 +70,8 @@ | |||
70 | #include <linux/fb.h> | 70 | #include <linux/fb.h> |
71 | #include <asm/atarikb.h> | 71 | #include <asm/atarikb.h> |
72 | 72 | ||
73 | #include <video/fbcon.h> | 73 | #include "c2p.h" |
74 | #include <video/fbcon-cfb8.h> | 74 | #include "atafb.h" |
75 | #include <video/fbcon-cfb16.h> | ||
76 | #include <video/fbcon-iplan2p2.h> | ||
77 | #include <video/fbcon-iplan2p4.h> | ||
78 | #include <video/fbcon-iplan2p8.h> | ||
79 | #include <video/fbcon-mfb.h> | ||
80 | |||
81 | 75 | ||
82 | #define SWITCH_ACIA 0x01 /* modes for switch on OverScan */ | 76 | #define SWITCH_ACIA 0x01 /* modes for switch on OverScan */ |
83 | #define SWITCH_SND6 0x40 | 77 | #define SWITCH_SND6 0x40 |
@@ -87,22 +81,48 @@ | |||
87 | 81 | ||
88 | #define up(x, r) (((x) + (r) - 1) & ~((r)-1)) | 82 | #define up(x, r) (((x) + (r) - 1) & ~((r)-1)) |
89 | 83 | ||
84 | /* | ||
85 | * Interface to the world | ||
86 | */ | ||
87 | |||
88 | static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info); | ||
89 | static int atafb_set_par(struct fb_info *info); | ||
90 | static int atafb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, | ||
91 | unsigned int blue, unsigned int transp, | ||
92 | struct fb_info *info); | ||
93 | static int atafb_blank(int blank, struct fb_info *info); | ||
94 | static int atafb_pan_display(struct fb_var_screeninfo *var, | ||
95 | struct fb_info *info); | ||
96 | static void atafb_fillrect(struct fb_info *info, | ||
97 | const struct fb_fillrect *rect); | ||
98 | static void atafb_copyarea(struct fb_info *info, | ||
99 | const struct fb_copyarea *region); | ||
100 | static void atafb_imageblit(struct fb_info *info, const struct fb_image *image); | ||
101 | static int atafb_ioctl(struct fb_info *info, unsigned int cmd, | ||
102 | unsigned long arg); | ||
103 | |||
90 | 104 | ||
91 | static int default_par=0; /* default resolution (0=none) */ | 105 | static int default_par; /* default resolution (0=none) */ |
92 | 106 | ||
93 | static unsigned long default_mem_req=0; | 107 | static unsigned long default_mem_req; |
94 | 108 | ||
95 | static int hwscroll=-1; | 109 | static int hwscroll = -1; |
96 | 110 | ||
97 | static int use_hwscroll = 1; | 111 | static int use_hwscroll = 1; |
98 | 112 | ||
99 | static int sttt_xres=640,st_yres=400,tt_yres=480; | 113 | static int sttt_xres = 640, st_yres = 400, tt_yres = 480; |
100 | static int sttt_xres_virtual=640,sttt_yres_virtual=400; | 114 | static int sttt_xres_virtual = 640, sttt_yres_virtual = 400; |
101 | static int ovsc_offset=0, ovsc_addlen=0; | 115 | static int ovsc_offset, ovsc_addlen; |
116 | |||
117 | /* | ||
118 | * Hardware parameters for current mode | ||
119 | */ | ||
102 | 120 | ||
103 | static struct atafb_par { | 121 | static struct atafb_par { |
104 | void *screen_base; | 122 | void *screen_base; |
105 | int yres_virtual; | 123 | int yres_virtual; |
124 | u_long next_line; | ||
125 | u_long next_plane; | ||
106 | #if defined ATAFB_TT || defined ATAFB_STE | 126 | #if defined ATAFB_TT || defined ATAFB_STE |
107 | union { | 127 | union { |
108 | struct { | 128 | struct { |
@@ -138,7 +158,7 @@ static struct atafb_par { | |||
138 | /* Don't calculate an own resolution, and thus don't change the one found when | 158 | /* Don't calculate an own resolution, and thus don't change the one found when |
139 | * booting (currently used for the Falcon to keep settings for internal video | 159 | * booting (currently used for the Falcon to keep settings for internal video |
140 | * hardware extensions (e.g. ScreenBlaster) */ | 160 | * hardware extensions (e.g. ScreenBlaster) */ |
141 | static int DontCalcRes = 0; | 161 | static int DontCalcRes = 0; |
142 | 162 | ||
143 | #ifdef ATAFB_FALCON | 163 | #ifdef ATAFB_FALCON |
144 | #define HHT hw.falcon.hht | 164 | #define HHT hw.falcon.hht |
@@ -163,83 +183,84 @@ static int DontCalcRes = 0; | |||
163 | #define VMO_PREMASK 0x0c | 183 | #define VMO_PREMASK 0x0c |
164 | #endif | 184 | #endif |
165 | 185 | ||
166 | static struct fb_info fb_info; | 186 | static struct fb_info fb_info = { |
187 | .fix = { | ||
188 | .id = "Atari ", | ||
189 | .visual = FB_VISUAL_PSEUDOCOLOR, | ||
190 | .accel = FB_ACCEL_NONE, | ||
191 | } | ||
192 | }; | ||
167 | 193 | ||
168 | static void *screen_base; /* base address of screen */ | 194 | static void *screen_base; /* base address of screen */ |
169 | static void *real_screen_base; /* (only for Overscan) */ | 195 | static void *real_screen_base; /* (only for Overscan) */ |
170 | 196 | ||
171 | static int screen_len; | 197 | static int screen_len; |
172 | 198 | ||
173 | static int current_par_valid=0; | 199 | static int current_par_valid; |
174 | 200 | ||
175 | static int mono_moni=0; | 201 | static int mono_moni; |
176 | |||
177 | static struct display disp; | ||
178 | 202 | ||
179 | 203 | ||
180 | #ifdef ATAFB_EXT | 204 | #ifdef ATAFB_EXT |
181 | /* external video handling */ | ||
182 | 205 | ||
183 | static unsigned external_xres; | 206 | /* external video handling */ |
184 | static unsigned external_xres_virtual; | 207 | static unsigned int external_xres; |
185 | static unsigned external_yres; | 208 | static unsigned int external_xres_virtual; |
186 | /* not needed - atafb will never support panning/hardwarescroll with external | 209 | static unsigned int external_yres; |
187 | * static unsigned external_yres_virtual; | ||
188 | */ | ||
189 | 210 | ||
190 | static unsigned external_depth; | 211 | /* |
191 | static int external_pmode; | 212 | * not needed - atafb will never support panning/hardwarescroll with external |
192 | static void *external_addr = 0; | 213 | * static unsigned int external_yres_virtual; |
193 | static unsigned long external_len; | 214 | */ |
194 | static unsigned long external_vgaiobase = 0; | 215 | static unsigned int external_depth; |
195 | static unsigned int external_bitspercol = 6; | 216 | static int external_pmode; |
196 | 217 | static void *external_addr; | |
197 | /* | 218 | static unsigned long external_len; |
198 | JOE <joe@amber.dinoco.de>: | 219 | static unsigned long external_vgaiobase; |
199 | added card type for external driver, is only needed for | 220 | static unsigned int external_bitspercol = 6; |
200 | colormap handling. | ||
201 | */ | ||
202 | 221 | ||
222 | /* | ||
223 | * JOE <joe@amber.dinoco.de>: | ||
224 | * added card type for external driver, is only needed for | ||
225 | * colormap handling. | ||
226 | */ | ||
203 | enum cardtype { IS_VGA, IS_MV300 }; | 227 | enum cardtype { IS_VGA, IS_MV300 }; |
204 | static enum cardtype external_card_type = IS_VGA; | 228 | static enum cardtype external_card_type = IS_VGA; |
205 | 229 | ||
206 | /* | 230 | /* |
207 | The MV300 mixes the color registers. So we need an array of munged | 231 | * The MV300 mixes the color registers. So we need an array of munged |
208 | indices in order to access the correct reg. | 232 | * indices in order to access the correct reg. |
209 | */ | 233 | */ |
210 | static int MV300_reg_1bit[2]={0,1}; | 234 | static int MV300_reg_1bit[2] = { |
211 | static int MV300_reg_4bit[16]={ | 235 | 0, 1 |
212 | 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; | 236 | }; |
213 | static int MV300_reg_8bit[256]={ | 237 | static int MV300_reg_4bit[16] = { |
214 | 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, | 238 | 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 |
215 | 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, | 239 | }; |
216 | 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, | 240 | static int MV300_reg_8bit[256] = { |
217 | 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, | 241 | 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, |
218 | 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, | 242 | 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, |
219 | 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, | 243 | 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, |
220 | 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, | 244 | 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, |
221 | 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, | 245 | 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, |
222 | 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, | 246 | 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, |
223 | 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, | 247 | 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, |
224 | 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, | 248 | 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, |
225 | 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, | 249 | 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, |
226 | 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, | 250 | 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, |
227 | 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, | 251 | 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, |
228 | 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, | 252 | 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, |
229 | 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 }; | 253 | 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, |
254 | 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, | ||
255 | 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, | ||
256 | 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 | ||
257 | }; | ||
230 | 258 | ||
231 | static int *MV300_reg = MV300_reg_8bit; | 259 | static int *MV300_reg = MV300_reg_8bit; |
232 | |||
233 | /* | ||
234 | And on the MV300 it's difficult to read out the hardware palette. So we | ||
235 | just keep track of the set colors in our own array here, and use that! | ||
236 | */ | ||
237 | |||
238 | static struct { unsigned char red,green,blue,pad; } ext_color[256]; | ||
239 | #endif /* ATAFB_EXT */ | 260 | #endif /* ATAFB_EXT */ |
240 | 261 | ||
241 | 262 | ||
242 | static int inverse=0; | 263 | static int inverse; |
243 | 264 | ||
244 | extern int fontheight_8x8; | 265 | extern int fontheight_8x8; |
245 | extern int fontwidth_8x8; | 266 | extern int fontwidth_8x8; |
@@ -249,96 +270,154 @@ extern int fontheight_8x16; | |||
249 | extern int fontwidth_8x16; | 270 | extern int fontwidth_8x16; |
250 | extern unsigned char fontdata_8x16[]; | 271 | extern unsigned char fontdata_8x16[]; |
251 | 272 | ||
273 | /* | ||
274 | * struct fb_ops { | ||
275 | * * open/release and usage marking | ||
276 | * struct module *owner; | ||
277 | * int (*fb_open)(struct fb_info *info, int user); | ||
278 | * int (*fb_release)(struct fb_info *info, int user); | ||
279 | * | ||
280 | * * For framebuffers with strange non linear layouts or that do not | ||
281 | * * work with normal memory mapped access | ||
282 | * ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos); | ||
283 | * ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos); | ||
284 | * | ||
285 | * * checks var and eventually tweaks it to something supported, | ||
286 | * * DOES NOT MODIFY PAR * | ||
287 | * int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info); | ||
288 | * | ||
289 | * * set the video mode according to info->var * | ||
290 | * int (*fb_set_par)(struct fb_info *info); | ||
291 | * | ||
292 | * * set color register * | ||
293 | * int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green, | ||
294 | * unsigned int blue, unsigned int transp, struct fb_info *info); | ||
295 | * | ||
296 | * * set color registers in batch * | ||
297 | * int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info); | ||
298 | * | ||
299 | * * blank display * | ||
300 | * int (*fb_blank)(int blank, struct fb_info *info); | ||
301 | * | ||
302 | * * pan display * | ||
303 | * int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info); | ||
304 | * | ||
305 | * *** The meat of the drawing engine *** | ||
306 | * * Draws a rectangle * | ||
307 | * void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect); | ||
308 | * * Copy data from area to another * | ||
309 | * void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region); | ||
310 | * * Draws a image to the display * | ||
311 | * void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image); | ||
312 | * | ||
313 | * * Draws cursor * | ||
314 | * int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor); | ||
315 | * | ||
316 | * * Rotates the display * | ||
317 | * void (*fb_rotate)(struct fb_info *info, int angle); | ||
318 | * | ||
319 | * * wait for blit idle, optional * | ||
320 | * int (*fb_sync)(struct fb_info *info); | ||
321 | * | ||
322 | * * perform fb specific ioctl (optional) * | ||
323 | * int (*fb_ioctl)(struct fb_info *info, unsigned int cmd, | ||
324 | * unsigned long arg); | ||
325 | * | ||
326 | * * Handle 32bit compat ioctl (optional) * | ||
327 | * int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd, | ||
328 | * unsigned long arg); | ||
329 | * | ||
330 | * * perform fb specific mmap * | ||
331 | * int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma); | ||
332 | * | ||
333 | * * save current hardware state * | ||
334 | * void (*fb_save_state)(struct fb_info *info); | ||
335 | * | ||
336 | * * restore saved state * | ||
337 | * void (*fb_restore_state)(struct fb_info *info); | ||
338 | * } ; | ||
339 | */ | ||
340 | |||
341 | |||
252 | /* ++roman: This structure abstracts from the underlying hardware (ST(e), | 342 | /* ++roman: This structure abstracts from the underlying hardware (ST(e), |
253 | * TT, or Falcon. | 343 | * TT, or Falcon. |
254 | * | 344 | * |
255 | * int (*detect)( void ) | 345 | * int (*detect)(void) |
256 | * This function should detect the current video mode settings and | 346 | * This function should detect the current video mode settings and |
257 | * store them in atafb_predefined[0] for later reference by the | 347 | * store them in atafb_predefined[0] for later reference by the |
258 | * user. Return the index+1 of an equivalent predefined mode or 0 | 348 | * user. Return the index+1 of an equivalent predefined mode or 0 |
259 | * if there is no such. | 349 | * if there is no such. |
260 | * | 350 | * |
261 | * int (*encode_fix)( struct fb_fix_screeninfo *fix, | 351 | * int (*encode_fix)(struct fb_fix_screeninfo *fix, |
262 | * struct atafb_par *par ) | 352 | * struct atafb_par *par) |
263 | * This function should fill in the 'fix' structure based on the | 353 | * This function should fill in the 'fix' structure based on the |
264 | * values in the 'par' structure. | 354 | * values in the 'par' structure. |
265 | * | 355 | * !!! Obsolete, perhaps !!! |
266 | * int (*decode_var)( struct fb_var_screeninfo *var, | 356 | * |
267 | * struct atafb_par *par ) | 357 | * int (*decode_var)(struct fb_var_screeninfo *var, |
358 | * struct atafb_par *par) | ||
268 | * Get the video params out of 'var'. If a value doesn't fit, round | 359 | * Get the video params out of 'var'. If a value doesn't fit, round |
269 | * it up, if it's too big, return EINVAL. | 360 | * it up, if it's too big, return EINVAL. |
270 | * Round up in the following order: bits_per_pixel, xres, yres, | 361 | * Round up in the following order: bits_per_pixel, xres, yres, |
271 | * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, | 362 | * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, |
272 | * horizontal timing, vertical timing. | 363 | * horizontal timing, vertical timing. |
273 | * | 364 | * |
274 | * int (*encode_var)( struct fb_var_screeninfo *var, | 365 | * int (*encode_var)(struct fb_var_screeninfo *var, |
275 | * struct atafb_par *par ); | 366 | * struct atafb_par *par); |
276 | * Fill the 'var' structure based on the values in 'par' and maybe | 367 | * Fill the 'var' structure based on the values in 'par' and maybe |
277 | * other values read out of the hardware. | 368 | * other values read out of the hardware. |
278 | * | 369 | * |
279 | * void (*get_par)( struct atafb_par *par ) | 370 | * void (*get_par)(struct atafb_par *par) |
280 | * Fill the hardware's 'par' structure. | 371 | * Fill the hardware's 'par' structure. |
281 | * | 372 | * !!! Used only by detect() !!! |
282 | * void (*set_par)( struct atafb_par *par ) | 373 | * |
374 | * void (*set_par)(struct atafb_par *par) | ||
283 | * Set the hardware according to 'par'. | 375 | * Set the hardware according to 'par'. |
284 | * | ||
285 | * int (*getcolreg)( unsigned regno, unsigned *red, | ||
286 | * unsigned *green, unsigned *blue, | ||
287 | * unsigned *transp, struct fb_info *info ) | ||
288 | * Read a single color register and split it into | ||
289 | * colors/transparent. Return != 0 for invalid regno. | ||
290 | * | 376 | * |
291 | * void (*set_screen_base)(void *s_base) | 377 | * void (*set_screen_base)(void *s_base) |
292 | * Set the base address of the displayed frame buffer. Only called | 378 | * Set the base address of the displayed frame buffer. Only called |
293 | * if yres_virtual > yres or xres_virtual > xres. | 379 | * if yres_virtual > yres or xres_virtual > xres. |
294 | * | 380 | * |
295 | * int (*blank)( int blank_mode ) | 381 | * int (*blank)(int blank_mode) |
296 | * Blank the screen if blank_mode!=0, else unblank. If blank==NULL then | 382 | * Blank the screen if blank_mode != 0, else unblank. If blank == NULL then |
297 | * the caller blanks by setting the CLUT to all black. Return 0 if blanking | 383 | * the caller blanks by setting the CLUT to all black. Return 0 if blanking |
298 | * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which | 384 | * succeeded, !=0 if un-/blanking failed due to e.g. a video mode which |
299 | * doesn't support it. Implements VESA suspend and powerdown modes on | 385 | * doesn't support it. Implements VESA suspend and powerdown modes on |
300 | * hardware that supports disabling hsync/vsync: | 386 | * hardware that supports disabling hsync/vsync: |
301 | * blank_mode==2: suspend vsync, 3:suspend hsync, 4: powerdown. | 387 | * blank_mode == 2: suspend vsync, 3:suspend hsync, 4: powerdown. |
302 | */ | 388 | */ |
303 | 389 | ||
304 | static struct fb_hwswitch { | 390 | static struct fb_hwswitch { |
305 | int (*detect)( void ); | 391 | int (*detect)(void); |
306 | int (*encode_fix)( struct fb_fix_screeninfo *fix, | 392 | int (*encode_fix)(struct fb_fix_screeninfo *fix, |
307 | struct atafb_par *par ); | 393 | struct atafb_par *par); |
308 | int (*decode_var)( struct fb_var_screeninfo *var, | 394 | int (*decode_var)(struct fb_var_screeninfo *var, |
309 | struct atafb_par *par ); | 395 | struct atafb_par *par); |
310 | int (*encode_var)( struct fb_var_screeninfo *var, | 396 | int (*encode_var)(struct fb_var_screeninfo *var, |
311 | struct atafb_par *par ); | 397 | struct atafb_par *par); |
312 | void (*get_par)( struct atafb_par *par ); | 398 | void (*get_par)(struct atafb_par *par); |
313 | void (*set_par)( struct atafb_par *par ); | 399 | void (*set_par)(struct atafb_par *par); |
314 | int (*getcolreg)( unsigned regno, unsigned *red, | ||
315 | unsigned *green, unsigned *blue, | ||
316 | unsigned *transp, struct fb_info *info ); | ||
317 | void (*set_screen_base)(void *s_base); | 400 | void (*set_screen_base)(void *s_base); |
318 | int (*blank)( int blank_mode ); | 401 | int (*blank)(int blank_mode); |
319 | int (*pan_display)( struct fb_var_screeninfo *var, | 402 | int (*pan_display)(struct fb_var_screeninfo *var, |
320 | struct atafb_par *par); | 403 | struct fb_info *info); |
321 | } *fbhw; | 404 | } *fbhw; |
322 | 405 | ||
323 | static char *autodetect_names[] = {"autodetect", NULL}; | 406 | static char *autodetect_names[] = { "autodetect", NULL }; |
324 | static char *stlow_names[] = {"stlow", NULL}; | 407 | static char *stlow_names[] = { "stlow", NULL }; |
325 | static char *stmid_names[] = {"stmid", "default5", NULL}; | 408 | static char *stmid_names[] = { "stmid", "default5", NULL }; |
326 | static char *sthigh_names[] = {"sthigh", "default4", NULL}; | 409 | static char *sthigh_names[] = { "sthigh", "default4", NULL }; |
327 | static char *ttlow_names[] = {"ttlow", NULL}; | 410 | static char *ttlow_names[] = { "ttlow", NULL }; |
328 | static char *ttmid_names[]= {"ttmid", "default1", NULL}; | 411 | static char *ttmid_names[] = { "ttmid", "default1", NULL }; |
329 | static char *tthigh_names[]= {"tthigh", "default2", NULL}; | 412 | static char *tthigh_names[] = { "tthigh", "default2", NULL }; |
330 | static char *vga2_names[] = {"vga2", NULL}; | 413 | static char *vga2_names[] = { "vga2", NULL }; |
331 | static char *vga4_names[] = {"vga4", NULL}; | 414 | static char *vga4_names[] = { "vga4", NULL }; |
332 | static char *vga16_names[] = {"vga16", "default3", NULL}; | 415 | static char *vga16_names[] = { "vga16", "default3", NULL }; |
333 | static char *vga256_names[] = {"vga256", NULL}; | 416 | static char *vga256_names[] = { "vga256", NULL }; |
334 | static char *falh2_names[] = {"falh2", NULL}; | 417 | static char *falh2_names[] = { "falh2", NULL }; |
335 | static char *falh16_names[] = {"falh16", NULL}; | 418 | static char *falh16_names[] = { "falh16", NULL }; |
336 | 419 | ||
337 | static char **fb_var_names[] = { | 420 | static char **fb_var_names[] = { |
338 | /* Writing the name arrays directly in this array (via "(char *[]){...}") | ||
339 | * crashes gcc 2.5.8 (sigsegv) if the inner array | ||
340 | * contains more than two items. I've also seen that all elements | ||
341 | * were identical to the last (my cross-gcc) :-(*/ | ||
342 | autodetect_names, | 421 | autodetect_names, |
343 | stlow_names, | 422 | stlow_names, |
344 | stmid_names, | 423 | stmid_names, |
@@ -353,18 +432,17 @@ static char **fb_var_names[] = { | |||
353 | falh2_names, | 432 | falh2_names, |
354 | falh16_names, | 433 | falh16_names, |
355 | NULL | 434 | NULL |
356 | /* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */ | ||
357 | }; | 435 | }; |
358 | 436 | ||
359 | static struct fb_var_screeninfo atafb_predefined[] = { | 437 | static struct fb_var_screeninfo atafb_predefined[] = { |
360 | /* | 438 | /* |
361 | * yres_virtual==0 means use hw-scrolling if possible, else yres | 439 | * yres_virtual == 0 means use hw-scrolling if possible, else yres |
362 | */ | 440 | */ |
363 | { /* autodetect */ | 441 | { /* autodetect */ |
364 | 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */ | 442 | 0, 0, 0, 0, 0, 0, 0, 0, /* xres-grayscale */ |
365 | {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/ | 443 | {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, /* red green blue tran*/ |
366 | 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, | 444 | 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, |
367 | { /* st low */ | 445 | { /* st low */ |
368 | 320, 200, 320, 0, 0, 0, 4, 0, | 446 | 320, 200, 320, 0, 0, 0, 4, 0, |
369 | {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0}, | 447 | {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0}, |
370 | 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, | 448 | 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, |
@@ -414,27 +492,100 @@ static struct fb_var_screeninfo atafb_predefined[] = { | |||
414 | 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, | 492 | 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, |
415 | }; | 493 | }; |
416 | 494 | ||
417 | static int num_atafb_predefined=ARRAY_SIZE(atafb_predefined); | 495 | static int num_atafb_predefined = ARRAY_SIZE(atafb_predefined); |
418 | 496 | ||
497 | static struct fb_videomode atafb_modedb[] __initdata = { | ||
498 | /* | ||
499 | * Atari Video Modes | ||
500 | * | ||
501 | * If you change these, make sure to update DEFMODE_* as well! | ||
502 | */ | ||
419 | 503 | ||
420 | static int | 504 | /* |
421 | get_video_mode(char *vname) | 505 | * ST/TT Video Modes |
506 | */ | ||
507 | |||
508 | { | ||
509 | /* 320x200, 15 kHz, 60 Hz (ST low) */ | ||
510 | "st-low", 60, 320, 200, 32000, 32, 16, 31, 14, 96, 4, | ||
511 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
512 | }, { | ||
513 | /* 640x200, 15 kHz, 60 Hz (ST medium) */ | ||
514 | "st-mid", 60, 640, 200, 32000, 32, 16, 31, 14, 96, 4, | ||
515 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
516 | }, { | ||
517 | /* 640x400, 30.25 kHz, 63.5 Hz (ST high) */ | ||
518 | "st-high", 63, 640, 400, 32000, 128, 0, 40, 14, 128, 4, | ||
519 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
520 | }, { | ||
521 | /* 320x480, 15 kHz, 60 Hz (TT low) */ | ||
522 | "tt-low", 60, 320, 480, 31041, 120, 100, 8, 16, 140, 30, | ||
523 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
524 | }, { | ||
525 | /* 640x480, 29 kHz, 57 Hz (TT medium) */ | ||
526 | "tt-mid", 60, 640, 480, 31041, 120, 100, 8, 16, 140, 30, | ||
527 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
528 | }, { | ||
529 | /* 1280x960, 29 kHz, 60 Hz (TT high) */ | ||
530 | "tt-high", 57, 640, 960, 31041, 120, 100, 8, 16, 140, 30, | ||
531 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
532 | }, | ||
533 | |||
534 | /* | ||
535 | * VGA Video Modes | ||
536 | */ | ||
537 | |||
538 | { | ||
539 | /* 640x480, 31 kHz, 60 Hz (VGA) */ | ||
540 | "vga", 63.5, 640, 480, 32000, 18, 42, 31, 11, 96, 3, | ||
541 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
542 | }, { | ||
543 | /* 640x400, 31 kHz, 70 Hz (VGA) */ | ||
544 | "vga70", 70, 640, 400, 32000, 18, 42, 31, 11, 96, 3, | ||
545 | FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
546 | }, | ||
547 | |||
548 | /* | ||
549 | * Falcon HiRes Video Modes | ||
550 | */ | ||
551 | |||
552 | { | ||
553 | /* 896x608, 31 kHz, 60 Hz (Falcon High) */ | ||
554 | "falh", 60, 896, 608, 32000, 18, 42, 31, 1, 96,3, | ||
555 | 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP | ||
556 | }, | ||
557 | }; | ||
558 | |||
559 | #define NUM_TOTAL_MODES ARRAY_SIZE(atafb_modedb) | ||
560 | |||
561 | static char *mode_option __initdata = NULL; | ||
562 | |||
563 | /* default modes */ | ||
564 | |||
565 | #define DEFMODE_TT 5 /* "tt-high" for TT */ | ||
566 | #define DEFMODE_F30 7 /* "vga70" for Falcon */ | ||
567 | #define DEFMODE_STE 2 /* "st-high" for ST/E */ | ||
568 | #define DEFMODE_EXT 6 /* "vga" for external */ | ||
569 | |||
570 | |||
571 | static int get_video_mode(char *vname) | ||
422 | { | 572 | { |
423 | char ***name_list; | 573 | char ***name_list; |
424 | char **name; | 574 | char **name; |
425 | int i; | 575 | int i; |
426 | name_list=fb_var_names; | 576 | |
427 | for (i = 0 ; i < num_atafb_predefined ; i++) { | 577 | name_list = fb_var_names; |
428 | name=*(name_list++); | 578 | for (i = 0; i < num_atafb_predefined; i++) { |
429 | if (! name || ! *name) | 579 | name = *name_list++; |
430 | break; | 580 | if (!name || !*name) |
431 | while (*name) { | 581 | break; |
432 | if (! strcmp(vname, *name)) | 582 | while (*name) { |
433 | return i+1; | 583 | if (!strcmp(vname, *name)) |
434 | name++; | 584 | return i + 1; |
585 | name++; | ||
586 | } | ||
435 | } | 587 | } |
436 | } | 588 | return 0; |
437 | return 0; | ||
438 | } | 589 | } |
439 | 590 | ||
440 | 591 | ||
@@ -443,93 +594,84 @@ get_video_mode(char *vname) | |||
443 | 594 | ||
444 | #ifdef ATAFB_TT | 595 | #ifdef ATAFB_TT |
445 | 596 | ||
446 | static int tt_encode_fix( struct fb_fix_screeninfo *fix, | 597 | static int tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par) |
447 | struct atafb_par *par ) | ||
448 | |||
449 | { | 598 | { |
450 | int mode; | 599 | int mode; |
451 | 600 | ||
452 | strcpy(fix->id,"Atari Builtin"); | 601 | strcpy(fix->id, "Atari Builtin"); |
453 | fix->smem_start = (unsigned long)real_screen_base; | 602 | fix->smem_start = (unsigned long)real_screen_base; |
454 | fix->smem_len = screen_len; | 603 | fix->smem_len = screen_len; |
455 | fix->type=FB_TYPE_INTERLEAVED_PLANES; | 604 | fix->type = FB_TYPE_INTERLEAVED_PLANES; |
456 | fix->type_aux=2; | 605 | fix->type_aux = 2; |
457 | fix->visual=FB_VISUAL_PSEUDOCOLOR; | 606 | fix->visual = FB_VISUAL_PSEUDOCOLOR; |
458 | mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK; | 607 | mode = par->hw.tt.mode & TT_SHIFTER_MODEMASK; |
459 | if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) { | 608 | if (mode == TT_SHIFTER_TTHIGH || mode == TT_SHIFTER_STHIGH) { |
460 | fix->type=FB_TYPE_PACKED_PIXELS; | 609 | fix->type = FB_TYPE_PACKED_PIXELS; |
461 | fix->type_aux=0; | 610 | fix->type_aux = 0; |
462 | if (mode == TT_SHIFTER_TTHIGH) | 611 | if (mode == TT_SHIFTER_TTHIGH) |
463 | fix->visual=FB_VISUAL_MONO01; | 612 | fix->visual = FB_VISUAL_MONO01; |
464 | } | 613 | } |
465 | fix->xpanstep=0; | 614 | fix->xpanstep = 0; |
466 | fix->ypanstep=1; | 615 | fix->ypanstep = 1; |
467 | fix->ywrapstep=0; | 616 | fix->ywrapstep = 0; |
468 | fix->line_length = 0; | 617 | fix->line_length = 0; |
469 | fix->accel = FB_ACCEL_ATARIBLITT; | 618 | fix->accel = FB_ACCEL_ATARIBLITT; |
470 | return 0; | 619 | return 0; |
471 | } | 620 | } |
472 | 621 | ||
473 | 622 | static int tt_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par) | |
474 | static int tt_decode_var( struct fb_var_screeninfo *var, | ||
475 | struct atafb_par *par ) | ||
476 | { | 623 | { |
477 | int xres=var->xres; | 624 | int xres = var->xres; |
478 | int yres=var->yres; | 625 | int yres = var->yres; |
479 | int bpp=var->bits_per_pixel; | 626 | int bpp = var->bits_per_pixel; |
480 | int linelen; | 627 | int linelen; |
481 | int yres_virtual = var->yres_virtual; | 628 | int yres_virtual = var->yres_virtual; |
482 | 629 | ||
483 | if (mono_moni) { | 630 | if (mono_moni) { |
484 | if (bpp > 1 || xres > sttt_xres*2 || yres >tt_yres*2) | 631 | if (bpp > 1 || xres > sttt_xres * 2 || yres > tt_yres * 2) |
485 | return -EINVAL; | 632 | return -EINVAL; |
486 | par->hw.tt.mode=TT_SHIFTER_TTHIGH; | 633 | par->hw.tt.mode = TT_SHIFTER_TTHIGH; |
487 | xres=sttt_xres*2; | 634 | xres = sttt_xres * 2; |
488 | yres=tt_yres*2; | 635 | yres = tt_yres * 2; |
489 | bpp=1; | 636 | bpp = 1; |
490 | } else { | 637 | } else { |
491 | if (bpp > 8 || xres > sttt_xres || yres > tt_yres) | 638 | if (bpp > 8 || xres > sttt_xres || yres > tt_yres) |
492 | return -EINVAL; | 639 | return -EINVAL; |
493 | if (bpp > 4) { | 640 | if (bpp > 4) { |
494 | if (xres > sttt_xres/2 || yres > tt_yres) | 641 | if (xres > sttt_xres / 2 || yres > tt_yres) |
495 | return -EINVAL; | 642 | return -EINVAL; |
496 | par->hw.tt.mode=TT_SHIFTER_TTLOW; | 643 | par->hw.tt.mode = TT_SHIFTER_TTLOW; |
497 | xres=sttt_xres/2; | 644 | xres = sttt_xres / 2; |
498 | yres=tt_yres; | 645 | yres = tt_yres; |
499 | bpp=8; | 646 | bpp = 8; |
500 | } | 647 | } else if (bpp > 2) { |
501 | else if (bpp > 2) { | ||
502 | if (xres > sttt_xres || yres > tt_yres) | 648 | if (xres > sttt_xres || yres > tt_yres) |
503 | return -EINVAL; | 649 | return -EINVAL; |
504 | if (xres > sttt_xres/2 || yres > st_yres/2) { | 650 | if (xres > sttt_xres / 2 || yres > st_yres / 2) { |
505 | par->hw.tt.mode=TT_SHIFTER_TTMID; | 651 | par->hw.tt.mode = TT_SHIFTER_TTMID; |
506 | xres=sttt_xres; | 652 | xres = sttt_xres; |
507 | yres=tt_yres; | 653 | yres = tt_yres; |
508 | bpp=4; | 654 | bpp = 4; |
509 | } | 655 | } else { |
510 | else { | 656 | par->hw.tt.mode = TT_SHIFTER_STLOW; |
511 | par->hw.tt.mode=TT_SHIFTER_STLOW; | 657 | xres = sttt_xres / 2; |
512 | xres=sttt_xres/2; | 658 | yres = st_yres / 2; |
513 | yres=st_yres/2; | 659 | bpp = 4; |
514 | bpp=4; | ||
515 | } | 660 | } |
516 | } | 661 | } else if (bpp > 1) { |
517 | else if (bpp > 1) { | 662 | if (xres > sttt_xres || yres > st_yres / 2) |
518 | if (xres > sttt_xres || yres > st_yres/2) | ||
519 | return -EINVAL; | 663 | return -EINVAL; |
520 | par->hw.tt.mode=TT_SHIFTER_STMID; | 664 | par->hw.tt.mode = TT_SHIFTER_STMID; |
521 | xres=sttt_xres; | 665 | xres = sttt_xres; |
522 | yres=st_yres/2; | 666 | yres = st_yres / 2; |
523 | bpp=2; | 667 | bpp = 2; |
524 | } | 668 | } else if (var->xres > sttt_xres || var->yres > st_yres) { |
525 | else if (var->xres > sttt_xres || var->yres > st_yres) { | ||
526 | return -EINVAL; | 669 | return -EINVAL; |
527 | } | 670 | } else { |
528 | else { | 671 | par->hw.tt.mode = TT_SHIFTER_STHIGH; |
529 | par->hw.tt.mode=TT_SHIFTER_STHIGH; | 672 | xres = sttt_xres; |
530 | xres=sttt_xres; | 673 | yres = st_yres; |
531 | yres=st_yres; | 674 | bpp = 1; |
532 | bpp=1; | ||
533 | } | 675 | } |
534 | } | 676 | } |
535 | if (yres_virtual <= 0) | 677 | if (yres_virtual <= 0) |
@@ -537,10 +679,10 @@ static int tt_decode_var( struct fb_var_screeninfo *var, | |||
537 | else if (yres_virtual < yres) | 679 | else if (yres_virtual < yres) |
538 | yres_virtual = yres; | 680 | yres_virtual = yres; |
539 | if (var->sync & FB_SYNC_EXT) | 681 | if (var->sync & FB_SYNC_EXT) |
540 | par->hw.tt.sync=0; | 682 | par->hw.tt.sync = 0; |
541 | else | 683 | else |
542 | par->hw.tt.sync=1; | 684 | par->hw.tt.sync = 1; |
543 | linelen=xres*bpp/8; | 685 | linelen = xres * bpp / 8; |
544 | if (yres_virtual * linelen > screen_len && screen_len) | 686 | if (yres_virtual * linelen > screen_len && screen_len) |
545 | return -EINVAL; | 687 | return -EINVAL; |
546 | if (yres * linelen > screen_len && screen_len) | 688 | if (yres * linelen > screen_len && screen_len) |
@@ -552,154 +694,123 @@ static int tt_decode_var( struct fb_var_screeninfo *var, | |||
552 | return 0; | 694 | return 0; |
553 | } | 695 | } |
554 | 696 | ||
555 | static int tt_encode_var( struct fb_var_screeninfo *var, | 697 | static int tt_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par) |
556 | struct atafb_par *par ) | ||
557 | { | 698 | { |
558 | int linelen; | 699 | int linelen; |
559 | memset(var, 0, sizeof(struct fb_var_screeninfo)); | 700 | memset(var, 0, sizeof(struct fb_var_screeninfo)); |
560 | var->red.offset=0; | 701 | var->red.offset = 0; |
561 | var->red.length=4; | 702 | var->red.length = 4; |
562 | var->red.msb_right=0; | 703 | var->red.msb_right = 0; |
563 | var->grayscale=0; | 704 | var->grayscale = 0; |
564 | 705 | ||
565 | var->pixclock=31041; | 706 | var->pixclock = 31041; |
566 | var->left_margin=120; /* these may be incorrect */ | 707 | var->left_margin = 120; /* these may be incorrect */ |
567 | var->right_margin=100; | 708 | var->right_margin = 100; |
568 | var->upper_margin=8; | 709 | var->upper_margin = 8; |
569 | var->lower_margin=16; | 710 | var->lower_margin = 16; |
570 | var->hsync_len=140; | 711 | var->hsync_len = 140; |
571 | var->vsync_len=30; | 712 | var->vsync_len = 30; |
572 | 713 | ||
573 | var->height=-1; | 714 | var->height = -1; |
574 | var->width=-1; | 715 | var->width = -1; |
575 | 716 | ||
576 | if (par->hw.tt.sync & 1) | 717 | if (par->hw.tt.sync & 1) |
577 | var->sync=0; | 718 | var->sync = 0; |
578 | else | 719 | else |
579 | var->sync=FB_SYNC_EXT; | 720 | var->sync = FB_SYNC_EXT; |
580 | 721 | ||
581 | switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) { | 722 | switch (par->hw.tt.mode & TT_SHIFTER_MODEMASK) { |
582 | case TT_SHIFTER_STLOW: | 723 | case TT_SHIFTER_STLOW: |
583 | var->xres=sttt_xres/2; | 724 | var->xres = sttt_xres / 2; |
584 | var->xres_virtual=sttt_xres_virtual/2; | 725 | var->xres_virtual = sttt_xres_virtual / 2; |
585 | var->yres=st_yres/2; | 726 | var->yres = st_yres / 2; |
586 | var->bits_per_pixel=4; | 727 | var->bits_per_pixel = 4; |
587 | break; | 728 | break; |
588 | case TT_SHIFTER_STMID: | 729 | case TT_SHIFTER_STMID: |
589 | var->xres=sttt_xres; | 730 | var->xres = sttt_xres; |
590 | var->xres_virtual=sttt_xres_virtual; | 731 | var->xres_virtual = sttt_xres_virtual; |
591 | var->yres=st_yres/2; | 732 | var->yres = st_yres / 2; |
592 | var->bits_per_pixel=2; | 733 | var->bits_per_pixel = 2; |
593 | break; | 734 | break; |
594 | case TT_SHIFTER_STHIGH: | 735 | case TT_SHIFTER_STHIGH: |
595 | var->xres=sttt_xres; | 736 | var->xres = sttt_xres; |
596 | var->xres_virtual=sttt_xres_virtual; | 737 | var->xres_virtual = sttt_xres_virtual; |
597 | var->yres=st_yres; | 738 | var->yres = st_yres; |
598 | var->bits_per_pixel=1; | 739 | var->bits_per_pixel = 1; |
599 | break; | 740 | break; |
600 | case TT_SHIFTER_TTLOW: | 741 | case TT_SHIFTER_TTLOW: |
601 | var->xres=sttt_xres/2; | 742 | var->xres = sttt_xres / 2; |
602 | var->xres_virtual=sttt_xres_virtual/2; | 743 | var->xres_virtual = sttt_xres_virtual / 2; |
603 | var->yres=tt_yres; | 744 | var->yres = tt_yres; |
604 | var->bits_per_pixel=8; | 745 | var->bits_per_pixel = 8; |
605 | break; | 746 | break; |
606 | case TT_SHIFTER_TTMID: | 747 | case TT_SHIFTER_TTMID: |
607 | var->xres=sttt_xres; | 748 | var->xres = sttt_xres; |
608 | var->xres_virtual=sttt_xres_virtual; | 749 | var->xres_virtual = sttt_xres_virtual; |
609 | var->yres=tt_yres; | 750 | var->yres = tt_yres; |
610 | var->bits_per_pixel=4; | 751 | var->bits_per_pixel = 4; |
611 | break; | 752 | break; |
612 | case TT_SHIFTER_TTHIGH: | 753 | case TT_SHIFTER_TTHIGH: |
613 | var->red.length=0; | 754 | var->red.length = 0; |
614 | var->xres=sttt_xres*2; | 755 | var->xres = sttt_xres * 2; |
615 | var->xres_virtual=sttt_xres_virtual*2; | 756 | var->xres_virtual = sttt_xres_virtual * 2; |
616 | var->yres=tt_yres*2; | 757 | var->yres = tt_yres * 2; |
617 | var->bits_per_pixel=1; | 758 | var->bits_per_pixel = 1; |
618 | break; | 759 | break; |
619 | } | 760 | } |
620 | var->blue=var->green=var->red; | 761 | var->blue = var->green = var->red; |
621 | var->transp.offset=0; | 762 | var->transp.offset = 0; |
622 | var->transp.length=0; | 763 | var->transp.length = 0; |
623 | var->transp.msb_right=0; | 764 | var->transp.msb_right = 0; |
624 | linelen=var->xres_virtual * var->bits_per_pixel / 8; | 765 | linelen = var->xres_virtual * var->bits_per_pixel / 8; |
625 | if (! use_hwscroll) | 766 | if (!use_hwscroll) |
626 | var->yres_virtual=var->yres; | 767 | var->yres_virtual = var->yres; |
627 | else if (screen_len) { | 768 | else if (screen_len) { |
628 | if (par->yres_virtual) | 769 | if (par->yres_virtual) |
629 | var->yres_virtual = par->yres_virtual; | 770 | var->yres_virtual = par->yres_virtual; |
630 | else | 771 | else |
631 | /* yres_virtual==0 means use maximum */ | 772 | /* yres_virtual == 0 means use maximum */ |
632 | var->yres_virtual = screen_len / linelen; | 773 | var->yres_virtual = screen_len / linelen; |
633 | } else { | 774 | } else { |
634 | if (hwscroll < 0) | 775 | if (hwscroll < 0) |
635 | var->yres_virtual = 2 * var->yres; | 776 | var->yres_virtual = 2 * var->yres; |
636 | else | 777 | else |
637 | var->yres_virtual=var->yres+hwscroll * 16; | 778 | var->yres_virtual = var->yres + hwscroll * 16; |
638 | } | 779 | } |
639 | var->xoffset=0; | 780 | var->xoffset = 0; |
640 | if (screen_base) | 781 | if (screen_base) |
641 | var->yoffset=(par->screen_base - screen_base)/linelen; | 782 | var->yoffset = (par->screen_base - screen_base) / linelen; |
642 | else | 783 | else |
643 | var->yoffset=0; | 784 | var->yoffset = 0; |
644 | var->nonstd=0; | 785 | var->nonstd = 0; |
645 | var->activate=0; | 786 | var->activate = 0; |
646 | var->vmode=FB_VMODE_NONINTERLACED; | 787 | var->vmode = FB_VMODE_NONINTERLACED; |
647 | return 0; | 788 | return 0; |
648 | } | 789 | } |
649 | 790 | ||
650 | 791 | static void tt_get_par(struct atafb_par *par) | |
651 | static void tt_get_par( struct atafb_par *par ) | ||
652 | { | 792 | { |
653 | unsigned long addr; | 793 | unsigned long addr; |
654 | par->hw.tt.mode=shifter_tt.tt_shiftmode; | 794 | par->hw.tt.mode = shifter_tt.tt_shiftmode; |
655 | par->hw.tt.sync=shifter.syncmode; | 795 | par->hw.tt.sync = shifter.syncmode; |
656 | addr = ((shifter.bas_hi & 0xff) << 16) | | 796 | addr = ((shifter.bas_hi & 0xff) << 16) | |
657 | ((shifter.bas_md & 0xff) << 8) | | 797 | ((shifter.bas_md & 0xff) << 8) | |
658 | ((shifter.bas_lo & 0xff)); | 798 | ((shifter.bas_lo & 0xff)); |
659 | par->screen_base = phys_to_virt(addr); | 799 | par->screen_base = phys_to_virt(addr); |
660 | } | 800 | } |
661 | 801 | ||
662 | static void tt_set_par( struct atafb_par *par ) | 802 | static void tt_set_par(struct atafb_par *par) |
663 | { | 803 | { |
664 | shifter_tt.tt_shiftmode=par->hw.tt.mode; | 804 | shifter_tt.tt_shiftmode = par->hw.tt.mode; |
665 | shifter.syncmode=par->hw.tt.sync; | 805 | shifter.syncmode = par->hw.tt.sync; |
666 | /* only set screen_base if really necessary */ | 806 | /* only set screen_base if really necessary */ |
667 | if (current_par.screen_base != par->screen_base) | 807 | if (current_par.screen_base != par->screen_base) |
668 | fbhw->set_screen_base(par->screen_base); | 808 | fbhw->set_screen_base(par->screen_base); |
669 | } | 809 | } |
670 | 810 | ||
671 | 811 | static int tt_setcolreg(unsigned int regno, unsigned int red, | |
672 | static int tt_getcolreg(unsigned regno, unsigned *red, | 812 | unsigned int green, unsigned int blue, |
673 | unsigned *green, unsigned *blue, | 813 | unsigned int transp, struct fb_info *info) |
674 | unsigned *transp, struct fb_info *info) | ||
675 | { | ||
676 | int t, col; | ||
677 | |||
678 | if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH) | ||
679 | regno += 254; | ||
680 | if (regno > 255) | ||
681 | return 1; | ||
682 | t = tt_palette[regno]; | ||
683 | col = t & 15; | ||
684 | col |= col << 4; | ||
685 | col |= col << 8; | ||
686 | *blue = col; | ||
687 | col = (t >> 4) & 15; | ||
688 | col |= col << 4; | ||
689 | col |= col << 8; | ||
690 | *green = col; | ||
691 | col = (t >> 8) & 15; | ||
692 | col |= col << 4; | ||
693 | col |= col << 8; | ||
694 | *red = col; | ||
695 | *transp = 0; | ||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | |||
700 | static int tt_setcolreg(unsigned regno, unsigned red, | ||
701 | unsigned green, unsigned blue, | ||
702 | unsigned transp, struct fb_info *info) | ||
703 | { | 814 | { |
704 | if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH) | 815 | if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH) |
705 | regno += 254; | 816 | regno += 254; |
@@ -708,15 +819,14 @@ static int tt_setcolreg(unsigned regno, unsigned red, | |||
708 | tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) | | 819 | tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) | |
709 | (blue >> 12)); | 820 | (blue >> 12)); |
710 | if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == | 821 | if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == |
711 | TT_SHIFTER_STHIGH && regno == 254) | 822 | TT_SHIFTER_STHIGH && regno == 254) |
712 | tt_palette[0] = 0; | 823 | tt_palette[0] = 0; |
713 | return 0; | 824 | return 0; |
714 | } | 825 | } |
715 | 826 | ||
716 | 827 | static int tt_detect(void) | |
717 | static int tt_detect( void ) | 828 | { |
718 | 829 | struct atafb_par par; | |
719 | { struct atafb_par par; | ||
720 | 830 | ||
721 | /* Determine the connected monitor: The DMA sound must be | 831 | /* Determine the connected monitor: The DMA sound must be |
722 | * disabled before reading the MFP GPIP, because the Sound | 832 | * disabled before reading the MFP GPIP, because the Sound |
@@ -726,9 +836,9 @@ static int tt_detect( void ) | |||
726 | * announced that the Eagle is TT compatible, but only the PCM is | 836 | * announced that the Eagle is TT compatible, but only the PCM is |
727 | * missing... | 837 | * missing... |
728 | */ | 838 | */ |
729 | if (ATARIHW_PRESENT(PCM_8BIT)) { | 839 | if (ATARIHW_PRESENT(PCM_8BIT)) { |
730 | tt_dmasnd.ctrl = DMASND_CTRL_OFF; | 840 | tt_dmasnd.ctrl = DMASND_CTRL_OFF; |
731 | udelay(20); /* wait a while for things to settle down */ | 841 | udelay(20); /* wait a while for things to settle down */ |
732 | } | 842 | } |
733 | mono_moni = (mfp.par_dt_reg & 0x80) == 0; | 843 | mono_moni = (mfp.par_dt_reg & 0x80) == 0; |
734 | 844 | ||
@@ -755,19 +865,24 @@ static struct pixel_clock { | |||
755 | unsigned long f; /* f/[Hz] */ | 865 | unsigned long f; /* f/[Hz] */ |
756 | unsigned long t; /* t/[ps] (=1/f) */ | 866 | unsigned long t; /* t/[ps] (=1/f) */ |
757 | int right, hsync, left; /* standard timing in clock cycles, not pixel */ | 867 | int right, hsync, left; /* standard timing in clock cycles, not pixel */ |
758 | /* hsync initialized in falcon_detect() */ | 868 | /* hsync initialized in falcon_detect() */ |
759 | int sync_mask; /* or-mask for hw.falcon.sync to set this clock */ | 869 | int sync_mask; /* or-mask for hw.falcon.sync to set this clock */ |
760 | int control_mask; /* ditto, for hw.falcon.vid_control */ | 870 | int control_mask; /* ditto, for hw.falcon.vid_control */ |
761 | } | 871 | } f25 = { |
762 | f25 = {25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25}, | 872 | 25175000, 39721, 18, 0, 42, 0x0, VCO_CLOCK25 |
763 | f32 = {32000000, 31250, 18, 0, 42, 0x0, 0}, | 873 | }, f32 = { |
764 | fext = { 0, 0, 18, 0, 42, 0x1, 0}; | 874 | 32000000, 31250, 18, 0, 42, 0x0, 0 |
875 | }, fext = { | ||
876 | 0, 0, 18, 0, 42, 0x1, 0 | ||
877 | }; | ||
765 | 878 | ||
766 | /* VIDEL-prescale values [mon_type][pixel_length from VCO] */ | 879 | /* VIDEL-prescale values [mon_type][pixel_length from VCO] */ |
767 | static int vdl_prescale[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}}; | 880 | static int vdl_prescale[4][3] = { |
881 | { 4,2,1 }, { 4,2,1 }, { 4,2,2 }, { 4,2,1 } | ||
882 | }; | ||
768 | 883 | ||
769 | /* Default hsync timing [mon_type] in picoseconds */ | 884 | /* Default hsync timing [mon_type] in picoseconds */ |
770 | static long h_syncs[4] = {3000000, 4875000, 4000000, 4875000}; | 885 | static long h_syncs[4] = { 3000000, 4875000, 4000000, 4875000 }; |
771 | 886 | ||
772 | #ifdef FBCON_HAS_CFB16 | 887 | #ifdef FBCON_HAS_CFB16 |
773 | static u16 fbcon_cfb16_cmap[16]; | 888 | static u16 fbcon_cfb16_cmap[16]; |
@@ -775,12 +890,12 @@ static u16 fbcon_cfb16_cmap[16]; | |||
775 | 890 | ||
776 | static inline int hxx_prescale(struct falcon_hw *hw) | 891 | static inline int hxx_prescale(struct falcon_hw *hw) |
777 | { | 892 | { |
778 | return hw->ste_mode ? 16 : | 893 | return hw->ste_mode ? 16 |
779 | vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3]; | 894 | : vdl_prescale[mon_type][hw->vid_mode >> 2 & 0x3]; |
780 | } | 895 | } |
781 | 896 | ||
782 | static int falcon_encode_fix( struct fb_fix_screeninfo *fix, | 897 | static int falcon_encode_fix(struct fb_fix_screeninfo *fix, |
783 | struct atafb_par *par ) | 898 | struct atafb_par *par) |
784 | { | 899 | { |
785 | strcpy(fix->id, "Atari Builtin"); | 900 | strcpy(fix->id, "Atari Builtin"); |
786 | fix->smem_start = (unsigned long)real_screen_base; | 901 | fix->smem_start = (unsigned long)real_screen_base; |
@@ -796,8 +911,7 @@ static int falcon_encode_fix( struct fb_fix_screeninfo *fix, | |||
796 | fix->type_aux = 0; | 911 | fix->type_aux = 0; |
797 | /* no smooth scrolling with longword aligned video mem */ | 912 | /* no smooth scrolling with longword aligned video mem */ |
798 | fix->xpanstep = 32; | 913 | fix->xpanstep = 32; |
799 | } | 914 | } else if (par->hw.falcon.f_shift & 0x100) { |
800 | else if (par->hw.falcon.f_shift & 0x100) { | ||
801 | fix->type = FB_TYPE_PACKED_PIXELS; | 915 | fix->type = FB_TYPE_PACKED_PIXELS; |
802 | fix->type_aux = 0; | 916 | fix->type_aux = 0; |
803 | /* Is this ok or should it be DIRECTCOLOR? */ | 917 | /* Is this ok or should it be DIRECTCOLOR? */ |
@@ -809,9 +923,8 @@ static int falcon_encode_fix( struct fb_fix_screeninfo *fix, | |||
809 | return 0; | 923 | return 0; |
810 | } | 924 | } |
811 | 925 | ||
812 | 926 | static int falcon_decode_var(struct fb_var_screeninfo *var, | |
813 | static int falcon_decode_var( struct fb_var_screeninfo *var, | 927 | struct atafb_par *par) |
814 | struct atafb_par *par ) | ||
815 | { | 928 | { |
816 | int bpp = var->bits_per_pixel; | 929 | int bpp = var->bits_per_pixel; |
817 | int xres = var->xres; | 930 | int xres = var->xres; |
@@ -823,17 +936,19 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
823 | int linelen; | 936 | int linelen; |
824 | int interlace = 0, doubleline = 0; | 937 | int interlace = 0, doubleline = 0; |
825 | struct pixel_clock *pclock; | 938 | struct pixel_clock *pclock; |
826 | int plen; /* width of pixel in clock cycles */ | 939 | int plen; /* width of pixel in clock cycles */ |
827 | int xstretch; | 940 | int xstretch; |
828 | int prescale; | 941 | int prescale; |
829 | int longoffset = 0; | 942 | int longoffset = 0; |
830 | int hfreq, vfreq; | 943 | int hfreq, vfreq; |
944 | int hdb_off, hde_off, base_off; | ||
945 | int gstart, gend1, gend2, align; | ||
831 | 946 | ||
832 | /* | 947 | /* |
833 | Get the video params out of 'var'. If a value doesn't fit, round | 948 | Get the video params out of 'var'. If a value doesn't fit, round |
834 | it up, if it's too big, return EINVAL. | 949 | it up, if it's too big, return EINVAL. |
835 | Round up in the following order: bits_per_pixel, xres, yres, | 950 | Round up in the following order: bits_per_pixel, xres, yres, |
836 | xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, | 951 | xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, |
837 | horizontal timing, vertical timing. | 952 | horizontal timing, vertical timing. |
838 | 953 | ||
839 | There is a maximum of screen resolution determined by pixelclock | 954 | There is a maximum of screen resolution determined by pixelclock |
@@ -843,11 +958,11 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
843 | Frequency range for multisync monitors is given via command line. | 958 | Frequency range for multisync monitors is given via command line. |
844 | For TV and SM124 both frequencies are fixed. | 959 | For TV and SM124 both frequencies are fixed. |
845 | 960 | ||
846 | X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32==0) | 961 | X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0) |
847 | Y % 16 == 0 to fit 8x16 font | 962 | Y % 16 == 0 to fit 8x16 font |
848 | Y % 8 == 0 if Y<400 | 963 | Y % 8 == 0 if Y<400 |
849 | 964 | ||
850 | Currently interlace and doubleline mode in var are ignored. | 965 | Currently interlace and doubleline mode in var are ignored. |
851 | On SM124 and TV only the standard resolutions can be used. | 966 | On SM124 and TV only the standard resolutions can be used. |
852 | */ | 967 | */ |
853 | 968 | ||
@@ -855,43 +970,38 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
855 | if (!xres || !yres || !bpp) | 970 | if (!xres || !yres || !bpp) |
856 | return -EINVAL; | 971 | return -EINVAL; |
857 | 972 | ||
858 | if (mon_type == F_MON_SM && bpp != 1) { | 973 | if (mon_type == F_MON_SM && bpp != 1) |
859 | return -EINVAL; | 974 | return -EINVAL; |
860 | } | 975 | |
861 | else if (bpp <= 1) { | 976 | if (bpp <= 1) { |
862 | bpp = 1; | 977 | bpp = 1; |
863 | par->hw.falcon.f_shift = 0x400; | 978 | par->hw.falcon.f_shift = 0x400; |
864 | par->hw.falcon.st_shift = 0x200; | 979 | par->hw.falcon.st_shift = 0x200; |
865 | } | 980 | } else if (bpp <= 2) { |
866 | else if (bpp <= 2) { | ||
867 | bpp = 2; | 981 | bpp = 2; |
868 | par->hw.falcon.f_shift = 0x000; | 982 | par->hw.falcon.f_shift = 0x000; |
869 | par->hw.falcon.st_shift = 0x100; | 983 | par->hw.falcon.st_shift = 0x100; |
870 | } | 984 | } else if (bpp <= 4) { |
871 | else if (bpp <= 4) { | ||
872 | bpp = 4; | 985 | bpp = 4; |
873 | par->hw.falcon.f_shift = 0x000; | 986 | par->hw.falcon.f_shift = 0x000; |
874 | par->hw.falcon.st_shift = 0x000; | 987 | par->hw.falcon.st_shift = 0x000; |
875 | } | 988 | } else if (bpp <= 8) { |
876 | else if (bpp <= 8) { | ||
877 | bpp = 8; | 989 | bpp = 8; |
878 | par->hw.falcon.f_shift = 0x010; | 990 | par->hw.falcon.f_shift = 0x010; |
879 | } | 991 | } else if (bpp <= 16) { |
880 | else if (bpp <= 16) { | 992 | bpp = 16; /* packed pixel mode */ |
881 | bpp = 16; /* packed pixel mode */ | 993 | par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */ |
882 | par->hw.falcon.f_shift = 0x100; /* hicolor, no overlay */ | 994 | } else |
883 | } | ||
884 | else | ||
885 | return -EINVAL; | 995 | return -EINVAL; |
886 | par->hw.falcon.bpp = bpp; | 996 | par->hw.falcon.bpp = bpp; |
887 | 997 | ||
888 | if (mon_type == F_MON_SM || DontCalcRes) { | 998 | if (mon_type == F_MON_SM || DontCalcRes) { |
889 | /* Skip all calculations. VGA/TV/SC1224 only supported. */ | 999 | /* Skip all calculations. VGA/TV/SC1224 only supported. */ |
890 | struct fb_var_screeninfo *myvar = &atafb_predefined[0]; | 1000 | struct fb_var_screeninfo *myvar = &atafb_predefined[0]; |
891 | 1001 | ||
892 | if (bpp > myvar->bits_per_pixel || | 1002 | if (bpp > myvar->bits_per_pixel || |
893 | var->xres > myvar->xres || | 1003 | var->xres > myvar->xres || |
894 | var->yres > myvar->yres) | 1004 | var->yres > myvar->yres) |
895 | return -EINVAL; | 1005 | return -EINVAL; |
896 | fbhw->get_par(par); /* Current par will be new par */ | 1006 | fbhw->get_par(par); /* Current par will be new par */ |
897 | goto set_screen_base; /* Don't forget this */ | 1007 | goto set_screen_base; /* Don't forget this */ |
@@ -910,8 +1020,8 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
910 | yres = 400; | 1020 | yres = 400; |
911 | 1021 | ||
912 | /* 2 planes must use STE compatibility mode */ | 1022 | /* 2 planes must use STE compatibility mode */ |
913 | par->hw.falcon.ste_mode = bpp==2; | 1023 | par->hw.falcon.ste_mode = bpp == 2; |
914 | par->hw.falcon.mono = bpp==1; | 1024 | par->hw.falcon.mono = bpp == 1; |
915 | 1025 | ||
916 | /* Total and visible scanline length must be a multiple of one longword, | 1026 | /* Total and visible scanline length must be a multiple of one longword, |
917 | * this and the console fontwidth yields the alignment for xres and | 1027 | * this and the console fontwidth yields the alignment for xres and |
@@ -967,8 +1077,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
967 | left_margin = hsync_len = 128 / plen; | 1077 | left_margin = hsync_len = 128 / plen; |
968 | right_margin = 0; | 1078 | right_margin = 0; |
969 | /* TODO set all margins */ | 1079 | /* TODO set all margins */ |
970 | } | 1080 | } else |
971 | else | ||
972 | #endif | 1081 | #endif |
973 | if (mon_type == F_MON_SC || mon_type == F_MON_TV) { | 1082 | if (mon_type == F_MON_SC || mon_type == F_MON_TV) { |
974 | plen = 2 * xstretch; | 1083 | plen = 2 * xstretch; |
@@ -1002,26 +1111,24 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1002 | vsync_len *= 2; | 1111 | vsync_len *= 2; |
1003 | } | 1112 | } |
1004 | } | 1113 | } |
1005 | } | 1114 | } else { /* F_MON_VGA */ |
1006 | else | ||
1007 | { /* F_MON_VGA */ | ||
1008 | if (bpp == 16) | 1115 | if (bpp == 16) |
1009 | xstretch = 2; /* Double pixel width only for hicolor */ | 1116 | xstretch = 2; /* Double pixel width only for hicolor */ |
1010 | /* Default values are used for vert./hor. timing if no pixelclock given. */ | 1117 | /* Default values are used for vert./hor. timing if no pixelclock given. */ |
1011 | if (var->pixclock == 0) { | 1118 | if (var->pixclock == 0) { |
1012 | int linesize; | 1119 | int linesize; |
1013 | 1120 | ||
1014 | /* Choose master pixelclock depending on hor. timing */ | 1121 | /* Choose master pixelclock depending on hor. timing */ |
1015 | plen = 1 * xstretch; | 1122 | plen = 1 * xstretch; |
1016 | if ((plen * xres + f25.right+f25.hsync+f25.left) * | 1123 | if ((plen * xres + f25.right + f25.hsync + f25.left) * |
1017 | fb_info.monspecs.hfmin < f25.f) | 1124 | fb_info.monspecs.hfmin < f25.f) |
1018 | pclock = &f25; | 1125 | pclock = &f25; |
1019 | else if ((plen * xres + f32.right+f32.hsync+f32.left) * | 1126 | else if ((plen * xres + f32.right + f32.hsync + |
1020 | fb_info.monspecs.hfmin < f32.f) | 1127 | f32.left) * fb_info.monspecs.hfmin < f32.f) |
1021 | pclock = &f32; | 1128 | pclock = &f32; |
1022 | else if ((plen * xres + fext.right+fext.hsync+fext.left) * | 1129 | else if ((plen * xres + fext.right + fext.hsync + |
1023 | fb_info.monspecs.hfmin < fext.f | 1130 | fext.left) * fb_info.monspecs.hfmin < fext.f && |
1024 | && fext.f) | 1131 | fext.f) |
1025 | pclock = &fext; | 1132 | pclock = &fext; |
1026 | else | 1133 | else |
1027 | return -EINVAL; | 1134 | return -EINVAL; |
@@ -1033,22 +1140,24 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1033 | upper_margin = 31; | 1140 | upper_margin = 31; |
1034 | lower_margin = 11; | 1141 | lower_margin = 11; |
1035 | vsync_len = 3; | 1142 | vsync_len = 3; |
1036 | } | 1143 | } else { |
1037 | else { | ||
1038 | /* Choose largest pixelclock <= wanted clock */ | 1144 | /* Choose largest pixelclock <= wanted clock */ |
1039 | int i; | 1145 | int i; |
1040 | unsigned long pcl = ULONG_MAX; | 1146 | unsigned long pcl = ULONG_MAX; |
1041 | pclock = 0; | 1147 | pclock = 0; |
1042 | for (i=1; i <= 4; i *= 2) { | 1148 | for (i = 1; i <= 4; i *= 2) { |
1043 | if (f25.t*i >= var->pixclock && f25.t*i < pcl) { | 1149 | if (f25.t * i >= var->pixclock && |
1150 | f25.t * i < pcl) { | ||
1044 | pcl = f25.t * i; | 1151 | pcl = f25.t * i; |
1045 | pclock = &f25; | 1152 | pclock = &f25; |
1046 | } | 1153 | } |
1047 | if (f32.t*i >= var->pixclock && f32.t*i < pcl) { | 1154 | if (f32.t * i >= var->pixclock && |
1155 | f32.t * i < pcl) { | ||
1048 | pcl = f32.t * i; | 1156 | pcl = f32.t * i; |
1049 | pclock = &f32; | 1157 | pclock = &f32; |
1050 | } | 1158 | } |
1051 | if (fext.t && fext.t*i >= var->pixclock && fext.t*i < pcl) { | 1159 | if (fext.t && fext.t * i >= var->pixclock && |
1160 | fext.t * i < pcl) { | ||
1052 | pcl = fext.t * i; | 1161 | pcl = fext.t * i; |
1053 | pclock = &fext; | 1162 | pclock = &fext; |
1054 | } | 1163 | } |
@@ -1070,8 +1179,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1070 | upper_margin = (upper_margin + 1) / 2; | 1179 | upper_margin = (upper_margin + 1) / 2; |
1071 | lower_margin = (lower_margin + 1) / 2; | 1180 | lower_margin = (lower_margin + 1) / 2; |
1072 | vsync_len = (vsync_len + 1) / 2; | 1181 | vsync_len = (vsync_len + 1) / 2; |
1073 | } | 1182 | } else if (var->vmode & FB_VMODE_DOUBLE) { |
1074 | else if (var->vmode & FB_VMODE_DOUBLE) { | ||
1075 | /* External unit is [double lines per frame] */ | 1183 | /* External unit is [double lines per frame] */ |
1076 | upper_margin *= 2; | 1184 | upper_margin *= 2; |
1077 | lower_margin *= 2; | 1185 | lower_margin *= 2; |
@@ -1079,7 +1187,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1079 | } | 1187 | } |
1080 | } | 1188 | } |
1081 | if (pclock == &fext) | 1189 | if (pclock == &fext) |
1082 | longoffset = 1; /* VIDEL doesn't synchronize on short offset */ | 1190 | longoffset = 1; /* VIDEL doesn't synchronize on short offset */ |
1083 | } | 1191 | } |
1084 | /* Is video bus bandwidth (32MB/s) too low for this resolution? */ | 1192 | /* Is video bus bandwidth (32MB/s) too low for this resolution? */ |
1085 | /* this is definitely wrong if bus clock != 32MHz */ | 1193 | /* this is definitely wrong if bus clock != 32MHz */ |
@@ -1098,7 +1206,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1098 | * between interlace and non-interlace without messing around | 1206 | * between interlace and non-interlace without messing around |
1099 | * with these. | 1207 | * with these. |
1100 | */ | 1208 | */ |
1101 | again: | 1209 | again: |
1102 | /* Set base_offset 128 and video bus width */ | 1210 | /* Set base_offset 128 and video bus width */ |
1103 | par->hw.falcon.vid_control = mon_type | f030_bus_width; | 1211 | par->hw.falcon.vid_control = mon_type | f030_bus_width; |
1104 | if (!longoffset) | 1212 | if (!longoffset) |
@@ -1112,37 +1220,34 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1112 | /* External or internal clock */ | 1220 | /* External or internal clock */ |
1113 | par->hw.falcon.sync = pclock->sync_mask | 0x2; | 1221 | par->hw.falcon.sync = pclock->sync_mask | 0x2; |
1114 | /* Pixellength and prescale */ | 1222 | /* Pixellength and prescale */ |
1115 | par->hw.falcon.vid_mode = (2/plen) << 2; | 1223 | par->hw.falcon.vid_mode = (2 / plen) << 2; |
1116 | if (doubleline) | 1224 | if (doubleline) |
1117 | par->hw.falcon.vid_mode |= VMO_DOUBLE; | 1225 | par->hw.falcon.vid_mode |= VMO_DOUBLE; |
1118 | if (interlace) | 1226 | if (interlace) |
1119 | par->hw.falcon.vid_mode |= VMO_INTER; | 1227 | par->hw.falcon.vid_mode |= VMO_INTER; |
1120 | 1228 | ||
1121 | /********************* | 1229 | /********************* |
1122 | Horizontal timing: unit = [master clock cycles] | 1230 | * Horizontal timing: unit = [master clock cycles] |
1123 | unit of hxx-registers: [master clock cycles * prescale] | 1231 | * unit of hxx-registers: [master clock cycles * prescale] |
1124 | Hxx-registers are 9 bit wide | 1232 | * Hxx-registers are 9 bit wide |
1125 | 1233 | * | |
1126 | 1 line = ((hht + 2) * 2 * prescale) clock cycles | 1234 | * 1 line = ((hht + 2) * 2 * prescale) clock cycles |
1127 | 1235 | * | |
1128 | graphic output = hdb & 0x200 ? | 1236 | * graphic output = hdb & 0x200 ? |
1129 | ((hht+2)*2 - hdb + hde) * prescale - hdboff + hdeoff: | 1237 | * ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff: |
1130 | ( hht + 2 - hdb + hde) * prescale - hdboff + hdeoff | 1238 | * (hht + 2 - hdb + hde) * prescale - hdboff + hdeoff |
1131 | (this must be a multiple of plen*128/bpp, on VGA pixels | 1239 | * (this must be a multiple of plen*128/bpp, on VGA pixels |
1132 | to the right may be cut off with a bigger right margin) | 1240 | * to the right may be cut off with a bigger right margin) |
1133 | 1241 | * | |
1134 | start of graphics relative to start of 1st halfline = hdb & 0x200 ? | 1242 | * start of graphics relative to start of 1st halfline = hdb & 0x200 ? |
1135 | (hdb - hht - 2) * prescale + hdboff : | 1243 | * (hdb - hht - 2) * prescale + hdboff : |
1136 | hdb * prescale + hdboff | 1244 | * hdb * prescale + hdboff |
1137 | 1245 | * | |
1138 | end of graphics relative to start of 1st halfline = | 1246 | * end of graphics relative to start of 1st halfline = |
1139 | (hde + hht + 2) * prescale + hdeoff | 1247 | * (hde + hht + 2) * prescale + hdeoff |
1140 | *********************/ | 1248 | *********************/ |
1141 | /* Calculate VIDEL registers */ | 1249 | /* Calculate VIDEL registers */ |
1142 | { | 1250 | { |
1143 | int hdb_off, hde_off, base_off; | ||
1144 | int gstart, gend1, gend2, align; | ||
1145 | |||
1146 | prescale = hxx_prescale(&par->hw.falcon); | 1251 | prescale = hxx_prescale(&par->hw.falcon); |
1147 | base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128; | 1252 | base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128; |
1148 | 1253 | ||
@@ -1154,8 +1259,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1154 | align = 1; | 1259 | align = 1; |
1155 | hde_off = 0; | 1260 | hde_off = 0; |
1156 | hdb_off = (base_off + 16 * plen) + prescale; | 1261 | hdb_off = (base_off + 16 * plen) + prescale; |
1157 | } | 1262 | } else { |
1158 | else { | ||
1159 | align = 128 / bpp; | 1263 | align = 128 / bpp; |
1160 | hde_off = ((128 / bpp + 2) * plen); | 1264 | hde_off = ((128 / bpp + 2) * plen); |
1161 | if (par->hw.falcon.ste_mode) | 1265 | if (par->hw.falcon.ste_mode) |
@@ -1164,23 +1268,24 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1164 | hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale; | 1268 | hdb_off = (base_off + (128 / bpp + 18) * plen) + prescale; |
1165 | } | 1269 | } |
1166 | 1270 | ||
1167 | gstart = (prescale/2 + plen * left_margin) / prescale; | 1271 | gstart = (prescale / 2 + plen * left_margin) / prescale; |
1168 | /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */ | 1272 | /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */ |
1169 | gend1 = gstart + ((xres + align-1) / align)*align * plen / prescale; | 1273 | gend1 = gstart + ((xres + align - 1) / align) * align * plen / prescale; |
1170 | /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */ | 1274 | /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */ |
1171 | gend2 = gstart + xres * plen / prescale; | 1275 | gend2 = gstart + xres * plen / prescale; |
1172 | par->HHT = plen * (left_margin + xres + right_margin) / | 1276 | par->HHT = plen * (left_margin + xres + right_margin) / |
1173 | (2 * prescale) - 2; | 1277 | (2 * prescale) - 2; |
1174 | /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/ | 1278 | /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/ |
1175 | 1279 | ||
1176 | par->HDB = gstart - hdb_off/prescale; | 1280 | par->HDB = gstart - hdb_off / prescale; |
1177 | par->HBE = gstart; | 1281 | par->HBE = gstart; |
1178 | if (par->HDB < 0) par->HDB += par->HHT + 2 + 0x200; | 1282 | if (par->HDB < 0) |
1179 | par->HDE = gend1 - par->HHT - 2 - hde_off/prescale; | 1283 | par->HDB += par->HHT + 2 + 0x200; |
1284 | par->HDE = gend1 - par->HHT - 2 - hde_off / prescale; | ||
1180 | par->HBB = gend2 - par->HHT - 2; | 1285 | par->HBB = gend2 - par->HHT - 2; |
1181 | #if 0 | 1286 | #if 0 |
1182 | /* One more Videl constraint: data fetch of two lines must not overlap */ | 1287 | /* One more Videl constraint: data fetch of two lines must not overlap */ |
1183 | if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) { | 1288 | if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) { |
1184 | /* if this happens increase margins, decrease hfreq. */ | 1289 | /* if this happens increase margins, decrease hfreq. */ |
1185 | } | 1290 | } |
1186 | #endif | 1291 | #endif |
@@ -1189,11 +1294,11 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1189 | par->HSS = par->HHT + 2 - plen * hsync_len / prescale; | 1294 | par->HSS = par->HHT + 2 - plen * hsync_len / prescale; |
1190 | if (par->HSS < par->HBB) | 1295 | if (par->HSS < par->HBB) |
1191 | par->HSS = par->HBB; | 1296 | par->HSS = par->HBB; |
1192 | } | 1297 | } |
1193 | 1298 | ||
1194 | /* check hor. frequency */ | 1299 | /* check hor. frequency */ |
1195 | hfreq = pclock->f / ((par->HHT+2)*prescale*2); | 1300 | hfreq = pclock->f / ((par->HHT + 2) * prescale * 2); |
1196 | if (hfreq > fb_info.monspecs.hfmax && mon_type!=F_MON_VGA) { | 1301 | if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) { |
1197 | /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */ | 1302 | /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */ |
1198 | /* Too high -> enlarge margin */ | 1303 | /* Too high -> enlarge margin */ |
1199 | left_margin += 1; | 1304 | left_margin += 1; |
@@ -1213,12 +1318,14 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1213 | par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */ | 1318 | par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */ |
1214 | par->VDB = par->VBE; | 1319 | par->VDB = par->VBE; |
1215 | par->VDE = yres; | 1320 | par->VDE = yres; |
1216 | if (!interlace) par->VDE <<= 1; | 1321 | if (!interlace) |
1217 | if (doubleline) par->VDE <<= 1; /* VDE now half lines per (half-)frame */ | 1322 | par->VDE <<= 1; |
1323 | if (doubleline) | ||
1324 | par->VDE <<= 1; /* VDE now half lines per (half-)frame */ | ||
1218 | par->VDE += par->VDB; | 1325 | par->VDE += par->VDB; |
1219 | par->VBB = par->VDE; | 1326 | par->VBB = par->VDE; |
1220 | par->VFT = par->VBB + (lower_margin * 2 - 1) - 1; | 1327 | par->VFT = par->VBB + (lower_margin * 2 - 1) - 1; |
1221 | par->VSS = par->VFT+1 - (vsync_len * 2 - 1); | 1328 | par->VSS = par->VFT + 1 - (vsync_len * 2 - 1); |
1222 | /* vbb,vss,vft must be even in interlace mode */ | 1329 | /* vbb,vss,vft must be even in interlace mode */ |
1223 | if (interlace) { | 1330 | if (interlace) { |
1224 | par->VBB++; | 1331 | par->VBB++; |
@@ -1229,55 +1336,53 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1229 | /* V-frequency check, hope I didn't create any loop here. */ | 1336 | /* V-frequency check, hope I didn't create any loop here. */ |
1230 | /* Interlace and doubleline are mutually exclusive. */ | 1337 | /* Interlace and doubleline are mutually exclusive. */ |
1231 | vfreq = (hfreq * 2) / (par->VFT + 1); | 1338 | vfreq = (hfreq * 2) / (par->VFT + 1); |
1232 | if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) { | 1339 | if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) { |
1233 | /* Too high -> try again with doubleline */ | 1340 | /* Too high -> try again with doubleline */ |
1234 | doubleline = 1; | 1341 | doubleline = 1; |
1235 | goto again; | 1342 | goto again; |
1236 | } | 1343 | } else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) { |
1237 | else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) { | ||
1238 | /* Too low -> try again with interlace */ | 1344 | /* Too low -> try again with interlace */ |
1239 | interlace = 1; | 1345 | interlace = 1; |
1240 | goto again; | 1346 | goto again; |
1241 | } | 1347 | } else if (vfreq < fb_info.monspecs.vfmin && doubleline) { |
1242 | else if (vfreq < fb_info.monspecs.vfmin && doubleline) { | ||
1243 | /* Doubleline too low -> clear doubleline and enlarge margins */ | 1348 | /* Doubleline too low -> clear doubleline and enlarge margins */ |
1244 | int lines; | 1349 | int lines; |
1245 | doubleline = 0; | 1350 | doubleline = 0; |
1246 | for (lines=0; | 1351 | for (lines = 0; |
1247 | (hfreq*2)/(par->VFT+1+4*lines-2*yres)>fb_info.monspecs.vfmax; | 1352 | (hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) > |
1353 | fb_info.monspecs.vfmax; | ||
1248 | lines++) | 1354 | lines++) |
1249 | ; | 1355 | ; |
1250 | upper_margin += lines; | 1356 | upper_margin += lines; |
1251 | lower_margin += lines; | 1357 | lower_margin += lines; |
1252 | goto again; | 1358 | goto again; |
1253 | } | 1359 | } else if (vfreq > fb_info.monspecs.vfmax && doubleline) { |
1254 | else if (vfreq > fb_info.monspecs.vfmax && doubleline) { | ||
1255 | /* Doubleline too high -> enlarge margins */ | 1360 | /* Doubleline too high -> enlarge margins */ |
1256 | int lines; | 1361 | int lines; |
1257 | for (lines=0; | 1362 | for (lines = 0; |
1258 | (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax; | 1363 | (hfreq * 2) / (par->VFT + 1 + 4 * lines) > |
1259 | lines+=2) | 1364 | fb_info.monspecs.vfmax; |
1365 | lines += 2) | ||
1260 | ; | 1366 | ; |
1261 | upper_margin += lines; | 1367 | upper_margin += lines; |
1262 | lower_margin += lines; | 1368 | lower_margin += lines; |
1263 | goto again; | 1369 | goto again; |
1264 | } | 1370 | } else if (vfreq > fb_info.monspecs.vfmax && interlace) { |
1265 | else if (vfreq > fb_info.monspecs.vfmax && interlace) { | ||
1266 | /* Interlace, too high -> enlarge margins */ | 1371 | /* Interlace, too high -> enlarge margins */ |
1267 | int lines; | 1372 | int lines; |
1268 | for (lines=0; | 1373 | for (lines = 0; |
1269 | (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax; | 1374 | (hfreq * 2) / (par->VFT + 1 + 4 * lines) > |
1375 | fb_info.monspecs.vfmax; | ||
1270 | lines++) | 1376 | lines++) |
1271 | ; | 1377 | ; |
1272 | upper_margin += lines; | 1378 | upper_margin += lines; |
1273 | lower_margin += lines; | 1379 | lower_margin += lines; |
1274 | goto again; | 1380 | goto again; |
1275 | } | 1381 | } else if (vfreq < fb_info.monspecs.vfmin || |
1276 | else if (vfreq < fb_info.monspecs.vfmin || | 1382 | vfreq > fb_info.monspecs.vfmax) |
1277 | vfreq > fb_info.monspecs.vfmax) | ||
1278 | return -EINVAL; | 1383 | return -EINVAL; |
1279 | 1384 | ||
1280 | set_screen_base: | 1385 | set_screen_base: |
1281 | linelen = xres_virtual * bpp / 8; | 1386 | linelen = xres_virtual * bpp / 8; |
1282 | if (yres_virtual * linelen > screen_len && screen_len) | 1387 | if (yres_virtual * linelen > screen_len && screen_len) |
1283 | return -EINVAL; | 1388 | return -EINVAL; |
@@ -1289,11 +1394,20 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, | |||
1289 | par->screen_base = screen_base + var->yoffset * linelen; | 1394 | par->screen_base = screen_base + var->yoffset * linelen; |
1290 | par->hw.falcon.xoffset = 0; | 1395 | par->hw.falcon.xoffset = 0; |
1291 | 1396 | ||
1397 | // FIXME!!! sort of works, no crash | ||
1398 | //par->next_line = linelen; | ||
1399 | //par->next_plane = yres_virtual * linelen; | ||
1400 | par->next_line = linelen; | ||
1401 | par->next_plane = 2; | ||
1402 | // crashes | ||
1403 | //par->next_plane = linelen; | ||
1404 | //par->next_line = yres_virtual * linelen; | ||
1405 | |||
1292 | return 0; | 1406 | return 0; |
1293 | } | 1407 | } |
1294 | 1408 | ||
1295 | static int falcon_encode_var( struct fb_var_screeninfo *var, | 1409 | static int falcon_encode_var(struct fb_var_screeninfo *var, |
1296 | struct atafb_par *par ) | 1410 | struct atafb_par *par) |
1297 | { | 1411 | { |
1298 | /* !!! only for VGA !!! */ | 1412 | /* !!! only for VGA !!! */ |
1299 | int linelen; | 1413 | int linelen; |
@@ -1306,10 +1420,10 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1306 | var->pixclock = hw->sync & 0x1 ? fext.t : | 1420 | var->pixclock = hw->sync & 0x1 ? fext.t : |
1307 | hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t; | 1421 | hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t; |
1308 | 1422 | ||
1309 | var->height=-1; | 1423 | var->height = -1; |
1310 | var->width=-1; | 1424 | var->width = -1; |
1311 | 1425 | ||
1312 | var->sync=0; | 1426 | var->sync = 0; |
1313 | if (hw->vid_control & VCO_HSYPOS) | 1427 | if (hw->vid_control & VCO_HSYPOS) |
1314 | var->sync |= FB_SYNC_HOR_HIGH_ACT; | 1428 | var->sync |= FB_SYNC_HOR_HIGH_ACT; |
1315 | if (hw->vid_control & VCO_VSYPOS) | 1429 | if (hw->vid_control & VCO_VSYPOS) |
@@ -1320,7 +1434,7 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1320 | var->vmode |= FB_VMODE_INTERLACED; | 1434 | var->vmode |= FB_VMODE_INTERLACED; |
1321 | if (hw->vid_mode & VMO_DOUBLE) | 1435 | if (hw->vid_mode & VMO_DOUBLE) |
1322 | var->vmode |= FB_VMODE_DOUBLE; | 1436 | var->vmode |= FB_VMODE_DOUBLE; |
1323 | 1437 | ||
1324 | /* visible y resolution: | 1438 | /* visible y resolution: |
1325 | * Graphics display starts at line VDB and ends at line | 1439 | * Graphics display starts at line VDB and ends at line |
1326 | * VDE. If interlace mode off unit of VC-registers is | 1440 | * VDE. If interlace mode off unit of VC-registers is |
@@ -1332,14 +1446,15 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1332 | if (var->vmode & FB_VMODE_DOUBLE) | 1446 | if (var->vmode & FB_VMODE_DOUBLE) |
1333 | var->yres >>= 1; | 1447 | var->yres >>= 1; |
1334 | 1448 | ||
1335 | /* to get bpp, we must examine f_shift and st_shift. | 1449 | /* |
1450 | * to get bpp, we must examine f_shift and st_shift. | ||
1336 | * f_shift is valid if any of bits no. 10, 8 or 4 | 1451 | * f_shift is valid if any of bits no. 10, 8 or 4 |
1337 | * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e. | 1452 | * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e. |
1338 | * if bit 10 set then bit 8 and bit 4 don't care... | 1453 | * if bit 10 set then bit 8 and bit 4 don't care... |
1339 | * If all these bits are 0 get display depth from st_shift | 1454 | * If all these bits are 0 get display depth from st_shift |
1340 | * (as for ST and STE) | 1455 | * (as for ST and STE) |
1341 | */ | 1456 | */ |
1342 | if (hw->f_shift & 0x400) /* 2 colors */ | 1457 | if (hw->f_shift & 0x400) /* 2 colors */ |
1343 | var->bits_per_pixel = 1; | 1458 | var->bits_per_pixel = 1; |
1344 | else if (hw->f_shift & 0x100) /* hicolor */ | 1459 | else if (hw->f_shift & 0x100) /* hicolor */ |
1345 | var->bits_per_pixel = 16; | 1460 | var->bits_per_pixel = 16; |
@@ -1349,7 +1464,7 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1349 | var->bits_per_pixel = 4; | 1464 | var->bits_per_pixel = 4; |
1350 | else if (hw->st_shift == 0x100) | 1465 | else if (hw->st_shift == 0x100) |
1351 | var->bits_per_pixel = 2; | 1466 | var->bits_per_pixel = 2; |
1352 | else /* if (hw->st_shift == 0x200) */ | 1467 | else /* if (hw->st_shift == 0x200) */ |
1353 | var->bits_per_pixel = 1; | 1468 | var->bits_per_pixel = 1; |
1354 | 1469 | ||
1355 | var->xres = hw->line_width * 16 / var->bits_per_pixel; | 1470 | var->xres = hw->line_width * 16 / var->bits_per_pixel; |
@@ -1358,42 +1473,42 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1358 | var->xres_virtual += 16; | 1473 | var->xres_virtual += 16; |
1359 | 1474 | ||
1360 | if (var->bits_per_pixel == 16) { | 1475 | if (var->bits_per_pixel == 16) { |
1361 | var->red.offset=11; | 1476 | var->red.offset = 11; |
1362 | var->red.length=5; | 1477 | var->red.length = 5; |
1363 | var->red.msb_right=0; | 1478 | var->red.msb_right = 0; |
1364 | var->green.offset=5; | 1479 | var->green.offset = 5; |
1365 | var->green.length=6; | 1480 | var->green.length = 6; |
1366 | var->green.msb_right=0; | 1481 | var->green.msb_right = 0; |
1367 | var->blue.offset=0; | 1482 | var->blue.offset = 0; |
1368 | var->blue.length=5; | 1483 | var->blue.length = 5; |
1369 | var->blue.msb_right=0; | 1484 | var->blue.msb_right = 0; |
1370 | } | 1485 | } else { |
1371 | else { | 1486 | var->red.offset = 0; |
1372 | var->red.offset=0; | ||
1373 | var->red.length = hw->ste_mode ? 4 : 6; | 1487 | var->red.length = hw->ste_mode ? 4 : 6; |
1374 | var->red.msb_right=0; | 1488 | if (var->red.length > var->bits_per_pixel) |
1375 | var->grayscale=0; | 1489 | var->red.length = var->bits_per_pixel; |
1376 | var->blue=var->green=var->red; | 1490 | var->red.msb_right = 0; |
1491 | var->grayscale = 0; | ||
1492 | var->blue = var->green = var->red; | ||
1377 | } | 1493 | } |
1378 | var->transp.offset=0; | 1494 | var->transp.offset = 0; |
1379 | var->transp.length=0; | 1495 | var->transp.length = 0; |
1380 | var->transp.msb_right=0; | 1496 | var->transp.msb_right = 0; |
1381 | 1497 | ||
1382 | linelen = var->xres_virtual * var->bits_per_pixel / 8; | 1498 | linelen = var->xres_virtual * var->bits_per_pixel / 8; |
1383 | if (screen_len) { | 1499 | if (screen_len) { |
1384 | if (par->yres_virtual) | 1500 | if (par->yres_virtual) |
1385 | var->yres_virtual = par->yres_virtual; | 1501 | var->yres_virtual = par->yres_virtual; |
1386 | else | 1502 | else |
1387 | /* yres_virtual==0 means use maximum */ | 1503 | /* yres_virtual == 0 means use maximum */ |
1388 | var->yres_virtual = screen_len / linelen; | 1504 | var->yres_virtual = screen_len / linelen; |
1389 | } | 1505 | } else { |
1390 | else { | ||
1391 | if (hwscroll < 0) | 1506 | if (hwscroll < 0) |
1392 | var->yres_virtual = 2 * var->yres; | 1507 | var->yres_virtual = 2 * var->yres; |
1393 | else | 1508 | else |
1394 | var->yres_virtual=var->yres+hwscroll * 16; | 1509 | var->yres_virtual = var->yres + hwscroll * 16; |
1395 | } | 1510 | } |
1396 | var->xoffset=0; /* TODO change this */ | 1511 | var->xoffset = 0; /* TODO change this */ |
1397 | 1512 | ||
1398 | /* hdX-offsets */ | 1513 | /* hdX-offsets */ |
1399 | prescale = hxx_prescale(hw); | 1514 | prescale = hxx_prescale(hw); |
@@ -1402,8 +1517,7 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1402 | if (hw->f_shift & 0x100) { | 1517 | if (hw->f_shift & 0x100) { |
1403 | hde_off = 0; | 1518 | hde_off = 0; |
1404 | hdb_off = (base_off + 16 * plen) + prescale; | 1519 | hdb_off = (base_off + 16 * plen) + prescale; |
1405 | } | 1520 | } else { |
1406 | else { | ||
1407 | hde_off = ((128 / var->bits_per_pixel + 2) * plen); | 1521 | hde_off = ((128 / var->bits_per_pixel + 2) * plen); |
1408 | if (hw->ste_mode) | 1522 | if (hw->ste_mode) |
1409 | hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen) | 1523 | hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen) |
@@ -1415,8 +1529,8 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1415 | 1529 | ||
1416 | /* Right margin includes hsync */ | 1530 | /* Right margin includes hsync */ |
1417 | var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) - | 1531 | var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) - |
1418 | (hw->hdb & 0x200 ? 2+hw->hht : 0)); | 1532 | (hw->hdb & 0x200 ? 2 + hw->hht : 0)); |
1419 | if (hw->ste_mode || mon_type!=F_MON_VGA) | 1533 | if (hw->ste_mode || mon_type != F_MON_VGA) |
1420 | var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off; | 1534 | var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off; |
1421 | else | 1535 | else |
1422 | /* can't use this in ste_mode, because hbb is +1 off */ | 1536 | /* can't use this in ste_mode, because hbb is +1 off */ |
@@ -1424,15 +1538,14 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1424 | var->hsync_len = prescale * (hw->hht + 2 - hw->hss); | 1538 | var->hsync_len = prescale * (hw->hht + 2 - hw->hss); |
1425 | 1539 | ||
1426 | /* Lower margin includes vsync */ | 1540 | /* Lower margin includes vsync */ |
1427 | var->upper_margin = hw->vdb / 2 ; /* round down to full lines */ | 1541 | var->upper_margin = hw->vdb / 2; /* round down to full lines */ |
1428 | var->lower_margin = (hw->vft+1 - hw->vde + 1) / 2; /* round up */ | 1542 | var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2; /* round up */ |
1429 | var->vsync_len = (hw->vft+1 - hw->vss + 1) / 2; /* round up */ | 1543 | var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2; /* round up */ |
1430 | if (var->vmode & FB_VMODE_INTERLACED) { | 1544 | if (var->vmode & FB_VMODE_INTERLACED) { |
1431 | var->upper_margin *= 2; | 1545 | var->upper_margin *= 2; |
1432 | var->lower_margin *= 2; | 1546 | var->lower_margin *= 2; |
1433 | var->vsync_len *= 2; | 1547 | var->vsync_len *= 2; |
1434 | } | 1548 | } else if (var->vmode & FB_VMODE_DOUBLE) { |
1435 | else if (var->vmode & FB_VMODE_DOUBLE) { | ||
1436 | var->upper_margin = (var->upper_margin + 1) / 2; | 1549 | var->upper_margin = (var->upper_margin + 1) / 2; |
1437 | var->lower_margin = (var->lower_margin + 1) / 2; | 1550 | var->lower_margin = (var->lower_margin + 1) / 2; |
1438 | var->vsync_len = (var->vsync_len + 1) / 2; | 1551 | var->vsync_len = (var->vsync_len + 1) / 2; |
@@ -1447,20 +1560,19 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, | |||
1447 | var->lower_margin -= var->vsync_len; | 1560 | var->lower_margin -= var->vsync_len; |
1448 | 1561 | ||
1449 | if (screen_base) | 1562 | if (screen_base) |
1450 | var->yoffset=(par->screen_base - screen_base)/linelen; | 1563 | var->yoffset = (par->screen_base - screen_base) / linelen; |
1451 | else | 1564 | else |
1452 | var->yoffset=0; | 1565 | var->yoffset = 0; |
1453 | var->nonstd=0; /* what is this for? */ | 1566 | var->nonstd = 0; /* what is this for? */ |
1454 | var->activate=0; | 1567 | var->activate = 0; |
1455 | return 0; | 1568 | return 0; |
1456 | } | 1569 | } |
1457 | 1570 | ||
1458 | 1571 | static int f_change_mode; | |
1459 | static int f_change_mode = 0; | ||
1460 | static struct falcon_hw f_new_mode; | 1572 | static struct falcon_hw f_new_mode; |
1461 | static int f_pan_display = 0; | 1573 | static int f_pan_display; |
1462 | 1574 | ||
1463 | static void falcon_get_par( struct atafb_par *par ) | 1575 | static void falcon_get_par(struct atafb_par *par) |
1464 | { | 1576 | { |
1465 | unsigned long addr; | 1577 | unsigned long addr; |
1466 | struct falcon_hw *hw = &par->hw.falcon; | 1578 | struct falcon_hw *hw = &par->hw.falcon; |
@@ -1492,12 +1604,12 @@ static void falcon_get_par( struct atafb_par *par ) | |||
1492 | par->screen_base = phys_to_virt(addr); | 1604 | par->screen_base = phys_to_virt(addr); |
1493 | 1605 | ||
1494 | /* derived parameters */ | 1606 | /* derived parameters */ |
1495 | hw->ste_mode = (hw->f_shift & 0x510)==0 && hw->st_shift==0x100; | 1607 | hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100; |
1496 | hw->mono = (hw->f_shift & 0x400) || | 1608 | hw->mono = (hw->f_shift & 0x400) || |
1497 | ((hw->f_shift & 0x510)==0 && hw->st_shift==0x200); | 1609 | ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200); |
1498 | } | 1610 | } |
1499 | 1611 | ||
1500 | static void falcon_set_par( struct atafb_par *par ) | 1612 | static void falcon_set_par(struct atafb_par *par) |
1501 | { | 1613 | { |
1502 | f_change_mode = 0; | 1614 | f_change_mode = 0; |
1503 | 1615 | ||
@@ -1519,8 +1631,7 @@ static void falcon_set_par( struct atafb_par *par ) | |||
1519 | f_change_mode = 1; | 1631 | f_change_mode = 1; |
1520 | } | 1632 | } |
1521 | 1633 | ||
1522 | 1634 | static irqreturn_t falcon_vbl_switcher(int irq, void *dummy) | |
1523 | static irqreturn_t falcon_vbl_switcher( int irq, void *dummy ) | ||
1524 | { | 1635 | { |
1525 | struct falcon_hw *hw = &f_new_mode; | 1636 | struct falcon_hw *hw = &f_new_mode; |
1526 | 1637 | ||
@@ -1529,11 +1640,10 @@ static irqreturn_t falcon_vbl_switcher( int irq, void *dummy ) | |||
1529 | 1640 | ||
1530 | if (hw->sync & 0x1) { | 1641 | if (hw->sync & 0x1) { |
1531 | /* Enable external pixelclock. This code only for ScreenWonder */ | 1642 | /* Enable external pixelclock. This code only for ScreenWonder */ |
1532 | *(volatile unsigned short*)0xffff9202 = 0xffbf; | 1643 | *(volatile unsigned short *)0xffff9202 = 0xffbf; |
1533 | } | 1644 | } else { |
1534 | else { | ||
1535 | /* Turn off external clocks. Read sets all output bits to 1. */ | 1645 | /* Turn off external clocks. Read sets all output bits to 1. */ |
1536 | *(volatile unsigned short*)0xffff9202; | 1646 | *(volatile unsigned short *)0xffff9202; |
1537 | } | 1647 | } |
1538 | shifter.syncmode = hw->sync; | 1648 | shifter.syncmode = hw->sync; |
1539 | 1649 | ||
@@ -1550,15 +1660,14 @@ static irqreturn_t falcon_vbl_switcher( int irq, void *dummy ) | |||
1550 | videl.vde = hw->vde; | 1660 | videl.vde = hw->vde; |
1551 | videl.vss = hw->vss; | 1661 | videl.vss = hw->vss; |
1552 | 1662 | ||
1553 | videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */ | 1663 | videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */ |
1554 | if (hw->ste_mode) { | 1664 | if (hw->ste_mode) { |
1555 | videl.st_shift = hw->st_shift; /* write enables STE palette */ | 1665 | videl.st_shift = hw->st_shift; /* write enables STE palette */ |
1556 | } | 1666 | } else { |
1557 | else { | ||
1558 | /* IMPORTANT: | 1667 | /* IMPORTANT: |
1559 | * set st_shift 0, so we can tell the screen-depth if f_shift==0. | 1668 | * set st_shift 0, so we can tell the screen-depth if f_shift == 0. |
1560 | * Writing 0 to f_shift enables 4 plane Falcon mode but | 1669 | * Writing 0 to f_shift enables 4 plane Falcon mode but |
1561 | * doesn't set st_shift. st_shift!=0 (!=4planes) is impossible | 1670 | * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible |
1562 | * with Falcon palette. | 1671 | * with Falcon palette. |
1563 | */ | 1672 | */ |
1564 | videl.st_shift = 0; | 1673 | videl.st_shift = 0; |
@@ -1580,12 +1689,13 @@ static irqreturn_t falcon_vbl_switcher( int irq, void *dummy ) | |||
1580 | return IRQ_HANDLED; | 1689 | return IRQ_HANDLED; |
1581 | } | 1690 | } |
1582 | 1691 | ||
1583 | 1692 | static int falcon_pan_display(struct fb_var_screeninfo *var, | |
1584 | static int falcon_pan_display( struct fb_var_screeninfo *var, | 1693 | struct fb_info *info) |
1585 | struct atafb_par *par ) | ||
1586 | { | 1694 | { |
1695 | struct atafb_par *par = (struct atafb_par *)info->par; | ||
1696 | |||
1587 | int xoffset; | 1697 | int xoffset; |
1588 | int bpp = fb_display[fb_info.currcon].var.bits_per_pixel; | 1698 | int bpp = info->var.bits_per_pixel; |
1589 | 1699 | ||
1590 | if (bpp == 1) | 1700 | if (bpp == 1) |
1591 | var->xoffset = up(var->xoffset, 32); | 1701 | var->xoffset = up(var->xoffset, 32); |
@@ -1596,45 +1706,24 @@ static int falcon_pan_display( struct fb_var_screeninfo *var, | |||
1596 | var->xoffset = up(var->xoffset, 2); | 1706 | var->xoffset = up(var->xoffset, 2); |
1597 | } | 1707 | } |
1598 | par->hw.falcon.line_offset = bpp * | 1708 | par->hw.falcon.line_offset = bpp * |
1599 | (fb_display[fb_info.currcon].var.xres_virtual - fb_display[fb_info.currcon].var.xres) / 16; | 1709 | (info->var.xres_virtual - info->var.xres) / 16; |
1600 | if (par->hw.falcon.xoffset) | 1710 | if (par->hw.falcon.xoffset) |
1601 | par->hw.falcon.line_offset -= bpp; | 1711 | par->hw.falcon.line_offset -= bpp; |
1602 | xoffset = var->xoffset - par->hw.falcon.xoffset; | 1712 | xoffset = var->xoffset - par->hw.falcon.xoffset; |
1603 | 1713 | ||
1604 | par->screen_base = screen_base + | 1714 | par->screen_base = screen_base + |
1605 | (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + xoffset) * bpp / 8; | 1715 | (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8; |
1606 | if (fbhw->set_screen_base) | 1716 | if (fbhw->set_screen_base) |
1607 | fbhw->set_screen_base (par->screen_base); | 1717 | fbhw->set_screen_base(par->screen_base); |
1608 | else | 1718 | else |
1609 | return -EINVAL; /* shouldn't happen */ | 1719 | return -EINVAL; /* shouldn't happen */ |
1610 | f_pan_display = 1; | 1720 | f_pan_display = 1; |
1611 | return 0; | 1721 | return 0; |
1612 | } | 1722 | } |
1613 | 1723 | ||
1614 | 1724 | static int falcon_setcolreg(unsigned int regno, unsigned int red, | |
1615 | static int falcon_getcolreg( unsigned regno, unsigned *red, | 1725 | unsigned int green, unsigned int blue, |
1616 | unsigned *green, unsigned *blue, | 1726 | unsigned int transp, struct fb_info *info) |
1617 | unsigned *transp, struct fb_info *info ) | ||
1618 | { unsigned long col; | ||
1619 | |||
1620 | if (regno > 255) | ||
1621 | return 1; | ||
1622 | /* This works in STE-mode (with 4bit/color) since f030_col-registers | ||
1623 | * hold up to 6bit/color. | ||
1624 | * Even with hicolor r/g/b=5/6/5 bit! | ||
1625 | */ | ||
1626 | col = f030_col[regno]; | ||
1627 | *red = (col >> 16) & 0xff00; | ||
1628 | *green = (col >> 8) & 0xff00; | ||
1629 | *blue = (col << 8) & 0xff00; | ||
1630 | *transp = 0; | ||
1631 | return 0; | ||
1632 | } | ||
1633 | |||
1634 | |||
1635 | static int falcon_setcolreg( unsigned regno, unsigned red, | ||
1636 | unsigned green, unsigned blue, | ||
1637 | unsigned transp, struct fb_info *info ) | ||
1638 | { | 1727 | { |
1639 | if (regno > 255) | 1728 | if (regno > 255) |
1640 | return 1; | 1729 | return 1; |
@@ -1655,13 +1744,12 @@ static int falcon_setcolreg( unsigned regno, unsigned red, | |||
1655 | return 0; | 1744 | return 0; |
1656 | } | 1745 | } |
1657 | 1746 | ||
1658 | 1747 | static int falcon_blank(int blank_mode) | |
1659 | static int falcon_blank( int blank_mode ) | ||
1660 | { | 1748 | { |
1661 | /* ++guenther: we can switch off graphics by changing VDB and VDE, | 1749 | /* ++guenther: we can switch off graphics by changing VDB and VDE, |
1662 | * so VIDEL doesn't hog the bus while saving. | 1750 | * so VIDEL doesn't hog the bus while saving. |
1663 | * (this may affect usleep()). | 1751 | * (this may affect usleep()). |
1664 | */ | 1752 | */ |
1665 | int vdb, vss, hbe, hss; | 1753 | int vdb, vss, hbe, hss; |
1666 | 1754 | ||
1667 | if (mon_type == F_MON_SM) /* this doesn't work on SM124 */ | 1755 | if (mon_type == F_MON_SM) /* this doesn't work on SM124 */ |
@@ -1694,14 +1782,13 @@ static int falcon_blank( int blank_mode ) | |||
1694 | return 0; | 1782 | return 0; |
1695 | } | 1783 | } |
1696 | 1784 | ||
1697 | 1785 | static int falcon_detect(void) | |
1698 | static int falcon_detect( void ) | ||
1699 | { | 1786 | { |
1700 | struct atafb_par par; | 1787 | struct atafb_par par; |
1701 | unsigned char fhw; | 1788 | unsigned char fhw; |
1702 | 1789 | ||
1703 | /* Determine connected monitor and set monitor parameters */ | 1790 | /* Determine connected monitor and set monitor parameters */ |
1704 | fhw = *(unsigned char*)0xffff8006; | 1791 | fhw = *(unsigned char *)0xffff8006; |
1705 | mon_type = fhw >> 6 & 0x3; | 1792 | mon_type = fhw >> 6 & 0x3; |
1706 | /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */ | 1793 | /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */ |
1707 | f030_bus_width = fhw << 6 & 0x80; | 1794 | f030_bus_width = fhw << 6 & 0x80; |
@@ -1715,7 +1802,7 @@ static int falcon_detect( void ) | |||
1715 | case F_MON_SC: | 1802 | case F_MON_SC: |
1716 | case F_MON_TV: | 1803 | case F_MON_TV: |
1717 | /* PAL...NTSC */ | 1804 | /* PAL...NTSC */ |
1718 | fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */ | 1805 | fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */ |
1719 | fb_info.monspecs.vfmax = 60; | 1806 | fb_info.monspecs.vfmax = 60; |
1720 | fb_info.monspecs.hfmin = 15620; | 1807 | fb_info.monspecs.hfmin = 15620; |
1721 | fb_info.monspecs.hfmax = 15755; | 1808 | fb_info.monspecs.hfmax = 15755; |
@@ -1740,13 +1827,12 @@ static int falcon_detect( void ) | |||
1740 | 1827 | ||
1741 | #ifdef ATAFB_STE | 1828 | #ifdef ATAFB_STE |
1742 | 1829 | ||
1743 | static int stste_encode_fix( struct fb_fix_screeninfo *fix, | 1830 | static int stste_encode_fix(struct fb_fix_screeninfo *fix, |
1744 | struct atafb_par *par ) | 1831 | struct atafb_par *par) |
1745 | |||
1746 | { | 1832 | { |
1747 | int mode; | 1833 | int mode; |
1748 | 1834 | ||
1749 | strcpy(fix->id,"Atari Builtin"); | 1835 | strcpy(fix->id, "Atari Builtin"); |
1750 | fix->smem_start = (unsigned long)real_screen_base; | 1836 | fix->smem_start = (unsigned long)real_screen_base; |
1751 | fix->smem_len = screen_len; | 1837 | fix->smem_len = screen_len; |
1752 | fix->type = FB_TYPE_INTERLEAVED_PLANES; | 1838 | fix->type = FB_TYPE_INTERLEAVED_PLANES; |
@@ -1771,43 +1857,40 @@ static int stste_encode_fix( struct fb_fix_screeninfo *fix, | |||
1771 | return 0; | 1857 | return 0; |
1772 | } | 1858 | } |
1773 | 1859 | ||
1774 | 1860 | static int stste_decode_var(struct fb_var_screeninfo *var, | |
1775 | static int stste_decode_var( struct fb_var_screeninfo *var, | 1861 | struct atafb_par *par) |
1776 | struct atafb_par *par ) | ||
1777 | { | 1862 | { |
1778 | int xres=var->xres; | 1863 | int xres = var->xres; |
1779 | int yres=var->yres; | 1864 | int yres = var->yres; |
1780 | int bpp=var->bits_per_pixel; | 1865 | int bpp = var->bits_per_pixel; |
1781 | int linelen; | 1866 | int linelen; |
1782 | int yres_virtual = var->yres_virtual; | 1867 | int yres_virtual = var->yres_virtual; |
1783 | 1868 | ||
1784 | if (mono_moni) { | 1869 | if (mono_moni) { |
1785 | if (bpp > 1 || xres > sttt_xres || yres > st_yres) | 1870 | if (bpp > 1 || xres > sttt_xres || yres > st_yres) |
1786 | return -EINVAL; | 1871 | return -EINVAL; |
1787 | par->hw.st.mode=ST_HIGH; | 1872 | par->hw.st.mode = ST_HIGH; |
1788 | xres=sttt_xres; | 1873 | xres = sttt_xres; |
1789 | yres=st_yres; | 1874 | yres = st_yres; |
1790 | bpp=1; | 1875 | bpp = 1; |
1791 | } else { | 1876 | } else { |
1792 | if (bpp > 4 || xres > sttt_xres || yres > st_yres) | 1877 | if (bpp > 4 || xres > sttt_xres || yres > st_yres) |
1793 | return -EINVAL; | 1878 | return -EINVAL; |
1794 | if (bpp > 2) { | 1879 | if (bpp > 2) { |
1795 | if (xres > sttt_xres/2 || yres > st_yres/2) | 1880 | if (xres > sttt_xres / 2 || yres > st_yres / 2) |
1796 | return -EINVAL; | 1881 | return -EINVAL; |
1797 | par->hw.st.mode=ST_LOW; | 1882 | par->hw.st.mode = ST_LOW; |
1798 | xres=sttt_xres/2; | 1883 | xres = sttt_xres / 2; |
1799 | yres=st_yres/2; | 1884 | yres = st_yres / 2; |
1800 | bpp=4; | 1885 | bpp = 4; |
1801 | } | 1886 | } else if (bpp > 1) { |
1802 | else if (bpp > 1) { | 1887 | if (xres > sttt_xres || yres > st_yres / 2) |
1803 | if (xres > sttt_xres || yres > st_yres/2) | ||
1804 | return -EINVAL; | 1888 | return -EINVAL; |
1805 | par->hw.st.mode=ST_MID; | 1889 | par->hw.st.mode = ST_MID; |
1806 | xres=sttt_xres; | 1890 | xres = sttt_xres; |
1807 | yres=st_yres/2; | 1891 | yres = st_yres / 2; |
1808 | bpp=2; | 1892 | bpp = 2; |
1809 | } | 1893 | } else |
1810 | else | ||
1811 | return -EINVAL; | 1894 | return -EINVAL; |
1812 | } | 1895 | } |
1813 | if (yres_virtual <= 0) | 1896 | if (yres_virtual <= 0) |
@@ -1815,10 +1898,10 @@ static int stste_decode_var( struct fb_var_screeninfo *var, | |||
1815 | else if (yres_virtual < yres) | 1898 | else if (yres_virtual < yres) |
1816 | yres_virtual = yres; | 1899 | yres_virtual = yres; |
1817 | if (var->sync & FB_SYNC_EXT) | 1900 | if (var->sync & FB_SYNC_EXT) |
1818 | par->hw.st.sync=(par->hw.st.sync & ~1) | 1; | 1901 | par->hw.st.sync = (par->hw.st.sync & ~1) | 1; |
1819 | else | 1902 | else |
1820 | par->hw.st.sync=(par->hw.st.sync & ~1); | 1903 | par->hw.st.sync = (par->hw.st.sync & ~1); |
1821 | linelen=xres*bpp/8; | 1904 | linelen = xres * bpp / 8; |
1822 | if (yres_virtual * linelen > screen_len && screen_len) | 1905 | if (yres_virtual * linelen > screen_len && screen_len) |
1823 | return -EINVAL; | 1906 | return -EINVAL; |
1824 | if (yres * linelen > screen_len && screen_len) | 1907 | if (yres * linelen > screen_len && screen_len) |
@@ -1826,93 +1909,91 @@ static int stste_decode_var( struct fb_var_screeninfo *var, | |||
1826 | if (var->yoffset + yres > yres_virtual && yres_virtual) | 1909 | if (var->yoffset + yres > yres_virtual && yres_virtual) |
1827 | return -EINVAL; | 1910 | return -EINVAL; |
1828 | par->yres_virtual = yres_virtual; | 1911 | par->yres_virtual = yres_virtual; |
1829 | par->screen_base=screen_base+ var->yoffset*linelen; | 1912 | par->screen_base = screen_base + var->yoffset * linelen; |
1830 | return 0; | 1913 | return 0; |
1831 | } | 1914 | } |
1832 | 1915 | ||
1833 | static int stste_encode_var( struct fb_var_screeninfo *var, | 1916 | static int stste_encode_var(struct fb_var_screeninfo *var, |
1834 | struct atafb_par *par ) | 1917 | struct atafb_par *par) |
1835 | { | 1918 | { |
1836 | int linelen; | 1919 | int linelen; |
1837 | memset(var, 0, sizeof(struct fb_var_screeninfo)); | 1920 | memset(var, 0, sizeof(struct fb_var_screeninfo)); |
1838 | var->red.offset=0; | 1921 | var->red.offset = 0; |
1839 | var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3; | 1922 | var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3; |
1840 | var->red.msb_right=0; | 1923 | var->red.msb_right = 0; |
1841 | var->grayscale=0; | 1924 | var->grayscale = 0; |
1842 | 1925 | ||
1843 | var->pixclock=31041; | 1926 | var->pixclock = 31041; |
1844 | var->left_margin=120; /* these are incorrect */ | 1927 | var->left_margin = 120; /* these are incorrect */ |
1845 | var->right_margin=100; | 1928 | var->right_margin = 100; |
1846 | var->upper_margin=8; | 1929 | var->upper_margin = 8; |
1847 | var->lower_margin=16; | 1930 | var->lower_margin = 16; |
1848 | var->hsync_len=140; | 1931 | var->hsync_len = 140; |
1849 | var->vsync_len=30; | 1932 | var->vsync_len = 30; |
1850 | 1933 | ||
1851 | var->height=-1; | 1934 | var->height = -1; |
1852 | var->width=-1; | 1935 | var->width = -1; |
1853 | 1936 | ||
1854 | if (!(par->hw.st.sync & 1)) | 1937 | if (!(par->hw.st.sync & 1)) |
1855 | var->sync=0; | 1938 | var->sync = 0; |
1856 | else | 1939 | else |
1857 | var->sync=FB_SYNC_EXT; | 1940 | var->sync = FB_SYNC_EXT; |
1858 | 1941 | ||
1859 | switch (par->hw.st.mode & 3) { | 1942 | switch (par->hw.st.mode & 3) { |
1860 | case ST_LOW: | 1943 | case ST_LOW: |
1861 | var->xres=sttt_xres/2; | 1944 | var->xres = sttt_xres / 2; |
1862 | var->yres=st_yres/2; | 1945 | var->yres = st_yres / 2; |
1863 | var->bits_per_pixel=4; | 1946 | var->bits_per_pixel = 4; |
1864 | break; | 1947 | break; |
1865 | case ST_MID: | 1948 | case ST_MID: |
1866 | var->xres=sttt_xres; | 1949 | var->xres = sttt_xres; |
1867 | var->yres=st_yres/2; | 1950 | var->yres = st_yres / 2; |
1868 | var->bits_per_pixel=2; | 1951 | var->bits_per_pixel = 2; |
1869 | break; | 1952 | break; |
1870 | case ST_HIGH: | 1953 | case ST_HIGH: |
1871 | var->xres=sttt_xres; | 1954 | var->xres = sttt_xres; |
1872 | var->yres=st_yres; | 1955 | var->yres = st_yres; |
1873 | var->bits_per_pixel=1; | 1956 | var->bits_per_pixel = 1; |
1874 | break; | 1957 | break; |
1875 | } | 1958 | } |
1876 | var->blue=var->green=var->red; | 1959 | var->blue = var->green = var->red; |
1877 | var->transp.offset=0; | 1960 | var->transp.offset = 0; |
1878 | var->transp.length=0; | 1961 | var->transp.length = 0; |
1879 | var->transp.msb_right=0; | 1962 | var->transp.msb_right = 0; |
1880 | var->xres_virtual=sttt_xres_virtual; | 1963 | var->xres_virtual = sttt_xres_virtual; |
1881 | linelen=var->xres_virtual * var->bits_per_pixel / 8; | 1964 | linelen = var->xres_virtual * var->bits_per_pixel / 8; |
1882 | ovsc_addlen=linelen*(sttt_yres_virtual - st_yres); | 1965 | ovsc_addlen = linelen * (sttt_yres_virtual - st_yres); |
1883 | 1966 | ||
1884 | if (! use_hwscroll) | 1967 | if (!use_hwscroll) |
1885 | var->yres_virtual=var->yres; | 1968 | var->yres_virtual = var->yres; |
1886 | else if (screen_len) { | 1969 | else if (screen_len) { |
1887 | if (par->yres_virtual) | 1970 | if (par->yres_virtual) |
1888 | var->yres_virtual = par->yres_virtual; | 1971 | var->yres_virtual = par->yres_virtual; |
1889 | else | 1972 | else |
1890 | /* yres_virtual==0 means use maximum */ | 1973 | /* yres_virtual == 0 means use maximum */ |
1891 | var->yres_virtual = screen_len / linelen; | 1974 | var->yres_virtual = screen_len / linelen; |
1892 | } | 1975 | } else { |
1893 | else { | ||
1894 | if (hwscroll < 0) | 1976 | if (hwscroll < 0) |
1895 | var->yres_virtual = 2 * var->yres; | 1977 | var->yres_virtual = 2 * var->yres; |
1896 | else | 1978 | else |
1897 | var->yres_virtual=var->yres+hwscroll * 16; | 1979 | var->yres_virtual = var->yres + hwscroll * 16; |
1898 | } | 1980 | } |
1899 | var->xoffset=0; | 1981 | var->xoffset = 0; |
1900 | if (screen_base) | 1982 | if (screen_base) |
1901 | var->yoffset=(par->screen_base - screen_base)/linelen; | 1983 | var->yoffset = (par->screen_base - screen_base) / linelen; |
1902 | else | 1984 | else |
1903 | var->yoffset=0; | 1985 | var->yoffset = 0; |
1904 | var->nonstd=0; | 1986 | var->nonstd = 0; |
1905 | var->activate=0; | 1987 | var->activate = 0; |
1906 | var->vmode=FB_VMODE_NONINTERLACED; | 1988 | var->vmode = FB_VMODE_NONINTERLACED; |
1907 | return 0; | 1989 | return 0; |
1908 | } | 1990 | } |
1909 | 1991 | ||
1910 | 1992 | static void stste_get_par(struct atafb_par *par) | |
1911 | static void stste_get_par( struct atafb_par *par ) | ||
1912 | { | 1993 | { |
1913 | unsigned long addr; | 1994 | unsigned long addr; |
1914 | par->hw.st.mode=shifter_tt.st_shiftmode; | 1995 | par->hw.st.mode = shifter_tt.st_shiftmode; |
1915 | par->hw.st.sync=shifter.syncmode; | 1996 | par->hw.st.sync = shifter.syncmode; |
1916 | addr = ((shifter.bas_hi & 0xff) << 16) | | 1997 | addr = ((shifter.bas_hi & 0xff) << 16) | |
1917 | ((shifter.bas_md & 0xff) << 8); | 1998 | ((shifter.bas_md & 0xff) << 8); |
1918 | if (ATARIHW_PRESENT(EXTD_SHIFTER)) | 1999 | if (ATARIHW_PRESENT(EXTD_SHIFTER)) |
@@ -1920,55 +2001,18 @@ static void stste_get_par( struct atafb_par *par ) | |||
1920 | par->screen_base = phys_to_virt(addr); | 2001 | par->screen_base = phys_to_virt(addr); |
1921 | } | 2002 | } |
1922 | 2003 | ||
1923 | static void stste_set_par( struct atafb_par *par ) | 2004 | static void stste_set_par(struct atafb_par *par) |
1924 | { | 2005 | { |
1925 | shifter_tt.st_shiftmode=par->hw.st.mode; | 2006 | shifter_tt.st_shiftmode = par->hw.st.mode; |
1926 | shifter.syncmode=par->hw.st.sync; | 2007 | shifter.syncmode = par->hw.st.sync; |
1927 | /* only set screen_base if really necessary */ | 2008 | /* only set screen_base if really necessary */ |
1928 | if (current_par.screen_base != par->screen_base) | 2009 | if (current_par.screen_base != par->screen_base) |
1929 | fbhw->set_screen_base(par->screen_base); | 2010 | fbhw->set_screen_base(par->screen_base); |
1930 | } | 2011 | } |
1931 | 2012 | ||
1932 | 2013 | static int stste_setcolreg(unsigned int regno, unsigned int red, | |
1933 | static int stste_getcolreg(unsigned regno, unsigned *red, | 2014 | unsigned int green, unsigned int blue, |
1934 | unsigned *green, unsigned *blue, | 2015 | unsigned int transp, struct fb_info *info) |
1935 | unsigned *transp, struct fb_info *info) | ||
1936 | { | ||
1937 | unsigned col, t; | ||
1938 | |||
1939 | if (regno > 15) | ||
1940 | return 1; | ||
1941 | col = shifter_tt.color_reg[regno]; | ||
1942 | if (ATARIHW_PRESENT(EXTD_SHIFTER)) { | ||
1943 | t = ((col >> 7) & 0xe) | ((col >> 11) & 1); | ||
1944 | t |= t << 4; | ||
1945 | *red = t | (t << 8); | ||
1946 | t = ((col >> 3) & 0xe) | ((col >> 7) & 1); | ||
1947 | t |= t << 4; | ||
1948 | *green = t | (t << 8); | ||
1949 | t = ((col << 1) & 0xe) | ((col >> 3) & 1); | ||
1950 | t |= t << 4; | ||
1951 | *blue = t | (t << 8); | ||
1952 | } | ||
1953 | else { | ||
1954 | t = (col >> 7) & 0xe; | ||
1955 | t |= t << 4; | ||
1956 | *red = t | (t << 8); | ||
1957 | t = (col >> 3) & 0xe; | ||
1958 | t |= t << 4; | ||
1959 | *green = t | (t << 8); | ||
1960 | t = (col << 1) & 0xe; | ||
1961 | t |= t << 4; | ||
1962 | *blue = t | (t << 8); | ||
1963 | } | ||
1964 | *transp = 0; | ||
1965 | return 0; | ||
1966 | } | ||
1967 | |||
1968 | |||
1969 | static int stste_setcolreg(unsigned regno, unsigned red, | ||
1970 | unsigned green, unsigned blue, | ||
1971 | unsigned transp, struct fb_info *info) | ||
1972 | { | 2016 | { |
1973 | if (regno > 15) | 2017 | if (regno > 15) |
1974 | return 1; | 2018 | return 1; |
@@ -1988,10 +2032,9 @@ static int stste_setcolreg(unsigned regno, unsigned red, | |||
1988 | return 0; | 2032 | return 0; |
1989 | } | 2033 | } |
1990 | 2034 | ||
1991 | 2035 | static int stste_detect(void) | |
1992 | static int stste_detect( void ) | 2036 | { |
1993 | 2037 | struct atafb_par par; | |
1994 | { struct atafb_par par; | ||
1995 | 2038 | ||
1996 | /* Determine the connected monitor: The DMA sound must be | 2039 | /* Determine the connected monitor: The DMA sound must be |
1997 | * disabled before reading the MFP GPIP, because the Sound | 2040 | * disabled before reading the MFP GPIP, because the Sound |
@@ -1999,7 +2042,7 @@ static int stste_detect( void ) | |||
1999 | */ | 2042 | */ |
2000 | if (ATARIHW_PRESENT(PCM_8BIT)) { | 2043 | if (ATARIHW_PRESENT(PCM_8BIT)) { |
2001 | tt_dmasnd.ctrl = DMASND_CTRL_OFF; | 2044 | tt_dmasnd.ctrl = DMASND_CTRL_OFF; |
2002 | udelay(20); /* wait a while for things to settle down */ | 2045 | udelay(20); /* wait a while for things to settle down */ |
2003 | } | 2046 | } |
2004 | mono_moni = (mfp.par_dt_reg & 0x80) == 0; | 2047 | mono_moni = (mfp.par_dt_reg & 0x80) == 0; |
2005 | 2048 | ||
@@ -2014,12 +2057,12 @@ static int stste_detect( void ) | |||
2014 | static void stste_set_screen_base(void *s_base) | 2057 | static void stste_set_screen_base(void *s_base) |
2015 | { | 2058 | { |
2016 | unsigned long addr; | 2059 | unsigned long addr; |
2017 | addr= virt_to_phys(s_base); | 2060 | addr = virt_to_phys(s_base); |
2018 | /* Setup Screen Memory */ | 2061 | /* Setup Screen Memory */ |
2019 | shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16); | 2062 | shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16); |
2020 | shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8); | 2063 | shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8); |
2021 | if (ATARIHW_PRESENT(EXTD_SHIFTER)) | 2064 | if (ATARIHW_PRESENT(EXTD_SHIFTER)) |
2022 | shifter.bas_lo=(unsigned char) (addr & 0x0000ff); | 2065 | shifter.bas_lo = (unsigned char)(addr & 0x0000ff); |
2023 | } | 2066 | } |
2024 | 2067 | ||
2025 | #endif /* ATAFB_STE */ | 2068 | #endif /* ATAFB_STE */ |
@@ -2045,51 +2088,49 @@ static void stste_set_screen_base(void *s_base) | |||
2045 | /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */ | 2088 | /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */ |
2046 | static void st_ovsc_switch(void) | 2089 | static void st_ovsc_switch(void) |
2047 | { | 2090 | { |
2048 | unsigned long flags; | 2091 | unsigned long flags; |
2049 | register unsigned char old, new; | 2092 | register unsigned char old, new; |
2050 | 2093 | ||
2051 | if (!(atari_switches & ATARI_SWITCH_OVSC_MASK)) | 2094 | if (!(atari_switches & ATARI_SWITCH_OVSC_MASK)) |
2052 | return; | 2095 | return; |
2053 | local_irq_save(flags); | 2096 | local_irq_save(flags); |
2054 | 2097 | ||
2055 | mfp.tim_ct_b = 0x10; | 2098 | mfp.tim_ct_b = 0x10; |
2056 | mfp.active_edge |= 8; | 2099 | mfp.active_edge |= 8; |
2057 | mfp.tim_ct_b = 0; | 2100 | mfp.tim_ct_b = 0; |
2058 | mfp.tim_dt_b = 0xf0; | 2101 | mfp.tim_dt_b = 0xf0; |
2059 | mfp.tim_ct_b = 8; | 2102 | mfp.tim_ct_b = 8; |
2060 | while (mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */ | 2103 | while (mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */ |
2061 | ; | 2104 | ; |
2062 | new = mfp.tim_dt_b; | ||
2063 | do { | ||
2064 | udelay(LINE_DELAY); | ||
2065 | old = new; | ||
2066 | new = mfp.tim_dt_b; | 2105 | new = mfp.tim_dt_b; |
2067 | } while (old != new); | 2106 | do { |
2068 | mfp.tim_ct_b = 0x10; | 2107 | udelay(LINE_DELAY); |
2069 | udelay(SYNC_DELAY); | 2108 | old = new; |
2070 | 2109 | new = mfp.tim_dt_b; | |
2071 | if (atari_switches & ATARI_SWITCH_OVSC_IKBD) | 2110 | } while (old != new); |
2072 | acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE; | 2111 | mfp.tim_ct_b = 0x10; |
2073 | if (atari_switches & ATARI_SWITCH_OVSC_MIDI) | 2112 | udelay(SYNC_DELAY); |
2074 | acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID; | 2113 | |
2075 | if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) { | 2114 | if (atari_switches & ATARI_SWITCH_OVSC_IKBD) |
2076 | sound_ym.rd_data_reg_sel = 14; | 2115 | acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE; |
2077 | sound_ym.wd_data = sound_ym.rd_data_reg_sel | | 2116 | if (atari_switches & ATARI_SWITCH_OVSC_MIDI) |
2078 | ((atari_switches&ATARI_SWITCH_OVSC_SND6) ? 0x40:0) | | 2117 | acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID; |
2079 | ((atari_switches&ATARI_SWITCH_OVSC_SND7) ? 0x80:0); | 2118 | if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) { |
2080 | } | 2119 | sound_ym.rd_data_reg_sel = 14; |
2081 | local_irq_restore(flags); | 2120 | sound_ym.wd_data = sound_ym.rd_data_reg_sel | |
2121 | ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) | | ||
2122 | ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0); | ||
2123 | } | ||
2124 | local_irq_restore(flags); | ||
2082 | } | 2125 | } |
2083 | 2126 | ||
2084 | /* ------------------- External Video ---------------------- */ | 2127 | /* ------------------- External Video ---------------------- */ |
2085 | 2128 | ||
2086 | #ifdef ATAFB_EXT | 2129 | #ifdef ATAFB_EXT |
2087 | 2130 | ||
2088 | static int ext_encode_fix( struct fb_fix_screeninfo *fix, | 2131 | static int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par) |
2089 | struct atafb_par *par ) | ||
2090 | |||
2091 | { | 2132 | { |
2092 | strcpy(fix->id,"Unknown Extern"); | 2133 | strcpy(fix->id, "Unknown Extern"); |
2093 | fix->smem_start = (unsigned long)external_addr; | 2134 | fix->smem_start = (unsigned long)external_addr; |
2094 | fix->smem_len = PAGE_ALIGN(external_len); | 2135 | fix->smem_len = PAGE_ALIGN(external_len); |
2095 | if (external_depth == 1) { | 2136 | if (external_depth == 1) { |
@@ -2099,31 +2140,29 @@ static int ext_encode_fix( struct fb_fix_screeninfo *fix, | |||
2099 | fix->visual = | 2140 | fix->visual = |
2100 | (external_pmode == FB_TYPE_INTERLEAVED_PLANES || | 2141 | (external_pmode == FB_TYPE_INTERLEAVED_PLANES || |
2101 | external_pmode == FB_TYPE_PACKED_PIXELS) ? | 2142 | external_pmode == FB_TYPE_PACKED_PIXELS) ? |
2102 | FB_VISUAL_MONO10 : | 2143 | FB_VISUAL_MONO10 : FB_VISUAL_MONO01; |
2103 | FB_VISUAL_MONO01; | 2144 | } else { |
2104 | } | ||
2105 | else { | ||
2106 | /* Use STATIC if we don't know how to access color registers */ | 2145 | /* Use STATIC if we don't know how to access color registers */ |
2107 | int visual = external_vgaiobase ? | 2146 | int visual = external_vgaiobase ? |
2108 | FB_VISUAL_PSEUDOCOLOR : | 2147 | FB_VISUAL_PSEUDOCOLOR : |
2109 | FB_VISUAL_STATIC_PSEUDOCOLOR; | 2148 | FB_VISUAL_STATIC_PSEUDOCOLOR; |
2110 | switch (external_pmode) { | 2149 | switch (external_pmode) { |
2111 | case -1: /* truecolor */ | 2150 | case -1: /* truecolor */ |
2112 | fix->type=FB_TYPE_PACKED_PIXELS; | 2151 | fix->type = FB_TYPE_PACKED_PIXELS; |
2113 | fix->visual=FB_VISUAL_TRUECOLOR; | 2152 | fix->visual = FB_VISUAL_TRUECOLOR; |
2114 | break; | 2153 | break; |
2115 | case FB_TYPE_PACKED_PIXELS: | 2154 | case FB_TYPE_PACKED_PIXELS: |
2116 | fix->type=FB_TYPE_PACKED_PIXELS; | 2155 | fix->type = FB_TYPE_PACKED_PIXELS; |
2117 | fix->visual=visual; | 2156 | fix->visual = visual; |
2118 | break; | 2157 | break; |
2119 | case FB_TYPE_PLANES: | 2158 | case FB_TYPE_PLANES: |
2120 | fix->type=FB_TYPE_PLANES; | 2159 | fix->type = FB_TYPE_PLANES; |
2121 | fix->visual=visual; | 2160 | fix->visual = visual; |
2122 | break; | 2161 | break; |
2123 | case FB_TYPE_INTERLEAVED_PLANES: | 2162 | case FB_TYPE_INTERLEAVED_PLANES: |
2124 | fix->type=FB_TYPE_INTERLEAVED_PLANES; | 2163 | fix->type = FB_TYPE_INTERLEAVED_PLANES; |
2125 | fix->type_aux=2; | 2164 | fix->type_aux = 2; |
2126 | fix->visual=visual; | 2165 | fix->visual = visual; |
2127 | break; | 2166 | break; |
2128 | } | 2167 | } |
2129 | } | 2168 | } |
@@ -2134,137 +2173,112 @@ static int ext_encode_fix( struct fb_fix_screeninfo *fix, | |||
2134 | return 0; | 2173 | return 0; |
2135 | } | 2174 | } |
2136 | 2175 | ||
2137 | 2176 | static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par) | |
2138 | static int ext_decode_var( struct fb_var_screeninfo *var, | ||
2139 | struct atafb_par *par ) | ||
2140 | { | 2177 | { |
2141 | struct fb_var_screeninfo *myvar = &atafb_predefined[0]; | 2178 | struct fb_var_screeninfo *myvar = &atafb_predefined[0]; |
2142 | 2179 | ||
2143 | if (var->bits_per_pixel > myvar->bits_per_pixel || | 2180 | if (var->bits_per_pixel > myvar->bits_per_pixel || |
2144 | var->xres > myvar->xres || | 2181 | var->xres > myvar->xres || |
2145 | var->xres_virtual > myvar->xres_virtual || | 2182 | var->xres_virtual > myvar->xres_virtual || |
2146 | var->yres > myvar->yres || | 2183 | var->yres > myvar->yres || |
2147 | var->xoffset > 0 || | 2184 | var->xoffset > 0 || |
2148 | var->yoffset > 0) | 2185 | var->yoffset > 0) |
2149 | return -EINVAL; | 2186 | return -EINVAL; |
2150 | return 0; | 2187 | return 0; |
2151 | } | 2188 | } |
2152 | 2189 | ||
2153 | 2190 | static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par) | |
2154 | static int ext_encode_var( struct fb_var_screeninfo *var, | ||
2155 | struct atafb_par *par ) | ||
2156 | { | 2191 | { |
2157 | memset(var, 0, sizeof(struct fb_var_screeninfo)); | 2192 | memset(var, 0, sizeof(struct fb_var_screeninfo)); |
2158 | var->red.offset=0; | 2193 | var->red.offset = 0; |
2159 | var->red.length=(external_pmode == -1) ? external_depth/3 : | 2194 | var->red.length = (external_pmode == -1) ? external_depth / 3 : |
2160 | (external_vgaiobase ? external_bitspercol : 0); | 2195 | (external_vgaiobase ? external_bitspercol : 0); |
2161 | var->red.msb_right=0; | 2196 | var->red.msb_right = 0; |
2162 | var->grayscale=0; | 2197 | var->grayscale = 0; |
2163 | 2198 | ||
2164 | var->pixclock=31041; | 2199 | var->pixclock = 31041; |
2165 | var->left_margin=120; /* these are surely incorrect */ | 2200 | var->left_margin = 120; /* these are surely incorrect */ |
2166 | var->right_margin=100; | 2201 | var->right_margin = 100; |
2167 | var->upper_margin=8; | 2202 | var->upper_margin = 8; |
2168 | var->lower_margin=16; | 2203 | var->lower_margin = 16; |
2169 | var->hsync_len=140; | 2204 | var->hsync_len = 140; |
2170 | var->vsync_len=30; | 2205 | var->vsync_len = 30; |
2171 | 2206 | ||
2172 | var->height=-1; | 2207 | var->height = -1; |
2173 | var->width=-1; | 2208 | var->width = -1; |
2174 | 2209 | ||
2175 | var->sync=0; | 2210 | var->sync = 0; |
2176 | 2211 | ||
2177 | var->xres = external_xres; | 2212 | var->xres = external_xres; |
2178 | var->yres = external_yres; | 2213 | var->yres = external_yres; |
2179 | var->xres_virtual = external_xres_virtual; | 2214 | var->xres_virtual = external_xres_virtual; |
2180 | var->bits_per_pixel = external_depth; | 2215 | var->bits_per_pixel = external_depth; |
2181 | 2216 | ||
2182 | var->blue=var->green=var->red; | 2217 | var->blue = var->green = var->red; |
2183 | var->transp.offset=0; | 2218 | var->transp.offset = 0; |
2184 | var->transp.length=0; | 2219 | var->transp.length = 0; |
2185 | var->transp.msb_right=0; | 2220 | var->transp.msb_right = 0; |
2186 | var->yres_virtual=var->yres; | 2221 | var->yres_virtual = var->yres; |
2187 | var->xoffset=0; | 2222 | var->xoffset = 0; |
2188 | var->yoffset=0; | 2223 | var->yoffset = 0; |
2189 | var->nonstd=0; | 2224 | var->nonstd = 0; |
2190 | var->activate=0; | 2225 | var->activate = 0; |
2191 | var->vmode=FB_VMODE_NONINTERLACED; | 2226 | var->vmode = FB_VMODE_NONINTERLACED; |
2192 | return 0; | 2227 | return 0; |
2193 | } | 2228 | } |
2194 | 2229 | ||
2195 | 2230 | static void ext_get_par(struct atafb_par *par) | |
2196 | static void ext_get_par( struct atafb_par *par ) | ||
2197 | { | 2231 | { |
2198 | par->screen_base = external_addr; | 2232 | par->screen_base = external_addr; |
2199 | } | 2233 | } |
2200 | 2234 | ||
2201 | static void ext_set_par( struct atafb_par *par ) | 2235 | static void ext_set_par(struct atafb_par *par) |
2202 | { | 2236 | { |
2203 | } | 2237 | } |
2204 | 2238 | ||
2205 | #define OUTB(port,val) \ | 2239 | #define OUTB(port,val) \ |
2206 | *((unsigned volatile char *) ((port)+external_vgaiobase))=(val) | 2240 | *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val) |
2207 | #define INB(port) \ | 2241 | #define INB(port) \ |
2208 | (*((unsigned volatile char *) ((port)+external_vgaiobase))) | 2242 | (*((unsigned volatile char *) ((port)+external_vgaiobase))) |
2209 | #define DACDelay \ | 2243 | #define DACDelay \ |
2210 | do { \ | 2244 | do { \ |
2211 | unsigned char tmp=INB(0x3da); \ | 2245 | unsigned char tmp = INB(0x3da); \ |
2212 | tmp=INB(0x3da); \ | 2246 | tmp = INB(0x3da); \ |
2213 | } while (0) | 2247 | } while (0) |
2214 | 2248 | ||
2215 | static int ext_getcolreg( unsigned regno, unsigned *red, | 2249 | static int ext_setcolreg(unsigned int regno, unsigned int red, |
2216 | unsigned *green, unsigned *blue, | 2250 | unsigned int green, unsigned int blue, |
2217 | unsigned *transp, struct fb_info *info ) | 2251 | unsigned int transp, struct fb_info *info) |
2218 | { | 2252 | { |
2219 | if (! external_vgaiobase) | 2253 | unsigned char colmask = (1 << external_bitspercol) - 1; |
2254 | |||
2255 | if (!external_vgaiobase) | ||
2220 | return 1; | 2256 | return 1; |
2221 | 2257 | ||
2222 | *red = ext_color[regno].red; | 2258 | switch (external_card_type) { |
2223 | *green = ext_color[regno].green; | 2259 | case IS_VGA: |
2224 | *blue = ext_color[regno].blue; | 2260 | OUTB(0x3c8, regno); |
2225 | *transp=0; | 2261 | DACDelay; |
2226 | return 0; | 2262 | OUTB(0x3c9, red & colmask); |
2227 | } | 2263 | DACDelay; |
2228 | 2264 | OUTB(0x3c9, green & colmask); | |
2229 | static int ext_setcolreg( unsigned regno, unsigned red, | 2265 | DACDelay; |
2230 | unsigned green, unsigned blue, | 2266 | OUTB(0x3c9, blue & colmask); |
2231 | unsigned transp, struct fb_info *info ) | 2267 | DACDelay; |
2268 | return 0; | ||
2232 | 2269 | ||
2233 | { unsigned char colmask = (1 << external_bitspercol) - 1; | 2270 | case IS_MV300: |
2271 | OUTB((MV300_reg[regno] << 2) + 1, red); | ||
2272 | OUTB((MV300_reg[regno] << 2) + 1, green); | ||
2273 | OUTB((MV300_reg[regno] << 2) + 1, blue); | ||
2274 | return 0; | ||
2234 | 2275 | ||
2235 | if (! external_vgaiobase) | 2276 | default: |
2236 | return 1; | 2277 | return 1; |
2237 | 2278 | } | |
2238 | ext_color[regno].red = red; | ||
2239 | ext_color[regno].green = green; | ||
2240 | ext_color[regno].blue = blue; | ||
2241 | |||
2242 | switch (external_card_type) { | ||
2243 | case IS_VGA: | ||
2244 | OUTB(0x3c8, regno); | ||
2245 | DACDelay; | ||
2246 | OUTB(0x3c9, red & colmask); | ||
2247 | DACDelay; | ||
2248 | OUTB(0x3c9, green & colmask); | ||
2249 | DACDelay; | ||
2250 | OUTB(0x3c9, blue & colmask); | ||
2251 | DACDelay; | ||
2252 | return 0; | ||
2253 | |||
2254 | case IS_MV300: | ||
2255 | OUTB((MV300_reg[regno] << 2)+1, red); | ||
2256 | OUTB((MV300_reg[regno] << 2)+1, green); | ||
2257 | OUTB((MV300_reg[regno] << 2)+1, blue); | ||
2258 | return 0; | ||
2259 | |||
2260 | default: | ||
2261 | return 1; | ||
2262 | } | ||
2263 | } | 2279 | } |
2264 | |||
2265 | |||
2266 | static int ext_detect( void ) | ||
2267 | 2280 | ||
2281 | static int ext_detect(void) | ||
2268 | { | 2282 | { |
2269 | struct fb_var_screeninfo *myvar = &atafb_predefined[0]; | 2283 | struct fb_var_screeninfo *myvar = &atafb_predefined[0]; |
2270 | struct atafb_par dummy_par; | 2284 | struct atafb_par dummy_par; |
@@ -2284,213 +2298,182 @@ static int ext_detect( void ) | |||
2284 | static void set_screen_base(void *s_base) | 2298 | static void set_screen_base(void *s_base) |
2285 | { | 2299 | { |
2286 | unsigned long addr; | 2300 | unsigned long addr; |
2287 | addr= virt_to_phys(s_base); | 2301 | |
2302 | addr = virt_to_phys(s_base); | ||
2288 | /* Setup Screen Memory */ | 2303 | /* Setup Screen Memory */ |
2289 | shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16); | 2304 | shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16); |
2290 | shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8); | 2305 | shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8); |
2291 | shifter.bas_lo=(unsigned char) (addr & 0x0000ff); | 2306 | shifter.bas_lo = (unsigned char)(addr & 0x0000ff); |
2292 | } | 2307 | } |
2293 | 2308 | ||
2294 | 2309 | static int pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |
2295 | static int pan_display( struct fb_var_screeninfo *var, | ||
2296 | struct atafb_par *par ) | ||
2297 | { | 2310 | { |
2311 | struct atafb_par *par = (struct atafb_par *)info->par; | ||
2312 | |||
2298 | if (!fbhw->set_screen_base || | 2313 | if (!fbhw->set_screen_base || |
2299 | (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset)) | 2314 | (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset)) |
2300 | return -EINVAL; | 2315 | return -EINVAL; |
2301 | var->xoffset = up(var->xoffset, 16); | 2316 | var->xoffset = up(var->xoffset, 16); |
2302 | par->screen_base = screen_base + | 2317 | par->screen_base = screen_base + |
2303 | (var->yoffset * fb_display[fb_info.currcon].var.xres_virtual + var->xoffset) | 2318 | (var->yoffset * info->var.xres_virtual + var->xoffset) |
2304 | * fb_display[fb_info.currcon].var.bits_per_pixel / 8; | 2319 | * info->var.bits_per_pixel / 8; |
2305 | fbhw->set_screen_base (par->screen_base); | 2320 | fbhw->set_screen_base(par->screen_base); |
2306 | return 0; | 2321 | return 0; |
2307 | } | 2322 | } |
2308 | 2323 | ||
2309 | |||
2310 | /* ------------ Interfaces to hardware functions ------------ */ | 2324 | /* ------------ Interfaces to hardware functions ------------ */ |
2311 | 2325 | ||
2312 | |||
2313 | #ifdef ATAFB_TT | 2326 | #ifdef ATAFB_TT |
2314 | static struct fb_hwswitch tt_switch = { | 2327 | static struct fb_hwswitch tt_switch = { |
2315 | tt_detect, tt_encode_fix, tt_decode_var, tt_encode_var, | 2328 | .detect = tt_detect, |
2316 | tt_get_par, tt_set_par, tt_getcolreg, | 2329 | .encode_fix = tt_encode_fix, |
2317 | set_screen_base, NULL, pan_display | 2330 | .decode_var = tt_decode_var, |
2331 | .encode_var = tt_encode_var, | ||
2332 | .get_par = tt_get_par, | ||
2333 | .set_par = tt_set_par, | ||
2334 | .set_screen_base = set_screen_base, | ||
2335 | .pan_display = pan_display, | ||
2318 | }; | 2336 | }; |
2319 | #endif | 2337 | #endif |
2320 | 2338 | ||
2321 | #ifdef ATAFB_FALCON | 2339 | #ifdef ATAFB_FALCON |
2322 | static struct fb_hwswitch falcon_switch = { | 2340 | static struct fb_hwswitch falcon_switch = { |
2323 | falcon_detect, falcon_encode_fix, falcon_decode_var, falcon_encode_var, | 2341 | .detect = falcon_detect, |
2324 | falcon_get_par, falcon_set_par, falcon_getcolreg, | 2342 | .encode_fix = falcon_encode_fix, |
2325 | set_screen_base, falcon_blank, falcon_pan_display | 2343 | .decode_var = falcon_decode_var, |
2344 | .encode_var = falcon_encode_var, | ||
2345 | .get_par = falcon_get_par, | ||
2346 | .set_par = falcon_set_par, | ||
2347 | .set_screen_base = set_screen_base, | ||
2348 | .blank = falcon_blank, | ||
2349 | .pan_display = falcon_pan_display, | ||
2326 | }; | 2350 | }; |
2327 | #endif | 2351 | #endif |
2328 | 2352 | ||
2329 | #ifdef ATAFB_STE | 2353 | #ifdef ATAFB_STE |
2330 | static struct fb_hwswitch st_switch = { | 2354 | static struct fb_hwswitch st_switch = { |
2331 | stste_detect, stste_encode_fix, stste_decode_var, stste_encode_var, | 2355 | .detect = stste_detect, |
2332 | stste_get_par, stste_set_par, stste_getcolreg, | 2356 | .encode_fix = stste_encode_fix, |
2333 | stste_set_screen_base, NULL, pan_display | 2357 | .decode_var = stste_decode_var, |
2358 | .encode_var = stste_encode_var, | ||
2359 | .get_par = stste_get_par, | ||
2360 | .set_par = stste_set_par, | ||
2361 | .set_screen_base = stste_set_screen_base, | ||
2362 | .pan_display = pan_display | ||
2334 | }; | 2363 | }; |
2335 | #endif | 2364 | #endif |
2336 | 2365 | ||
2337 | #ifdef ATAFB_EXT | 2366 | #ifdef ATAFB_EXT |
2338 | static struct fb_hwswitch ext_switch = { | 2367 | static struct fb_hwswitch ext_switch = { |
2339 | ext_detect, ext_encode_fix, ext_decode_var, ext_encode_var, | 2368 | .detect = ext_detect, |
2340 | ext_get_par, ext_set_par, ext_getcolreg, NULL, NULL, NULL | 2369 | .encode_fix = ext_encode_fix, |
2370 | .decode_var = ext_decode_var, | ||
2371 | .encode_var = ext_encode_var, | ||
2372 | .get_par = ext_get_par, | ||
2373 | .set_par = ext_set_par, | ||
2341 | }; | 2374 | }; |
2342 | #endif | 2375 | #endif |
2343 | 2376 | ||
2344 | 2377 | static void ata_get_par(struct atafb_par *par) | |
2345 | |||
2346 | static void atafb_get_par( struct atafb_par *par ) | ||
2347 | { | 2378 | { |
2348 | if (current_par_valid) { | 2379 | if (current_par_valid) |
2349 | *par=current_par; | 2380 | *par = current_par; |
2350 | } | ||
2351 | else | 2381 | else |
2352 | fbhw->get_par(par); | 2382 | fbhw->get_par(par); |
2353 | } | 2383 | } |
2354 | 2384 | ||
2355 | 2385 | static void ata_set_par(struct atafb_par *par) | |
2356 | static void atafb_set_par( struct atafb_par *par ) | ||
2357 | { | 2386 | { |
2358 | fbhw->set_par(par); | 2387 | fbhw->set_par(par); |
2359 | current_par=*par; | 2388 | current_par = *par; |
2360 | current_par_valid=1; | 2389 | current_par_valid = 1; |
2361 | } | 2390 | } |
2362 | 2391 | ||
2363 | 2392 | ||
2364 | |||
2365 | /* =========================================================== */ | 2393 | /* =========================================================== */ |
2366 | /* ============== Hardware Independent Functions ============= */ | 2394 | /* ============== Hardware Independent Functions ============= */ |
2367 | /* =========================================================== */ | 2395 | /* =========================================================== */ |
2368 | 2396 | ||
2369 | |||
2370 | /* used for hardware scrolling */ | 2397 | /* used for hardware scrolling */ |
2371 | 2398 | ||
2372 | static int | 2399 | static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) |
2373 | fb_update_var(int con, struct fb_info *info) | ||
2374 | { | ||
2375 | int off=fb_display[con].var.yoffset*fb_display[con].var.xres_virtual* | ||
2376 | fb_display[con].var.bits_per_pixel>>3; | ||
2377 | |||
2378 | current_par.screen_base=screen_base + off; | ||
2379 | |||
2380 | if (fbhw->set_screen_base) | ||
2381 | fbhw->set_screen_base(current_par.screen_base); | ||
2382 | return 0; | ||
2383 | } | ||
2384 | |||
2385 | static int | ||
2386 | do_fb_set_var(struct fb_var_screeninfo *var, int isactive) | ||
2387 | { | 2400 | { |
2388 | int err,activate; | 2401 | int err, activate; |
2389 | struct atafb_par par; | 2402 | struct atafb_par par; |
2390 | if ((err=fbhw->decode_var(var, &par))) | 2403 | |
2404 | err = fbhw->decode_var(var, &par); | ||
2405 | if (err) | ||
2391 | return err; | 2406 | return err; |
2392 | activate=var->activate; | 2407 | activate = var->activate; |
2393 | if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) | 2408 | if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) |
2394 | atafb_set_par(&par); | 2409 | ata_set_par(&par); |
2395 | fbhw->encode_var(var, &par); | 2410 | fbhw->encode_var(var, &par); |
2396 | var->activate=activate; | 2411 | var->activate = activate; |
2397 | return 0; | 2412 | return 0; |
2398 | } | 2413 | } |
2399 | 2414 | ||
2400 | static int | 2415 | static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) |
2401 | atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) | ||
2402 | { | 2416 | { |
2403 | struct atafb_par par; | 2417 | struct atafb_par par; |
2404 | if (con == -1) | 2418 | int err; |
2405 | atafb_get_par(&par); | 2419 | // Get fix directly (case con == -1 before)?? |
2406 | else { | 2420 | err = fbhw->decode_var(&info->var, &par); |
2407 | int err; | 2421 | if (err) |
2408 | if ((err=fbhw->decode_var(&fb_display[con].var,&par))) | 2422 | return err; |
2409 | return err; | ||
2410 | } | ||
2411 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | 2423 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); |
2412 | return fbhw->encode_fix(fix, &par); | 2424 | return fbhw->encode_fix(fix, &par); |
2413 | } | 2425 | } |
2414 | 2426 | ||
2415 | static int | 2427 | static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info) |
2416 | atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) | ||
2417 | { | 2428 | { |
2418 | struct atafb_par par; | 2429 | struct atafb_par par; |
2419 | if (con == -1) { | 2430 | |
2420 | atafb_get_par(&par); | 2431 | ata_get_par(&par); |
2421 | fbhw->encode_var(var, &par); | 2432 | fbhw->encode_var(var, &par); |
2422 | } | 2433 | |
2423 | else | ||
2424 | *var=fb_display[con].var; | ||
2425 | return 0; | 2434 | return 0; |
2426 | } | 2435 | } |
2427 | 2436 | ||
2428 | static void | 2437 | // No longer called by fbcon! |
2429 | atafb_set_disp(int con, struct fb_info *info) | 2438 | // Still called by set_var internally |
2439 | |||
2440 | static void atafb_set_disp(struct fb_info *info) | ||
2430 | { | 2441 | { |
2431 | struct fb_fix_screeninfo fix; | 2442 | atafb_get_var(&info->var, info); |
2432 | struct fb_var_screeninfo var; | 2443 | atafb_get_fix(&info->fix, info); |
2433 | struct display *display; | ||
2434 | 2444 | ||
2435 | if (con >= 0) | 2445 | info->screen_base = (void *)info->fix.smem_start; |
2436 | display = &fb_display[con]; | 2446 | |
2437 | else | 2447 | switch (info->fix.type) { |
2438 | display = &disp; /* used during initialization */ | 2448 | case FB_TYPE_INTERLEAVED_PLANES: |
2439 | 2449 | switch (info->var.bits_per_pixel) { | |
2440 | atafb_get_fix(&fix, con, info); | 2450 | case 2: |
2441 | atafb_get_var(&var, con, info); | 2451 | // display->dispsw = &fbcon_iplan2p2; |
2442 | if (con == -1) | ||
2443 | con=0; | ||
2444 | info->screen_base = (void *)fix.smem_start; | ||
2445 | display->visual = fix.visual; | ||
2446 | display->type = fix.type; | ||
2447 | display->type_aux = fix.type_aux; | ||
2448 | display->ypanstep = fix.ypanstep; | ||
2449 | display->ywrapstep = fix.ywrapstep; | ||
2450 | display->line_length = fix.line_length; | ||
2451 | if (fix.visual != FB_VISUAL_PSEUDOCOLOR && | ||
2452 | fix.visual != FB_VISUAL_DIRECTCOLOR) | ||
2453 | display->can_soft_blank = 0; | ||
2454 | else | ||
2455 | display->can_soft_blank = 1; | ||
2456 | display->inverse = | ||
2457 | (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse); | ||
2458 | switch (fix.type) { | ||
2459 | case FB_TYPE_INTERLEAVED_PLANES: | ||
2460 | switch (var.bits_per_pixel) { | ||
2461 | #ifdef FBCON_HAS_IPLAN2P2 | ||
2462 | case 2: | ||
2463 | display->dispsw = &fbcon_iplan2p2; | ||
2464 | break; | 2452 | break; |
2465 | #endif | 2453 | case 4: |
2466 | #ifdef FBCON_HAS_IPLAN2P4 | 2454 | // display->dispsw = &fbcon_iplan2p4; |
2467 | case 4: | ||
2468 | display->dispsw = &fbcon_iplan2p4; | ||
2469 | break; | 2455 | break; |
2470 | #endif | 2456 | case 8: |
2471 | #ifdef FBCON_HAS_IPLAN2P8 | 2457 | // display->dispsw = &fbcon_iplan2p8; |
2472 | case 8: | ||
2473 | display->dispsw = &fbcon_iplan2p8; | ||
2474 | break; | 2458 | break; |
2475 | #endif | ||
2476 | } | 2459 | } |
2477 | break; | 2460 | break; |
2478 | case FB_TYPE_PACKED_PIXELS: | 2461 | case FB_TYPE_PACKED_PIXELS: |
2479 | switch (var.bits_per_pixel) { | 2462 | switch (info->var.bits_per_pixel) { |
2480 | #ifdef FBCON_HAS_MFB | 2463 | #ifdef FBCON_HAS_MFB |
2481 | case 1: | 2464 | case 1: |
2482 | display->dispsw = &fbcon_mfb; | 2465 | // display->dispsw = &fbcon_mfb; |
2483 | break; | 2466 | break; |
2484 | #endif | 2467 | #endif |
2485 | #ifdef FBCON_HAS_CFB8 | 2468 | #ifdef FBCON_HAS_CFB8 |
2486 | case 8: | 2469 | case 8: |
2487 | display->dispsw = &fbcon_cfb8; | 2470 | // display->dispsw = &fbcon_cfb8; |
2488 | break; | 2471 | break; |
2489 | #endif | 2472 | #endif |
2490 | #ifdef FBCON_HAS_CFB16 | 2473 | #ifdef FBCON_HAS_CFB16 |
2491 | case 16: | 2474 | case 16: |
2492 | display->dispsw = &fbcon_cfb16; | 2475 | // display->dispsw = &fbcon_cfb16; |
2493 | display->dispsw_data = fbcon_cfb16_cmap; | 2476 | // display->dispsw_data = fbcon_cfb16_cmap; |
2494 | break; | 2477 | break; |
2495 | #endif | 2478 | #endif |
2496 | } | 2479 | } |
@@ -2498,74 +2481,203 @@ atafb_set_disp(int con, struct fb_info *info) | |||
2498 | } | 2481 | } |
2499 | } | 2482 | } |
2500 | 2483 | ||
2484 | static int atafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | ||
2485 | u_int transp, struct fb_info *info) | ||
2486 | { | ||
2487 | red >>= 8; | ||
2488 | green >>= 8; | ||
2489 | blue >>= 8; | ||
2490 | |||
2491 | return info->fbops->fb_setcolreg(regno, red, green, blue, transp, info); | ||
2492 | } | ||
2493 | |||
2501 | static int | 2494 | static int |
2502 | atafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) | 2495 | atafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) |
2503 | { | 2496 | { |
2504 | int err,oldxres,oldyres,oldbpp,oldxres_virtual, | 2497 | int xoffset = var->xoffset; |
2505 | oldyres_virtual,oldyoffset; | 2498 | int yoffset = var->yoffset; |
2506 | if ((err=do_fb_set_var(var, con==info->currcon))) | 2499 | int err; |
2507 | return err; | 2500 | |
2508 | if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { | 2501 | if (var->vmode & FB_VMODE_YWRAP) { |
2509 | oldxres=fb_display[con].var.xres; | 2502 | if (yoffset < 0 || yoffset >= info->var.yres_virtual || xoffset) |
2510 | oldyres=fb_display[con].var.yres; | 2503 | return -EINVAL; |
2511 | oldxres_virtual=fb_display[con].var.xres_virtual; | 2504 | } else { |
2512 | oldyres_virtual=fb_display[con].var.yres_virtual; | 2505 | if (xoffset + info->var.xres > info->var.xres_virtual || |
2513 | oldbpp=fb_display[con].var.bits_per_pixel; | 2506 | yoffset + info->var.yres > info->var.yres_virtual) |
2514 | oldyoffset=fb_display[con].var.yoffset; | 2507 | return -EINVAL; |
2515 | fb_display[con].var=*var; | ||
2516 | if (oldxres != var->xres || oldyres != var->yres | ||
2517 | || oldxres_virtual != var->xres_virtual | ||
2518 | || oldyres_virtual != var->yres_virtual | ||
2519 | || oldbpp != var->bits_per_pixel | ||
2520 | || oldyoffset != var->yoffset) { | ||
2521 | atafb_set_disp(con, info); | ||
2522 | (*fb_info.changevar)(con); | ||
2523 | fb_alloc_cmap(&fb_display[con].cmap, 0, 0); | ||
2524 | do_install_cmap(con, info); | ||
2525 | } | ||
2526 | } | 2508 | } |
2527 | var->activate=0; | 2509 | |
2510 | if (fbhw->pan_display) { | ||
2511 | err = fbhw->pan_display(var, info); | ||
2512 | if (err) | ||
2513 | return err; | ||
2514 | } else | ||
2515 | return -EINVAL; | ||
2516 | |||
2517 | info->var.xoffset = xoffset; | ||
2518 | info->var.yoffset = yoffset; | ||
2519 | |||
2520 | if (var->vmode & FB_VMODE_YWRAP) | ||
2521 | info->var.vmode |= FB_VMODE_YWRAP; | ||
2522 | else | ||
2523 | info->var.vmode &= ~FB_VMODE_YWRAP; | ||
2524 | |||
2528 | return 0; | 2525 | return 0; |
2529 | } | 2526 | } |
2530 | 2527 | ||
2528 | /* | ||
2529 | * generic drawing routines; imageblit needs updating for image depth > 1 | ||
2530 | */ | ||
2531 | 2531 | ||
2532 | #if BITS_PER_LONG == 32 | ||
2533 | #define BYTES_PER_LONG 4 | ||
2534 | #define SHIFT_PER_LONG 5 | ||
2535 | #elif BITS_PER_LONG == 64 | ||
2536 | #define BYTES_PER_LONG 8 | ||
2537 | #define SHIFT_PER_LONG 6 | ||
2538 | #else | ||
2539 | #define Please update me | ||
2540 | #endif | ||
2532 | 2541 | ||
2533 | static int | 2542 | |
2534 | atafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) | 2543 | static void atafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) |
2535 | { | 2544 | { |
2536 | if (con == info->currcon) /* current console ? */ | 2545 | struct atafb_par *par = (struct atafb_par *)info->par; |
2537 | return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info); | 2546 | int x2, y2; |
2547 | u32 width, height; | ||
2548 | |||
2549 | if (!rect->width || !rect->height) | ||
2550 | return; | ||
2551 | |||
2552 | /* | ||
2553 | * We could use hardware clipping but on many cards you get around | ||
2554 | * hardware clipping by writing to framebuffer directly. | ||
2555 | * */ | ||
2556 | x2 = rect->dx + rect->width; | ||
2557 | y2 = rect->dy + rect->height; | ||
2558 | x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; | ||
2559 | y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; | ||
2560 | width = x2 - rect->dx; | ||
2561 | height = y2 - rect->dy; | ||
2562 | |||
2563 | if (info->var.bits_per_pixel == 1) | ||
2564 | atafb_mfb_fillrect(info, par->next_line, rect->color, | ||
2565 | rect->dy, rect->dx, height, width); | ||
2566 | else if (info->var.bits_per_pixel == 2) | ||
2567 | atafb_iplan2p2_fillrect(info, par->next_line, rect->color, | ||
2568 | rect->dy, rect->dx, height, width); | ||
2569 | else if (info->var.bits_per_pixel == 4) | ||
2570 | atafb_iplan2p4_fillrect(info, par->next_line, rect->color, | ||
2571 | rect->dy, rect->dx, height, width); | ||
2538 | else | 2572 | else |
2539 | if (fb_display[con].cmap.len) /* non default colormap ? */ | 2573 | atafb_iplan2p8_fillrect(info, par->next_line, rect->color, |
2540 | fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); | 2574 | rect->dy, rect->dx, height, width); |
2541 | else | 2575 | |
2542 | fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), | 2576 | return; |
2543 | cmap, kspc ? 0 : 2); | ||
2544 | return 0; | ||
2545 | } | 2577 | } |
2546 | 2578 | ||
2547 | static int | 2579 | static void atafb_copyarea(struct fb_info *info, const struct fb_copyarea *area) |
2548 | atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info) | ||
2549 | { | 2580 | { |
2550 | int xoffset = var->xoffset; | 2581 | struct atafb_par *par = (struct atafb_par *)info->par; |
2551 | int yoffset = var->yoffset; | 2582 | int x2, y2; |
2552 | int err; | 2583 | u32 dx, dy, sx, sy, width, height; |
2584 | int rev_copy = 0; | ||
2585 | |||
2586 | /* clip the destination */ | ||
2587 | x2 = area->dx + area->width; | ||
2588 | y2 = area->dy + area->height; | ||
2589 | dx = area->dx > 0 ? area->dx : 0; | ||
2590 | dy = area->dy > 0 ? area->dy : 0; | ||
2591 | x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; | ||
2592 | y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; | ||
2593 | width = x2 - dx; | ||
2594 | height = y2 - dy; | ||
2595 | |||
2596 | /* update sx,sy */ | ||
2597 | sx = area->sx + (dx - area->dx); | ||
2598 | sy = area->sy + (dy - area->dy); | ||
2599 | |||
2600 | /* the source must be completely inside the virtual screen */ | ||
2601 | if (sx < 0 || sy < 0 || (sx + width) > info->var.xres_virtual || | ||
2602 | (sy + height) > info->var.yres_virtual) | ||
2603 | return; | ||
2553 | 2604 | ||
2554 | if ( xoffset < 0 || xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual | 2605 | if (dy > sy || (dy == sy && dx > sx)) { |
2555 | || yoffset < 0 || yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual) | 2606 | dy += height; |
2556 | return -EINVAL; | 2607 | sy += height; |
2608 | rev_copy = 1; | ||
2609 | } | ||
2610 | |||
2611 | if (info->var.bits_per_pixel == 1) | ||
2612 | atafb_mfb_copyarea(info, par->next_line, sy, sx, dy, dx, height, width); | ||
2613 | else if (info->var.bits_per_pixel == 2) | ||
2614 | atafb_iplan2p2_copyarea(info, par->next_line, sy, sx, dy, dx, height, width); | ||
2615 | else if (info->var.bits_per_pixel == 4) | ||
2616 | atafb_iplan2p4_copyarea(info, par->next_line, sy, sx, dy, dx, height, width); | ||
2617 | else | ||
2618 | atafb_iplan2p8_copyarea(info, par->next_line, sy, sx, dy, dx, height, width); | ||
2557 | 2619 | ||
2558 | if (con == info->currcon) { | 2620 | return; |
2559 | if (fbhw->pan_display) { | 2621 | } |
2560 | if ((err = fbhw->pan_display(var, ¤t_par))) | 2622 | |
2561 | return err; | 2623 | static void atafb_imageblit(struct fb_info *info, const struct fb_image *image) |
2624 | { | ||
2625 | struct atafb_par *par = (struct atafb_par *)info->par; | ||
2626 | int x2, y2; | ||
2627 | unsigned long *dst; | ||
2628 | int dst_idx; | ||
2629 | const char *src; | ||
2630 | u32 dx, dy, width, height, pitch; | ||
2631 | |||
2632 | /* | ||
2633 | * We could use hardware clipping but on many cards you get around | ||
2634 | * hardware clipping by writing to framebuffer directly like we are | ||
2635 | * doing here. | ||
2636 | */ | ||
2637 | x2 = image->dx + image->width; | ||
2638 | y2 = image->dy + image->height; | ||
2639 | dx = image->dx; | ||
2640 | dy = image->dy; | ||
2641 | x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; | ||
2642 | y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; | ||
2643 | width = x2 - dx; | ||
2644 | height = y2 - dy; | ||
2645 | |||
2646 | if (image->depth == 1) { | ||
2647 | // used for font data | ||
2648 | dst = (unsigned long *) | ||
2649 | ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1)); | ||
2650 | dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8; | ||
2651 | dst_idx += dy * par->next_line * 8 + dx; | ||
2652 | src = image->data; | ||
2653 | pitch = (image->width + 7) / 8; | ||
2654 | while (height--) { | ||
2655 | |||
2656 | if (info->var.bits_per_pixel == 1) | ||
2657 | atafb_mfb_linefill(info, par->next_line, | ||
2658 | dy, dx, width, src, | ||
2659 | image->bg_color, image->fg_color); | ||
2660 | else if (info->var.bits_per_pixel == 2) | ||
2661 | atafb_iplan2p2_linefill(info, par->next_line, | ||
2662 | dy, dx, width, src, | ||
2663 | image->bg_color, image->fg_color); | ||
2664 | else if (info->var.bits_per_pixel == 4) | ||
2665 | atafb_iplan2p4_linefill(info, par->next_line, | ||
2666 | dy, dx, width, src, | ||
2667 | image->bg_color, image->fg_color); | ||
2668 | else | ||
2669 | atafb_iplan2p8_linefill(info, par->next_line, | ||
2670 | dy, dx, width, src, | ||
2671 | image->bg_color, image->fg_color); | ||
2672 | dy++; | ||
2673 | src += pitch; | ||
2562 | } | 2674 | } |
2563 | else | 2675 | } else { |
2564 | return -EINVAL; | 2676 | // only used for logo; broken |
2677 | c2p(info->screen_base, image->data, dx, dy, width, height, | ||
2678 | par->next_line, par->next_plane, image->width, | ||
2679 | info->var.bits_per_pixel); | ||
2565 | } | 2680 | } |
2566 | fb_display[con].var.xoffset = var->xoffset; | ||
2567 | fb_display[con].var.yoffset = var->yoffset; | ||
2568 | return 0; | ||
2569 | } | 2681 | } |
2570 | 2682 | ||
2571 | static int | 2683 | static int |
@@ -2584,7 +2696,7 @@ atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) | |||
2584 | if (copy_from_user((void *)¤t_par, (void *)arg, | 2696 | if (copy_from_user((void *)¤t_par, (void *)arg, |
2585 | sizeof(struct atafb_par))) | 2697 | sizeof(struct atafb_par))) |
2586 | return -EFAULT; | 2698 | return -EFAULT; |
2587 | atafb_set_par(¤t_par); | 2699 | ata_set_par(¤t_par); |
2588 | return 0; | 2700 | return 0; |
2589 | #endif | 2701 | #endif |
2590 | } | 2702 | } |
@@ -2598,42 +2710,82 @@ atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) | |||
2598 | * 3 = suspend hsync | 2710 | * 3 = suspend hsync |
2599 | * 4 = off | 2711 | * 4 = off |
2600 | */ | 2712 | */ |
2601 | static int | 2713 | static int atafb_blank(int blank, struct fb_info *info) |
2602 | atafb_blank(int blank, struct fb_info *info) | ||
2603 | { | 2714 | { |
2604 | unsigned short black[16]; | 2715 | unsigned short black[16]; |
2605 | struct fb_cmap cmap; | 2716 | struct fb_cmap cmap; |
2606 | if (fbhw->blank && !fbhw->blank(blank)) | 2717 | if (fbhw->blank && !fbhw->blank(blank)) |
2607 | return 1; | 2718 | return 1; |
2608 | if (blank) { | 2719 | if (blank) { |
2609 | memset(black, 0, 16*sizeof(unsigned short)); | 2720 | memset(black, 0, 16 * sizeof(unsigned short)); |
2610 | cmap.red=black; | 2721 | cmap.red = black; |
2611 | cmap.green=black; | 2722 | cmap.green = black; |
2612 | cmap.blue=black; | 2723 | cmap.blue = black; |
2613 | cmap.transp=NULL; | 2724 | cmap.transp = NULL; |
2614 | cmap.start=0; | 2725 | cmap.start = 0; |
2615 | cmap.len=16; | 2726 | cmap.len = 16; |
2616 | fb_set_cmap(&cmap, 1, info); | 2727 | fb_set_cmap(&cmap, info); |
2617 | } | 2728 | } |
2729 | #if 0 | ||
2618 | else | 2730 | else |
2619 | do_install_cmap(info->currcon, info); | 2731 | do_install_cmap(info); |
2732 | #endif | ||
2733 | return 0; | ||
2734 | } | ||
2735 | |||
2736 | /* | ||
2737 | * New fbcon interface ... | ||
2738 | */ | ||
2739 | |||
2740 | /* check var by decoding var into hw par, rounding if necessary, | ||
2741 | * then encoding hw par back into new, validated var */ | ||
2742 | static int atafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | ||
2743 | { | ||
2744 | int err; | ||
2745 | struct atafb_par par; | ||
2746 | |||
2747 | /* Validate wanted screen parameters */ | ||
2748 | // if ((err = ata_decode_var(var, &par))) | ||
2749 | err = fbhw->decode_var(var, &par); | ||
2750 | if (err) | ||
2751 | return err; | ||
2752 | |||
2753 | /* Encode (possibly rounded) screen parameters */ | ||
2754 | fbhw->encode_var(var, &par); | ||
2755 | return 0; | ||
2756 | } | ||
2757 | |||
2758 | /* actually set hw par by decoding var, then setting hardware from | ||
2759 | * hw par just decoded */ | ||
2760 | static int atafb_set_par(struct fb_info *info) | ||
2761 | { | ||
2762 | struct atafb_par *par = (struct atafb_par *)info->par; | ||
2763 | |||
2764 | /* Decode wanted screen parameters */ | ||
2765 | fbhw->decode_var(&info->var, par); | ||
2766 | fbhw->encode_fix(&info->fix, par); | ||
2767 | |||
2768 | /* Set new videomode */ | ||
2769 | ata_set_par(par); | ||
2770 | |||
2620 | return 0; | 2771 | return 0; |
2621 | } | 2772 | } |
2622 | 2773 | ||
2774 | |||
2623 | static struct fb_ops atafb_ops = { | 2775 | static struct fb_ops atafb_ops = { |
2624 | .owner = THIS_MODULE, | 2776 | .owner = THIS_MODULE, |
2625 | .fb_get_fix = atafb_get_fix, | 2777 | .fb_check_var = atafb_check_var, |
2626 | .fb_get_var = atafb_get_var, | 2778 | .fb_set_par = atafb_set_par, |
2627 | .fb_set_var = atafb_set_var, | 2779 | .fb_setcolreg = atafb_setcolreg, |
2628 | .fb_get_cmap = atafb_get_cmap, | ||
2629 | .fb_set_cmap = gen_set_cmap, | ||
2630 | .fb_pan_display =atafb_pan_display, | ||
2631 | .fb_blank = atafb_blank, | 2780 | .fb_blank = atafb_blank, |
2781 | .fb_pan_display = atafb_pan_display, | ||
2782 | .fb_fillrect = atafb_fillrect, | ||
2783 | .fb_copyarea = atafb_copyarea, | ||
2784 | .fb_imageblit = atafb_imageblit, | ||
2632 | .fb_ioctl = atafb_ioctl, | 2785 | .fb_ioctl = atafb_ioctl, |
2633 | }; | 2786 | }; |
2634 | 2787 | ||
2635 | static void | 2788 | static void check_default_par(int detected_mode) |
2636 | check_default_par( int detected_mode ) | ||
2637 | { | 2789 | { |
2638 | char default_name[10]; | 2790 | char default_name[10]; |
2639 | int i; | 2791 | int i; |
@@ -2642,199 +2794,41 @@ check_default_par( int detected_mode ) | |||
2642 | 2794 | ||
2643 | /* First try the user supplied mode */ | 2795 | /* First try the user supplied mode */ |
2644 | if (default_par) { | 2796 | if (default_par) { |
2645 | var=atafb_predefined[default_par-1]; | 2797 | var = atafb_predefined[default_par - 1]; |
2646 | var.activate = FB_ACTIVATE_TEST; | 2798 | var.activate = FB_ACTIVATE_TEST; |
2647 | if (do_fb_set_var(&var,1)) | 2799 | if (do_fb_set_var(&var, 1)) |
2648 | default_par=0; /* failed */ | 2800 | default_par = 0; /* failed */ |
2649 | } | 2801 | } |
2650 | /* Next is the autodetected one */ | 2802 | /* Next is the autodetected one */ |
2651 | if (! default_par) { | 2803 | if (!default_par) { |
2652 | var=atafb_predefined[detected_mode-1]; /* autodetect */ | 2804 | var = atafb_predefined[detected_mode - 1]; /* autodetect */ |
2653 | var.activate = FB_ACTIVATE_TEST; | 2805 | var.activate = FB_ACTIVATE_TEST; |
2654 | if (!do_fb_set_var(&var,1)) | 2806 | if (!do_fb_set_var(&var, 1)) |
2655 | default_par=detected_mode; | 2807 | default_par = detected_mode; |
2656 | } | 2808 | } |
2657 | /* If that also failed, try some default modes... */ | 2809 | /* If that also failed, try some default modes... */ |
2658 | if (! default_par) { | 2810 | if (!default_par) { |
2659 | /* try default1, default2... */ | 2811 | /* try default1, default2... */ |
2660 | for (i=1 ; i < 10 ; i++) { | 2812 | for (i = 1; i < 10; i++) { |
2661 | sprintf(default_name,"default%d",i); | 2813 | sprintf(default_name,"default%d", i); |
2662 | default_par=get_video_mode(default_name); | 2814 | default_par = get_video_mode(default_name); |
2663 | if (! default_par) | 2815 | if (!default_par) |
2664 | panic("can't set default video mode"); | 2816 | panic("can't set default video mode"); |
2665 | var=atafb_predefined[default_par-1]; | 2817 | var = atafb_predefined[default_par - 1]; |
2666 | var.activate = FB_ACTIVATE_TEST; | 2818 | var.activate = FB_ACTIVATE_TEST; |
2667 | if (! do_fb_set_var(&var,1)) | 2819 | if (!do_fb_set_var(&var,1)) |
2668 | break; /* ok */ | 2820 | break; /* ok */ |
2669 | } | 2821 | } |
2670 | } | 2822 | } |
2671 | min_mem=var.xres_virtual * var.yres_virtual * var.bits_per_pixel/8; | 2823 | min_mem = var.xres_virtual * var.yres_virtual * var.bits_per_pixel / 8; |
2672 | if (default_mem_req < min_mem) | 2824 | if (default_mem_req < min_mem) |
2673 | default_mem_req=min_mem; | 2825 | default_mem_req = min_mem; |
2674 | } | ||
2675 | |||
2676 | static int | ||
2677 | atafb_switch(int con, struct fb_info *info) | ||
2678 | { | ||
2679 | /* Do we have to save the colormap ? */ | ||
2680 | if (fb_display[info->currcon].cmap.len) | ||
2681 | fb_get_cmap(&fb_display[info->currcon].cmap, 1, fbhw->getcolreg, | ||
2682 | info); | ||
2683 | do_fb_set_var(&fb_display[con].var,1); | ||
2684 | info->currcon=con; | ||
2685 | /* Install new colormap */ | ||
2686 | do_install_cmap(con, info); | ||
2687 | return 0; | ||
2688 | } | ||
2689 | |||
2690 | int __init atafb_init(void) | ||
2691 | { | ||
2692 | int pad; | ||
2693 | int detected_mode; | ||
2694 | unsigned long mem_req; | ||
2695 | |||
2696 | if (!MACH_IS_ATARI) | ||
2697 | return -ENXIO; | ||
2698 | |||
2699 | do { | ||
2700 | #ifdef ATAFB_EXT | ||
2701 | if (external_addr) { | ||
2702 | fbhw = &ext_switch; | ||
2703 | atafb_ops.fb_setcolreg = &ext_setcolreg; | ||
2704 | break; | ||
2705 | } | ||
2706 | #endif | ||
2707 | #ifdef ATAFB_TT | ||
2708 | if (ATARIHW_PRESENT(TT_SHIFTER)) { | ||
2709 | fbhw = &tt_switch; | ||
2710 | atafb_ops.fb_setcolreg = &tt_setcolreg; | ||
2711 | break; | ||
2712 | } | ||
2713 | #endif | ||
2714 | #ifdef ATAFB_FALCON | ||
2715 | if (ATARIHW_PRESENT(VIDEL_SHIFTER)) { | ||
2716 | fbhw = &falcon_switch; | ||
2717 | atafb_ops.fb_setcolreg = &falcon_setcolreg; | ||
2718 | request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO, | ||
2719 | "framebuffer/modeswitch", falcon_vbl_switcher); | ||
2720 | break; | ||
2721 | } | ||
2722 | #endif | ||
2723 | #ifdef ATAFB_STE | ||
2724 | if (ATARIHW_PRESENT(STND_SHIFTER) || | ||
2725 | ATARIHW_PRESENT(EXTD_SHIFTER)) { | ||
2726 | fbhw = &st_switch; | ||
2727 | atafb_ops.fb_setcolreg = &stste_setcolreg; | ||
2728 | break; | ||
2729 | } | ||
2730 | fbhw = &st_switch; | ||
2731 | atafb_ops.fb_setcolreg = &stste_setcolreg; | ||
2732 | printk("Cannot determine video hardware; defaulting to ST(e)\n"); | ||
2733 | #else /* ATAFB_STE */ | ||
2734 | /* no default driver included */ | ||
2735 | /* Nobody will ever see this message :-) */ | ||
2736 | panic("Cannot initialize video hardware"); | ||
2737 | #endif | ||
2738 | } while (0); | ||
2739 | |||
2740 | /* Multisync monitor capabilities */ | ||
2741 | /* Atari-TOS defaults if no boot option present */ | ||
2742 | if (fb_info.monspecs.hfmin == 0) { | ||
2743 | fb_info.monspecs.hfmin = 31000; | ||
2744 | fb_info.monspecs.hfmax = 32000; | ||
2745 | fb_info.monspecs.vfmin = 58; | ||
2746 | fb_info.monspecs.vfmax = 62; | ||
2747 | } | ||
2748 | |||
2749 | detected_mode = fbhw->detect(); | ||
2750 | check_default_par(detected_mode); | ||
2751 | #ifdef ATAFB_EXT | ||
2752 | if (!external_addr) { | ||
2753 | #endif /* ATAFB_EXT */ | ||
2754 | mem_req = default_mem_req + ovsc_offset + ovsc_addlen; | ||
2755 | mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE; | ||
2756 | screen_base = atari_stram_alloc(mem_req, "atafb"); | ||
2757 | if (!screen_base) | ||
2758 | panic("Cannot allocate screen memory"); | ||
2759 | memset(screen_base, 0, mem_req); | ||
2760 | pad = -(unsigned long)screen_base & (PAGE_SIZE-1); | ||
2761 | screen_base+=pad; | ||
2762 | real_screen_base=screen_base+ovsc_offset; | ||
2763 | screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK; | ||
2764 | st_ovsc_switch(); | ||
2765 | if (CPU_IS_040_OR_060) { | ||
2766 | /* On a '040+, the cache mode of video RAM must be set to | ||
2767 | * write-through also for internal video hardware! */ | ||
2768 | cache_push(virt_to_phys(screen_base), screen_len); | ||
2769 | kernel_set_cachemode(screen_base, screen_len, | ||
2770 | IOMAP_WRITETHROUGH); | ||
2771 | } | ||
2772 | #ifdef ATAFB_EXT | ||
2773 | } | ||
2774 | else { | ||
2775 | /* Map the video memory (physical address given) to somewhere | ||
2776 | * in the kernel address space. | ||
2777 | */ | ||
2778 | external_addr = | ||
2779 | ioremap_writethrough((unsigned long)external_addr, | ||
2780 | external_len); | ||
2781 | if (external_vgaiobase) | ||
2782 | external_vgaiobase = | ||
2783 | (unsigned long)ioremap(external_vgaiobase, 0x10000); | ||
2784 | screen_base = | ||
2785 | real_screen_base = external_addr; | ||
2786 | screen_len = external_len & PAGE_MASK; | ||
2787 | memset (screen_base, 0, external_len); | ||
2788 | } | ||
2789 | #endif /* ATAFB_EXT */ | ||
2790 | |||
2791 | strcpy(fb_info.modename, "Atari Builtin "); | ||
2792 | fb_info.changevar = NULL; | ||
2793 | fb_info.fbops = &atafb_ops; | ||
2794 | fb_info.disp = &disp; | ||
2795 | fb_info.currcon = -1; | ||
2796 | fb_info.switch_con = &atafb_switch; | ||
2797 | fb_info.updatevar = &fb_update_var; | ||
2798 | fb_info.flags = FBINFO_FLAG_DEFAULT; | ||
2799 | do_fb_set_var(&atafb_predefined[default_par-1], 1); | ||
2800 | strcat(fb_info.modename, fb_var_names[default_par-1][0]); | ||
2801 | |||
2802 | atafb_get_var(&disp.var, -1, &fb_info); | ||
2803 | atafb_set_disp(-1, &fb_info); | ||
2804 | do_install_cmap(0, &fb_info); | ||
2805 | |||
2806 | if (register_framebuffer(&fb_info) < 0) { | ||
2807 | #ifdef ATAFB_EXT | ||
2808 | if (external_addr) { | ||
2809 | iounmap(external_addr); | ||
2810 | external_addr = NULL; | ||
2811 | } | ||
2812 | if (external_vgaiobase) { | ||
2813 | iounmap((void*)external_vgaiobase); | ||
2814 | external_vgaiobase = 0; | ||
2815 | } | ||
2816 | #endif | ||
2817 | return -EINVAL; | ||
2818 | } | ||
2819 | |||
2820 | printk("Determined %dx%d, depth %d\n", | ||
2821 | disp.var.xres, disp.var.yres, disp.var.bits_per_pixel); | ||
2822 | if ((disp.var.xres != disp.var.xres_virtual) || | ||
2823 | (disp.var.yres != disp.var.yres_virtual)) | ||
2824 | printk(" virtual %dx%d\n", | ||
2825 | disp.var.xres_virtual, disp.var.yres_virtual); | ||
2826 | printk("fb%d: %s frame buffer device, using %dK of video memory\n", | ||
2827 | fb_info.node, fb_info.modename, screen_len>>10); | ||
2828 | |||
2829 | /* TODO: This driver cannot be unloaded yet */ | ||
2830 | return 0; | ||
2831 | } | 2826 | } |
2832 | 2827 | ||
2833 | |||
2834 | #ifdef ATAFB_EXT | 2828 | #ifdef ATAFB_EXT |
2835 | static void __init atafb_setup_ext(char *spec) | 2829 | static void __init atafb_setup_ext(char *spec) |
2836 | { | 2830 | { |
2837 | int xres, xres_virtual, yres, depth, planes; | 2831 | int xres, xres_virtual, yres, depth, planes; |
2838 | unsigned long addr, len; | 2832 | unsigned long addr, len; |
2839 | char *p; | 2833 | char *p; |
2840 | 2834 | ||
@@ -2848,27 +2842,31 @@ static void __init atafb_setup_ext(char *spec) | |||
2848 | * | 2842 | * |
2849 | * Even xres_virtual is available, we neither support panning nor hw-scrolling! | 2843 | * Even xres_virtual is available, we neither support panning nor hw-scrolling! |
2850 | */ | 2844 | */ |
2851 | if (!(p = strsep(&spec, ";")) || !*p) | 2845 | p = strsep(&spec, ";"); |
2852 | return; | 2846 | if (!p || !*p) |
2847 | return; | ||
2853 | xres_virtual = xres = simple_strtoul(p, NULL, 10); | 2848 | xres_virtual = xres = simple_strtoul(p, NULL, 10); |
2854 | if (xres <= 0) | 2849 | if (xres <= 0) |
2855 | return; | 2850 | return; |
2856 | 2851 | ||
2857 | if (!(p = strsep(&spec, ";")) || !*p) | 2852 | p = strsep(&spec, ";"); |
2858 | return; | 2853 | if (!p || !*p) |
2854 | return; | ||
2859 | yres = simple_strtoul(p, NULL, 10); | 2855 | yres = simple_strtoul(p, NULL, 10); |
2860 | if (yres <= 0) | 2856 | if (yres <= 0) |
2861 | return; | 2857 | return; |
2862 | 2858 | ||
2863 | if (!(p = strsep(&spec, ";")) || !*p) | 2859 | p = strsep(&spec, ";"); |
2864 | return; | 2860 | if (!p || !*p) |
2861 | return; | ||
2865 | depth = simple_strtoul(p, NULL, 10); | 2862 | depth = simple_strtoul(p, NULL, 10); |
2866 | if (depth != 1 && depth != 2 && depth != 4 && depth != 8 && | 2863 | if (depth != 1 && depth != 2 && depth != 4 && depth != 8 && |
2867 | depth != 16 && depth != 24) | 2864 | depth != 16 && depth != 24) |
2868 | return; | 2865 | return; |
2869 | 2866 | ||
2870 | if (!(p = strsep(&spec, ";")) || !*p) | 2867 | p = strsep(&spec, ";"); |
2871 | return; | 2868 | if (!p || !*p) |
2869 | return; | ||
2872 | if (*p == 'i') | 2870 | if (*p == 'i') |
2873 | planes = FB_TYPE_INTERLEAVED_PLANES; | 2871 | planes = FB_TYPE_INTERLEAVED_PLANES; |
2874 | else if (*p == 'p') | 2872 | else if (*p == 'p') |
@@ -2876,25 +2874,27 @@ static void __init atafb_setup_ext(char *spec) | |||
2876 | else if (*p == 'n') | 2874 | else if (*p == 'n') |
2877 | planes = FB_TYPE_PLANES; | 2875 | planes = FB_TYPE_PLANES; |
2878 | else if (*p == 't') | 2876 | else if (*p == 't') |
2879 | planes = -1; /* true color */ | 2877 | planes = -1; /* true color */ |
2880 | else | 2878 | else |
2881 | return; | 2879 | return; |
2882 | 2880 | ||
2883 | 2881 | p = strsep(&spec, ";"); | |
2884 | if (!(p = strsep(&spec, ";")) || !*p) | 2882 | if (!p || !*p) |
2885 | return; | 2883 | return; |
2886 | addr = simple_strtoul(p, NULL, 0); | 2884 | addr = simple_strtoul(p, NULL, 0); |
2887 | 2885 | ||
2888 | if (!(p = strsep(&spec, ";")) || !*p) | 2886 | p = strsep(&spec, ";"); |
2889 | len = xres*yres*depth/8; | 2887 | if (!p || !*p) |
2888 | len = xres * yres * depth / 8; | ||
2890 | else | 2889 | else |
2891 | len = simple_strtoul(p, NULL, 0); | 2890 | len = simple_strtoul(p, NULL, 0); |
2892 | 2891 | ||
2893 | if ((p = strsep(&spec, ";")) && *p) { | 2892 | p = strsep(&spec, ";"); |
2894 | external_vgaiobase=simple_strtoul(p, NULL, 0); | 2893 | if (p && *p) |
2895 | } | 2894 | external_vgaiobase = simple_strtoul(p, NULL, 0); |
2896 | 2895 | ||
2897 | if ((p = strsep(&spec, ";")) && *p) { | 2896 | p = strsep(&spec, ";"); |
2897 | if (p && *p) { | ||
2898 | external_bitspercol = simple_strtoul(p, NULL, 0); | 2898 | external_bitspercol = simple_strtoul(p, NULL, 0); |
2899 | if (external_bitspercol > 8) | 2899 | if (external_bitspercol > 8) |
2900 | external_bitspercol = 8; | 2900 | external_bitspercol = 8; |
@@ -2902,59 +2902,61 @@ static void __init atafb_setup_ext(char *spec) | |||
2902 | external_bitspercol = 1; | 2902 | external_bitspercol = 1; |
2903 | } | 2903 | } |
2904 | 2904 | ||
2905 | if ((p = strsep(&spec, ";")) && *p) { | 2905 | p = strsep(&spec, ";"); |
2906 | if (p && *p) { | ||
2906 | if (!strcmp(p, "vga")) | 2907 | if (!strcmp(p, "vga")) |
2907 | external_card_type = IS_VGA; | 2908 | external_card_type = IS_VGA; |
2908 | if (!strcmp(p, "mv300")) | 2909 | if (!strcmp(p, "mv300")) |
2909 | external_card_type = IS_MV300; | 2910 | external_card_type = IS_MV300; |
2910 | } | 2911 | } |
2911 | 2912 | ||
2912 | if ((p = strsep(&spec, ";")) && *p) { | 2913 | p = strsep(&spec, ";"); |
2914 | if (p && *p) { | ||
2913 | xres_virtual = simple_strtoul(p, NULL, 10); | 2915 | xres_virtual = simple_strtoul(p, NULL, 10); |
2914 | if (xres_virtual < xres) | 2916 | if (xres_virtual < xres) |
2915 | xres_virtual = xres; | 2917 | xres_virtual = xres; |
2916 | if (xres_virtual*yres*depth/8 > len) | 2918 | if (xres_virtual * yres * depth / 8 > len) |
2917 | len=xres_virtual*yres*depth/8; | 2919 | len = xres_virtual * yres * depth / 8; |
2918 | } | 2920 | } |
2919 | 2921 | ||
2920 | external_xres = xres; | 2922 | external_xres = xres; |
2921 | external_xres_virtual = xres_virtual; | 2923 | external_xres_virtual = xres_virtual; |
2922 | external_yres = yres; | 2924 | external_yres = yres; |
2923 | external_depth = depth; | 2925 | external_depth = depth; |
2924 | external_pmode = planes; | 2926 | external_pmode = planes; |
2925 | external_addr = (void *)addr; | 2927 | external_addr = (void *)addr; |
2926 | external_len = len; | 2928 | external_len = len; |
2927 | 2929 | ||
2928 | if (external_card_type == IS_MV300) | 2930 | if (external_card_type == IS_MV300) { |
2929 | switch (external_depth) { | 2931 | switch (external_depth) { |
2930 | case 1: | 2932 | case 1: |
2931 | MV300_reg = MV300_reg_1bit; | 2933 | MV300_reg = MV300_reg_1bit; |
2932 | break; | 2934 | break; |
2933 | case 4: | 2935 | case 4: |
2934 | MV300_reg = MV300_reg_4bit; | 2936 | MV300_reg = MV300_reg_4bit; |
2935 | break; | 2937 | break; |
2936 | case 8: | 2938 | case 8: |
2937 | MV300_reg = MV300_reg_8bit; | 2939 | MV300_reg = MV300_reg_8bit; |
2938 | break; | 2940 | break; |
2939 | } | 2941 | } |
2942 | } | ||
2940 | } | 2943 | } |
2941 | #endif /* ATAFB_EXT */ | 2944 | #endif /* ATAFB_EXT */ |
2942 | 2945 | ||
2943 | |||
2944 | static void __init atafb_setup_int(char *spec) | 2946 | static void __init atafb_setup_int(char *spec) |
2945 | { | 2947 | { |
2946 | /* Format to config extended internal video hardware like OverScan: | 2948 | /* Format to config extended internal video hardware like OverScan: |
2947 | "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>" | 2949 | * "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>" |
2948 | Explanation: | 2950 | * Explanation: |
2949 | <xres>: x-resolution | 2951 | * <xres>: x-resolution |
2950 | <yres>: y-resolution | 2952 | * <yres>: y-resolution |
2951 | The following are only needed if you have an overscan which | 2953 | * The following are only needed if you have an overscan which |
2952 | needs a black border: | 2954 | * needs a black border: |
2953 | <xres_max>: max. length of a line in pixels your OverScan hardware would allow | 2955 | * <xres_max>: max. length of a line in pixels your OverScan hardware would allow |
2954 | <yres_max>: max. number of lines your OverScan hardware would allow | 2956 | * <yres_max>: max. number of lines your OverScan hardware would allow |
2955 | <offset>: Offset from physical beginning to visible beginning | 2957 | * <offset>: Offset from physical beginning to visible beginning |
2956 | of screen in bytes | 2958 | * of screen in bytes |
2957 | */ | 2959 | */ |
2958 | int xres; | 2960 | int xres; |
2959 | char *p; | 2961 | char *p; |
2960 | 2962 | ||
@@ -2963,23 +2965,19 @@ static void __init atafb_setup_int(char *spec) | |||
2963 | xres = simple_strtoul(p, NULL, 10); | 2965 | xres = simple_strtoul(p, NULL, 10); |
2964 | if (!(p = strsep(&spec, ";")) || !*p) | 2966 | if (!(p = strsep(&spec, ";")) || !*p) |
2965 | return; | 2967 | return; |
2966 | sttt_xres=xres; | 2968 | sttt_xres = xres; |
2967 | tt_yres=st_yres=simple_strtoul(p, NULL, 10); | 2969 | tt_yres = st_yres = simple_strtoul(p, NULL, 10); |
2968 | if ((p=strsep(&spec, ";")) && *p) { | 2970 | if ((p = strsep(&spec, ";")) && *p) |
2969 | sttt_xres_virtual=simple_strtoul(p, NULL, 10); | 2971 | sttt_xres_virtual = simple_strtoul(p, NULL, 10); |
2970 | } | 2972 | if ((p = strsep(&spec, ";")) && *p) |
2971 | if ((p=strsep(&spec, ";")) && *p) { | 2973 | sttt_yres_virtual = simple_strtoul(p, NULL, 0); |
2972 | sttt_yres_virtual=simple_strtoul(p, NULL, 0); | 2974 | if ((p = strsep(&spec, ";")) && *p) |
2973 | } | 2975 | ovsc_offset = simple_strtoul(p, NULL, 0); |
2974 | if ((p=strsep(&spec, ";")) && *p) { | ||
2975 | ovsc_offset=simple_strtoul(p, NULL, 0); | ||
2976 | } | ||
2977 | 2976 | ||
2978 | if (ovsc_offset || (sttt_yres_virtual != st_yres)) | 2977 | if (ovsc_offset || (sttt_yres_virtual != st_yres)) |
2979 | use_hwscroll=0; | 2978 | use_hwscroll = 0; |
2980 | } | 2979 | } |
2981 | 2980 | ||
2982 | |||
2983 | #ifdef ATAFB_FALCON | 2981 | #ifdef ATAFB_FALCON |
2984 | static void __init atafb_setup_mcap(char *spec) | 2982 | static void __init atafb_setup_mcap(char *spec) |
2985 | { | 2983 | { |
@@ -3018,7 +3016,6 @@ static void __init atafb_setup_mcap(char *spec) | |||
3018 | } | 3016 | } |
3019 | #endif /* ATAFB_FALCON */ | 3017 | #endif /* ATAFB_FALCON */ |
3020 | 3018 | ||
3021 | |||
3022 | static void __init atafb_setup_user(char *spec) | 3019 | static void __init atafb_setup_user(char *spec) |
3023 | { | 3020 | { |
3024 | /* Format of user defined video mode is: <xres>;<yres>;<depth> | 3021 | /* Format of user defined video mode is: <xres>;<yres>;<depth> |
@@ -3026,81 +3023,257 @@ static void __init atafb_setup_user(char *spec) | |||
3026 | char *p; | 3023 | char *p; |
3027 | int xres, yres, depth, temp; | 3024 | int xres, yres, depth, temp; |
3028 | 3025 | ||
3029 | if (!(p = strsep(&spec, ";")) || !*p) | 3026 | p = strsep(&spec, ";"); |
3027 | if (!p || !*p) | ||
3030 | return; | 3028 | return; |
3031 | xres = simple_strtoul(p, NULL, 10); | 3029 | xres = simple_strtoul(p, NULL, 10); |
3032 | if (!(p = strsep(&spec, ";")) || !*p) | 3030 | p = strsep(&spec, ";"); |
3031 | if (!p || !*p) | ||
3033 | return; | 3032 | return; |
3034 | yres = simple_strtoul(p, NULL, 10); | 3033 | yres = simple_strtoul(p, NULL, 10); |
3035 | if (!(p = strsep(&spec, "")) || !*p) | 3034 | p = strsep(&spec, ""); |
3035 | if (!p || !*p) | ||
3036 | return; | 3036 | return; |
3037 | depth = simple_strtoul(p, NULL, 10); | 3037 | depth = simple_strtoul(p, NULL, 10); |
3038 | if ((temp=get_video_mode("user0"))) { | 3038 | temp = get_video_mode("user0"); |
3039 | default_par=temp; | 3039 | if (temp) { |
3040 | atafb_predefined[default_par-1].xres = xres; | 3040 | default_par = temp; |
3041 | atafb_predefined[default_par-1].yres = yres; | 3041 | atafb_predefined[default_par - 1].xres = xres; |
3042 | atafb_predefined[default_par-1].bits_per_pixel = depth; | 3042 | atafb_predefined[default_par - 1].yres = yres; |
3043 | atafb_predefined[default_par - 1].bits_per_pixel = depth; | ||
3043 | } | 3044 | } |
3044 | } | 3045 | } |
3045 | 3046 | ||
3046 | int __init atafb_setup( char *options ) | 3047 | int __init atafb_setup(char *options) |
3047 | { | 3048 | { |
3048 | char *this_opt; | 3049 | char *this_opt; |
3049 | int temp; | 3050 | int temp; |
3050 | |||
3051 | fb_info.fontname[0] = '\0'; | ||
3052 | 3051 | ||
3053 | if (!options || !*options) | 3052 | if (!options || !*options) |
3054 | return 0; | 3053 | return 0; |
3055 | 3054 | ||
3056 | while ((this_opt = strsep(&options, ",")) != NULL) { | 3055 | while ((this_opt = strsep(&options, ",")) != NULL) { |
3057 | if (!*this_opt) continue; | 3056 | if (!*this_opt) |
3058 | if ((temp=get_video_mode(this_opt))) | 3057 | continue; |
3059 | default_par=temp; | 3058 | if ((temp = get_video_mode(this_opt))) { |
3060 | else if (! strcmp(this_opt, "inverse")) | 3059 | default_par = temp; |
3061 | inverse=1; | 3060 | mode_option = this_opt; |
3062 | else if (!strncmp(this_opt, "font:", 5)) | 3061 | } else if (!strcmp(this_opt, "inverse")) |
3063 | strcpy(fb_info.fontname, this_opt+5); | 3062 | inverse = 1; |
3064 | else if (! strncmp(this_opt, "hwscroll_",9)) { | 3063 | else if (!strncmp(this_opt, "hwscroll_", 9)) { |
3065 | hwscroll=simple_strtoul(this_opt+9, NULL, 10); | 3064 | hwscroll = simple_strtoul(this_opt + 9, NULL, 10); |
3066 | if (hwscroll < 0) | 3065 | if (hwscroll < 0) |
3067 | hwscroll = 0; | 3066 | hwscroll = 0; |
3068 | if (hwscroll > 200) | 3067 | if (hwscroll > 200) |
3069 | hwscroll = 200; | 3068 | hwscroll = 200; |
3070 | } | 3069 | } |
3071 | #ifdef ATAFB_EXT | 3070 | #ifdef ATAFB_EXT |
3072 | else if (!strcmp(this_opt,"mv300")) { | 3071 | else if (!strcmp(this_opt, "mv300")) { |
3073 | external_bitspercol = 8; | 3072 | external_bitspercol = 8; |
3074 | external_card_type = IS_MV300; | 3073 | external_card_type = IS_MV300; |
3074 | } else if (!strncmp(this_opt, "external:", 9)) | ||
3075 | atafb_setup_ext(this_opt + 9); | ||
3076 | #endif | ||
3077 | else if (!strncmp(this_opt, "internal:", 9)) | ||
3078 | atafb_setup_int(this_opt + 9); | ||
3079 | #ifdef ATAFB_FALCON | ||
3080 | else if (!strncmp(this_opt, "eclock:", 7)) { | ||
3081 | fext.f = simple_strtoul(this_opt + 7, NULL, 10); | ||
3082 | /* external pixelclock in kHz --> ps */ | ||
3083 | fext.t = 1000000000 / fext.f; | ||
3084 | fext.f *= 1000; | ||
3085 | } else if (!strncmp(this_opt, "monitorcap:", 11)) | ||
3086 | atafb_setup_mcap(this_opt + 11); | ||
3087 | #endif | ||
3088 | else if (!strcmp(this_opt, "keep")) | ||
3089 | DontCalcRes = 1; | ||
3090 | else if (!strncmp(this_opt, "R", 1)) | ||
3091 | atafb_setup_user(this_opt + 1); | ||
3075 | } | 3092 | } |
3076 | else if (!strncmp(this_opt,"external:",9)) | 3093 | return 0; |
3077 | atafb_setup_ext(this_opt+9); | 3094 | } |
3095 | |||
3096 | int __init atafb_init(void) | ||
3097 | { | ||
3098 | int pad; | ||
3099 | int detected_mode; | ||
3100 | unsigned int defmode = 0; | ||
3101 | unsigned long mem_req; | ||
3102 | |||
3103 | #ifndef MODULE | ||
3104 | char *option = NULL; | ||
3105 | |||
3106 | if (fb_get_options("atafb", &option)) | ||
3107 | return -ENODEV; | ||
3108 | atafb_setup(option); | ||
3109 | #endif | ||
3110 | printk("atafb_init: start\n"); | ||
3111 | |||
3112 | if (!MACH_IS_ATARI) | ||
3113 | return -ENXIO; | ||
3114 | |||
3115 | do { | ||
3116 | #ifdef ATAFB_EXT | ||
3117 | if (external_addr) { | ||
3118 | printk("atafb_init: initializing external hw\n"); | ||
3119 | fbhw = &ext_switch; | ||
3120 | atafb_ops.fb_setcolreg = &ext_setcolreg; | ||
3121 | defmode = DEFMODE_EXT; | ||
3122 | break; | ||
3123 | } | ||
3124 | #endif | ||
3125 | #ifdef ATAFB_TT | ||
3126 | if (ATARIHW_PRESENT(TT_SHIFTER)) { | ||
3127 | printk("atafb_init: initializing TT hw\n"); | ||
3128 | fbhw = &tt_switch; | ||
3129 | atafb_ops.fb_setcolreg = &tt_setcolreg; | ||
3130 | defmode = DEFMODE_TT; | ||
3131 | break; | ||
3132 | } | ||
3078 | #endif | 3133 | #endif |
3079 | else if (!strncmp(this_opt,"internal:",9)) | ||
3080 | atafb_setup_int(this_opt+9); | ||
3081 | #ifdef ATAFB_FALCON | 3134 | #ifdef ATAFB_FALCON |
3082 | else if (!strncmp(this_opt, "eclock:", 7)) { | 3135 | if (ATARIHW_PRESENT(VIDEL_SHIFTER)) { |
3083 | fext.f = simple_strtoul(this_opt+7, NULL, 10); | 3136 | printk("atafb_init: initializing Falcon hw\n"); |
3084 | /* external pixelclock in kHz --> ps */ | 3137 | fbhw = &falcon_switch; |
3085 | fext.t = 1000000000/fext.f; | 3138 | atafb_ops.fb_setcolreg = &falcon_setcolreg; |
3086 | fext.f *= 1000; | 3139 | request_irq(IRQ_AUTO_4, falcon_vbl_switcher, IRQ_TYPE_PRIO, |
3140 | "framebuffer/modeswitch", falcon_vbl_switcher); | ||
3141 | defmode = DEFMODE_F30; | ||
3142 | break; | ||
3143 | } | ||
3144 | #endif | ||
3145 | #ifdef ATAFB_STE | ||
3146 | if (ATARIHW_PRESENT(STND_SHIFTER) || | ||
3147 | ATARIHW_PRESENT(EXTD_SHIFTER)) { | ||
3148 | printk("atafb_init: initializing ST/E hw\n"); | ||
3149 | fbhw = &st_switch; | ||
3150 | atafb_ops.fb_setcolreg = &stste_setcolreg; | ||
3151 | defmode = DEFMODE_STE; | ||
3152 | break; | ||
3153 | } | ||
3154 | fbhw = &st_switch; | ||
3155 | atafb_ops.fb_setcolreg = &stste_setcolreg; | ||
3156 | printk("Cannot determine video hardware; defaulting to ST(e)\n"); | ||
3157 | #else /* ATAFB_STE */ | ||
3158 | /* no default driver included */ | ||
3159 | /* Nobody will ever see this message :-) */ | ||
3160 | panic("Cannot initialize video hardware"); | ||
3161 | #endif | ||
3162 | } while (0); | ||
3163 | |||
3164 | /* Multisync monitor capabilities */ | ||
3165 | /* Atari-TOS defaults if no boot option present */ | ||
3166 | if (fb_info.monspecs.hfmin == 0) { | ||
3167 | fb_info.monspecs.hfmin = 31000; | ||
3168 | fb_info.monspecs.hfmax = 32000; | ||
3169 | fb_info.monspecs.vfmin = 58; | ||
3170 | fb_info.monspecs.vfmax = 62; | ||
3087 | } | 3171 | } |
3088 | else if (!strncmp(this_opt, "monitorcap:", 11)) | 3172 | |
3089 | atafb_setup_mcap(this_opt+11); | 3173 | detected_mode = fbhw->detect(); |
3174 | check_default_par(detected_mode); | ||
3175 | #ifdef ATAFB_EXT | ||
3176 | if (!external_addr) { | ||
3177 | #endif /* ATAFB_EXT */ | ||
3178 | mem_req = default_mem_req + ovsc_offset + ovsc_addlen; | ||
3179 | mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE; | ||
3180 | screen_base = atari_stram_alloc(mem_req, "atafb"); | ||
3181 | if (!screen_base) | ||
3182 | panic("Cannot allocate screen memory"); | ||
3183 | memset(screen_base, 0, mem_req); | ||
3184 | pad = -(unsigned long)screen_base & (PAGE_SIZE - 1); | ||
3185 | screen_base += pad; | ||
3186 | real_screen_base = screen_base + ovsc_offset; | ||
3187 | screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK; | ||
3188 | st_ovsc_switch(); | ||
3189 | if (CPU_IS_040_OR_060) { | ||
3190 | /* On a '040+, the cache mode of video RAM must be set to | ||
3191 | * write-through also for internal video hardware! */ | ||
3192 | cache_push(virt_to_phys(screen_base), screen_len); | ||
3193 | kernel_set_cachemode(screen_base, screen_len, | ||
3194 | IOMAP_WRITETHROUGH); | ||
3195 | } | ||
3196 | printk("atafb: screen_base %p real_screen_base %p screen_len %d\n", | ||
3197 | screen_base, real_screen_base, screen_len); | ||
3198 | #ifdef ATAFB_EXT | ||
3199 | } else { | ||
3200 | /* Map the video memory (physical address given) to somewhere | ||
3201 | * in the kernel address space. | ||
3202 | */ | ||
3203 | external_addr = ioremap_writethrough((unsigned long)external_addr, | ||
3204 | external_len); | ||
3205 | if (external_vgaiobase) | ||
3206 | external_vgaiobase = | ||
3207 | (unsigned long)ioremap(external_vgaiobase, 0x10000); | ||
3208 | screen_base = | ||
3209 | real_screen_base = external_addr; | ||
3210 | screen_len = external_len & PAGE_MASK; | ||
3211 | memset (screen_base, 0, external_len); | ||
3212 | } | ||
3213 | #endif /* ATAFB_EXT */ | ||
3214 | |||
3215 | // strcpy(fb_info.mode->name, "Atari Builtin "); | ||
3216 | fb_info.fbops = &atafb_ops; | ||
3217 | // try to set default (detected; requested) var | ||
3218 | do_fb_set_var(&atafb_predefined[default_par - 1], 1); | ||
3219 | // reads hw state into current par, which may not be sane yet | ||
3220 | ata_get_par(¤t_par); | ||
3221 | fb_info.par = ¤t_par; | ||
3222 | // tries to read from HW which may not be initialized yet | ||
3223 | // so set sane var first, then call atafb_set_par | ||
3224 | atafb_get_var(&fb_info.var, &fb_info); | ||
3225 | fb_info.flags = FBINFO_FLAG_DEFAULT; | ||
3226 | |||
3227 | if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, atafb_modedb, | ||
3228 | NUM_TOTAL_MODES, &atafb_modedb[defmode], | ||
3229 | fb_info.var.bits_per_pixel)) { | ||
3230 | return -EINVAL; | ||
3231 | } | ||
3232 | |||
3233 | atafb_set_disp(&fb_info); | ||
3234 | |||
3235 | fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0); | ||
3236 | |||
3237 | |||
3238 | printk("Determined %dx%d, depth %d\n", | ||
3239 | fb_info.var.xres, fb_info.var.yres, fb_info.var.bits_per_pixel); | ||
3240 | if ((fb_info.var.xres != fb_info.var.xres_virtual) || | ||
3241 | (fb_info.var.yres != fb_info.var.yres_virtual)) | ||
3242 | printk(" virtual %dx%d\n", fb_info.var.xres_virtual, | ||
3243 | fb_info.var.yres_virtual); | ||
3244 | |||
3245 | if (register_framebuffer(&fb_info) < 0) { | ||
3246 | #ifdef ATAFB_EXT | ||
3247 | if (external_addr) { | ||
3248 | iounmap(external_addr); | ||
3249 | external_addr = NULL; | ||
3250 | } | ||
3251 | if (external_vgaiobase) { | ||
3252 | iounmap((void*)external_vgaiobase); | ||
3253 | external_vgaiobase = 0; | ||
3254 | } | ||
3090 | #endif | 3255 | #endif |
3091 | else if (!strcmp(this_opt, "keep")) | 3256 | return -EINVAL; |
3092 | DontCalcRes = 1; | 3257 | } |
3093 | else if (!strncmp(this_opt, "R", 1)) | 3258 | |
3094 | atafb_setup_user(this_opt+1); | 3259 | // FIXME: mode needs setting! |
3095 | } | 3260 | //printk("fb%d: %s frame buffer device, using %dK of video memory\n", |
3096 | return 0; | 3261 | // fb_info.node, fb_info.mode->name, screen_len>>10); |
3262 | printk("fb%d: frame buffer device, using %dK of video memory\n", | ||
3263 | fb_info.node, screen_len >> 10); | ||
3264 | |||
3265 | /* TODO: This driver cannot be unloaded yet */ | ||
3266 | return 0; | ||
3097 | } | 3267 | } |
3098 | 3268 | ||
3269 | module_init(atafb_init); | ||
3270 | |||
3099 | #ifdef MODULE | 3271 | #ifdef MODULE |
3100 | MODULE_LICENSE("GPL"); | 3272 | MODULE_LICENSE("GPL"); |
3101 | 3273 | ||
3102 | int init_module(void) | 3274 | int cleanup_module(void) |
3103 | { | 3275 | { |
3104 | return atafb_init(); | 3276 | unregister_framebuffer(&fb_info); |
3277 | return atafb_deinit(); | ||
3105 | } | 3278 | } |
3106 | #endif /* MODULE */ | 3279 | #endif /* MODULE */ |
diff --git a/drivers/video/atafb.h b/drivers/video/atafb.h new file mode 100644 index 000000000000..014e05906cb1 --- /dev/null +++ b/drivers/video/atafb.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef _VIDEO_ATAFB_H | ||
2 | #define _VIDEO_ATAFB_H | ||
3 | |||
4 | void atafb_mfb_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy, | ||
5 | int dx, int height, int width); | ||
6 | void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
7 | int sy, int sx, int height, int width); | ||
8 | void atafb_mfb_linefill(struct fb_info *info, u_long next_line, | ||
9 | int dy, int dx, u32 width, | ||
10 | const u8 *data, u32 bgcolor, u32 fgcolor); | ||
11 | |||
12 | void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy, | ||
13 | int dx, int height, int width); | ||
14 | void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
15 | int sy, int sx, int height, int width); | ||
16 | void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line, | ||
17 | int dy, int dx, u32 width, | ||
18 | const u8 *data, u32 bgcolor, u32 fgcolor); | ||
19 | |||
20 | void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy, | ||
21 | int dx, int height, int width); | ||
22 | void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
23 | int sy, int sx, int height, int width); | ||
24 | void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line, | ||
25 | int dy, int dx, u32 width, | ||
26 | const u8 *data, u32 bgcolor, u32 fgcolor); | ||
27 | |||
28 | void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line, int sy, int sx, int dy, | ||
29 | int dx, int height, int width); | ||
30 | void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
31 | int sy, int sx, int height, int width); | ||
32 | void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line, | ||
33 | int dy, int dx, u32 width, | ||
34 | const u8 *data, u32 bgcolor, u32 fgcolor); | ||
35 | |||
36 | #endif /* _VIDEO_ATAFB_H */ | ||
diff --git a/drivers/video/atafb_iplan2p2.c b/drivers/video/atafb_iplan2p2.c new file mode 100644 index 000000000000..8cc9c50379d0 --- /dev/null +++ b/drivers/video/atafb_iplan2p2.c | |||
@@ -0,0 +1,293 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/iplan2p2.c -- Low level frame buffer operations for | ||
3 | * interleaved bitplanes à la Atari (2 | ||
4 | * planes, 2 bytes interleave) | ||
5 | * | ||
6 | * Created 5 Apr 1997 by Geert Uytterhoeven | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file COPYING in the main directory of this archive for | ||
10 | * more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/fb.h> | ||
16 | |||
17 | #include <asm/setup.h> | ||
18 | |||
19 | #include "atafb.h" | ||
20 | |||
21 | #define BPL 2 | ||
22 | #include "atafb_utils.h" | ||
23 | |||
24 | void atafb_iplan2p2_copyarea(struct fb_info *info, u_long next_line, | ||
25 | int sy, int sx, int dy, int dx, | ||
26 | int height, int width) | ||
27 | { | ||
28 | /* bmove() has to distinguish two major cases: If both, source and | ||
29 | * destination, start at even addresses or both are at odd | ||
30 | * addresses, just the first odd and last even column (if present) | ||
31 | * require special treatment (memmove_col()). The rest between | ||
32 | * then can be copied by normal operations, because all adjacent | ||
33 | * bytes are affected and are to be stored in the same order. | ||
34 | * The pathological case is when the move should go from an odd | ||
35 | * address to an even or vice versa. Since the bytes in the plane | ||
36 | * words must be assembled in new order, it seems wisest to make | ||
37 | * all movements by memmove_col(). | ||
38 | */ | ||
39 | |||
40 | u8 *src, *dst; | ||
41 | u32 *s, *d; | ||
42 | int w, l , i, j; | ||
43 | u_int colsize; | ||
44 | u_int upwards = (dy < sy) || (dy == sy && dx < sx); | ||
45 | |||
46 | colsize = height; | ||
47 | if (!((sx ^ dx) & 15)) { | ||
48 | /* odd->odd or even->even */ | ||
49 | |||
50 | if (upwards) { | ||
51 | src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); | ||
52 | dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); | ||
53 | if (sx & 15) { | ||
54 | memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2); | ||
55 | src += BPL * 2; | ||
56 | dst += BPL * 2; | ||
57 | width -= 8; | ||
58 | } | ||
59 | w = width >> 4; | ||
60 | if (w) { | ||
61 | s = (u32 *)src; | ||
62 | d = (u32 *)dst; | ||
63 | w *= BPL / 2; | ||
64 | l = next_line - w * 4; | ||
65 | for (j = height; j > 0; j--) { | ||
66 | for (i = w; i > 0; i--) | ||
67 | *d++ = *s++; | ||
68 | s = (u32 *)((u8 *)s + l); | ||
69 | d = (u32 *)((u8 *)d + l); | ||
70 | } | ||
71 | } | ||
72 | if (width & 15) | ||
73 | memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL), | ||
74 | 0xff00ff00, height, next_line - BPL * 2); | ||
75 | } else { | ||
76 | src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); | ||
77 | dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); | ||
78 | |||
79 | if ((sx + width) & 15) { | ||
80 | src -= BPL * 2; | ||
81 | dst -= BPL * 2; | ||
82 | memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2); | ||
83 | width -= 8; | ||
84 | } | ||
85 | w = width >> 4; | ||
86 | if (w) { | ||
87 | s = (u32 *)src; | ||
88 | d = (u32 *)dst; | ||
89 | w *= BPL / 2; | ||
90 | l = next_line - w * 4; | ||
91 | for (j = height; j > 0; j--) { | ||
92 | for (i = w; i > 0; i--) | ||
93 | *--d = *--s; | ||
94 | s = (u32 *)((u8 *)s - l); | ||
95 | d = (u32 *)((u8 *)d - l); | ||
96 | } | ||
97 | } | ||
98 | if (sx & 15) | ||
99 | memmove32_col(dst - (width - 16) / (8 / BPL), | ||
100 | src - (width - 16) / (8 / BPL), | ||
101 | 0xff00ff, colsize, -next_line - BPL * 2); | ||
102 | } | ||
103 | } else { | ||
104 | /* odd->even or even->odd */ | ||
105 | if (upwards) { | ||
106 | u32 *src32, *dst32; | ||
107 | u32 pval[4], v, v1, mask; | ||
108 | int i, j, w, f; | ||
109 | |||
110 | src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); | ||
111 | dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); | ||
112 | |||
113 | mask = 0xff00ff00; | ||
114 | f = 0; | ||
115 | w = width; | ||
116 | if (sx & 15) { | ||
117 | f = 1; | ||
118 | w += 8; | ||
119 | } | ||
120 | if ((sx + width) & 15) | ||
121 | f |= 2; | ||
122 | w >>= 4; | ||
123 | for (i = height; i; i--) { | ||
124 | src32 = (u32 *)src; | ||
125 | dst32 = (u32 *)dst; | ||
126 | |||
127 | if (f & 1) { | ||
128 | pval[0] = (*src32++ << 8) & mask; | ||
129 | } else { | ||
130 | pval[0] = dst32[0] & mask; | ||
131 | } | ||
132 | |||
133 | for (j = w; j > 0; j--) { | ||
134 | v = *src32++; | ||
135 | v1 = v & mask; | ||
136 | *dst32++ = pval[0] | (v1 >> 8); | ||
137 | pval[0] = (v ^ v1) << 8; | ||
138 | } | ||
139 | |||
140 | if (f & 2) { | ||
141 | dst32[0] = (dst32[0] & mask) | pval[0]; | ||
142 | } | ||
143 | |||
144 | src += next_line; | ||
145 | dst += next_line; | ||
146 | } | ||
147 | } else { | ||
148 | u32 *src32, *dst32; | ||
149 | u32 pval[4], v, v1, mask; | ||
150 | int i, j, w, f; | ||
151 | |||
152 | src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); | ||
153 | dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); | ||
154 | |||
155 | mask = 0xff00ff; | ||
156 | f = 0; | ||
157 | w = width; | ||
158 | if ((dx + width) & 15) | ||
159 | f = 1; | ||
160 | if (sx & 15) { | ||
161 | f |= 2; | ||
162 | w += 8; | ||
163 | } | ||
164 | w >>= 4; | ||
165 | for (i = height; i; i--) { | ||
166 | src32 = (u32 *)src; | ||
167 | dst32 = (u32 *)dst; | ||
168 | |||
169 | if (f & 1) { | ||
170 | pval[0] = dst32[-1] & mask; | ||
171 | } else { | ||
172 | pval[0] = (*--src32 >> 8) & mask; | ||
173 | } | ||
174 | |||
175 | for (j = w; j > 0; j--) { | ||
176 | v = *--src32; | ||
177 | v1 = v & mask; | ||
178 | *--dst32 = pval[0] | (v1 << 8); | ||
179 | pval[0] = (v ^ v1) >> 8; | ||
180 | } | ||
181 | |||
182 | if (!(f & 2)) { | ||
183 | dst32[-1] = (dst32[-1] & mask) | pval[0]; | ||
184 | } | ||
185 | |||
186 | src -= next_line; | ||
187 | dst -= next_line; | ||
188 | } | ||
189 | } | ||
190 | } | ||
191 | } | ||
192 | |||
193 | void atafb_iplan2p2_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
194 | int sy, int sx, int height, int width) | ||
195 | { | ||
196 | u32 *dest; | ||
197 | int rows, i; | ||
198 | u32 cval[4]; | ||
199 | |||
200 | dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL)); | ||
201 | if (sx & 15) { | ||
202 | u8 *dest8 = (u8 *)dest + 1; | ||
203 | |||
204 | expand8_col2mask(color, cval); | ||
205 | |||
206 | for (i = height; i; i--) { | ||
207 | fill8_col(dest8, cval); | ||
208 | dest8 += next_line; | ||
209 | } | ||
210 | dest += BPL / 2; | ||
211 | width -= 8; | ||
212 | } | ||
213 | |||
214 | expand16_col2mask(color, cval); | ||
215 | rows = width >> 4; | ||
216 | if (rows) { | ||
217 | u32 *d = dest; | ||
218 | u32 off = next_line - rows * BPL * 2; | ||
219 | for (i = height; i; i--) { | ||
220 | d = fill16_col(d, rows, cval); | ||
221 | d = (u32 *)((long)d + off); | ||
222 | } | ||
223 | dest += rows * BPL / 2; | ||
224 | width &= 15; | ||
225 | } | ||
226 | |||
227 | if (width) { | ||
228 | u8 *dest8 = (u8 *)dest; | ||
229 | |||
230 | expand8_col2mask(color, cval); | ||
231 | |||
232 | for (i = height; i; i--) { | ||
233 | fill8_col(dest8, cval); | ||
234 | dest8 += next_line; | ||
235 | } | ||
236 | } | ||
237 | } | ||
238 | |||
239 | void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line, | ||
240 | int dy, int dx, u32 width, | ||
241 | const u8 *data, u32 bgcolor, u32 fgcolor) | ||
242 | { | ||
243 | u32 *dest; | ||
244 | const u16 *data16; | ||
245 | int rows; | ||
246 | u32 fgm[4], bgm[4], m; | ||
247 | |||
248 | dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL)); | ||
249 | if (dx & 15) { | ||
250 | fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++); | ||
251 | dest += BPL / 2; | ||
252 | width -= 8; | ||
253 | } | ||
254 | |||
255 | if (width >= 16) { | ||
256 | data16 = (const u16 *)data; | ||
257 | expand16_2col2mask(fgcolor, bgcolor, fgm, bgm); | ||
258 | |||
259 | for (rows = width / 16; rows; rows--) { | ||
260 | u16 d = *data16++; | ||
261 | m = d | ((u32)d << 16); | ||
262 | *dest++ = (m & fgm[0]) ^ bgm[0]; | ||
263 | } | ||
264 | |||
265 | data = (const u8 *)data16; | ||
266 | width &= 15; | ||
267 | } | ||
268 | |||
269 | if (width) | ||
270 | fill8_2col((u8 *)dest, fgcolor, bgcolor, *data); | ||
271 | } | ||
272 | |||
273 | #ifdef MODULE | ||
274 | MODULE_LICENSE("GPL"); | ||
275 | |||
276 | int init_module(void) | ||
277 | { | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | void cleanup_module(void) | ||
282 | { | ||
283 | } | ||
284 | #endif /* MODULE */ | ||
285 | |||
286 | |||
287 | /* | ||
288 | * Visible symbols for modules | ||
289 | */ | ||
290 | |||
291 | EXPORT_SYMBOL(atafb_iplan2p2_copyarea); | ||
292 | EXPORT_SYMBOL(atafb_iplan2p2_fillrect); | ||
293 | EXPORT_SYMBOL(atafb_iplan2p2_linefill); | ||
diff --git a/drivers/video/atafb_iplan2p4.c b/drivers/video/atafb_iplan2p4.c new file mode 100644 index 000000000000..bee0d89463f7 --- /dev/null +++ b/drivers/video/atafb_iplan2p4.c | |||
@@ -0,0 +1,308 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/iplan2p4.c -- Low level frame buffer operations for | ||
3 | * interleaved bitplanes à la Atari (4 | ||
4 | * planes, 2 bytes interleave) | ||
5 | * | ||
6 | * Created 5 Apr 1997 by Geert Uytterhoeven | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file COPYING in the main directory of this archive for | ||
10 | * more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/fb.h> | ||
16 | |||
17 | #include <asm/setup.h> | ||
18 | |||
19 | #include "atafb.h" | ||
20 | |||
21 | #define BPL 4 | ||
22 | #include "atafb_utils.h" | ||
23 | |||
24 | void atafb_iplan2p4_copyarea(struct fb_info *info, u_long next_line, | ||
25 | int sy, int sx, int dy, int dx, | ||
26 | int height, int width) | ||
27 | { | ||
28 | /* bmove() has to distinguish two major cases: If both, source and | ||
29 | * destination, start at even addresses or both are at odd | ||
30 | * addresses, just the first odd and last even column (if present) | ||
31 | * require special treatment (memmove_col()). The rest between | ||
32 | * then can be copied by normal operations, because all adjacent | ||
33 | * bytes are affected and are to be stored in the same order. | ||
34 | * The pathological case is when the move should go from an odd | ||
35 | * address to an even or vice versa. Since the bytes in the plane | ||
36 | * words must be assembled in new order, it seems wisest to make | ||
37 | * all movements by memmove_col(). | ||
38 | */ | ||
39 | |||
40 | u8 *src, *dst; | ||
41 | u32 *s, *d; | ||
42 | int w, l , i, j; | ||
43 | u_int colsize; | ||
44 | u_int upwards = (dy < sy) || (dy == sy && dx < sx); | ||
45 | |||
46 | colsize = height; | ||
47 | if (!((sx ^ dx) & 15)) { | ||
48 | /* odd->odd or even->even */ | ||
49 | |||
50 | if (upwards) { | ||
51 | src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); | ||
52 | dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); | ||
53 | if (sx & 15) { | ||
54 | memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2); | ||
55 | src += BPL * 2; | ||
56 | dst += BPL * 2; | ||
57 | width -= 8; | ||
58 | } | ||
59 | w = width >> 4; | ||
60 | if (w) { | ||
61 | s = (u32 *)src; | ||
62 | d = (u32 *)dst; | ||
63 | w *= BPL / 2; | ||
64 | l = next_line - w * 4; | ||
65 | for (j = height; j > 0; j--) { | ||
66 | for (i = w; i > 0; i--) | ||
67 | *d++ = *s++; | ||
68 | s = (u32 *)((u8 *)s + l); | ||
69 | d = (u32 *)((u8 *)d + l); | ||
70 | } | ||
71 | } | ||
72 | if (width & 15) | ||
73 | memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL), | ||
74 | 0xff00ff00, height, next_line - BPL * 2); | ||
75 | } else { | ||
76 | src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); | ||
77 | dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); | ||
78 | |||
79 | if ((sx + width) & 15) { | ||
80 | src -= BPL * 2; | ||
81 | dst -= BPL * 2; | ||
82 | memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2); | ||
83 | width -= 8; | ||
84 | } | ||
85 | w = width >> 4; | ||
86 | if (w) { | ||
87 | s = (u32 *)src; | ||
88 | d = (u32 *)dst; | ||
89 | w *= BPL / 2; | ||
90 | l = next_line - w * 4; | ||
91 | for (j = height; j > 0; j--) { | ||
92 | for (i = w; i > 0; i--) | ||
93 | *--d = *--s; | ||
94 | s = (u32 *)((u8 *)s - l); | ||
95 | d = (u32 *)((u8 *)d - l); | ||
96 | } | ||
97 | } | ||
98 | if (sx & 15) | ||
99 | memmove32_col(dst - (width - 16) / (8 / BPL), | ||
100 | src - (width - 16) / (8 / BPL), | ||
101 | 0xff00ff, colsize, -next_line - BPL * 2); | ||
102 | } | ||
103 | } else { | ||
104 | /* odd->even or even->odd */ | ||
105 | if (upwards) { | ||
106 | u32 *src32, *dst32; | ||
107 | u32 pval[4], v, v1, mask; | ||
108 | int i, j, w, f; | ||
109 | |||
110 | src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); | ||
111 | dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); | ||
112 | |||
113 | mask = 0xff00ff00; | ||
114 | f = 0; | ||
115 | w = width; | ||
116 | if (sx & 15) { | ||
117 | f = 1; | ||
118 | w += 8; | ||
119 | } | ||
120 | if ((sx + width) & 15) | ||
121 | f |= 2; | ||
122 | w >>= 4; | ||
123 | for (i = height; i; i--) { | ||
124 | src32 = (u32 *)src; | ||
125 | dst32 = (u32 *)dst; | ||
126 | |||
127 | if (f & 1) { | ||
128 | pval[0] = (*src32++ << 8) & mask; | ||
129 | pval[1] = (*src32++ << 8) & mask; | ||
130 | } else { | ||
131 | pval[0] = dst32[0] & mask; | ||
132 | pval[1] = dst32[1] & mask; | ||
133 | } | ||
134 | |||
135 | for (j = w; j > 0; j--) { | ||
136 | v = *src32++; | ||
137 | v1 = v & mask; | ||
138 | *dst32++ = pval[0] | (v1 >> 8); | ||
139 | pval[0] = (v ^ v1) << 8; | ||
140 | v = *src32++; | ||
141 | v1 = v & mask; | ||
142 | *dst32++ = pval[1] | (v1 >> 8); | ||
143 | pval[1] = (v ^ v1) << 8; | ||
144 | } | ||
145 | |||
146 | if (f & 2) { | ||
147 | dst32[0] = (dst32[0] & mask) | pval[0]; | ||
148 | dst32[1] = (dst32[1] & mask) | pval[1]; | ||
149 | } | ||
150 | |||
151 | src += next_line; | ||
152 | dst += next_line; | ||
153 | } | ||
154 | } else { | ||
155 | u32 *src32, *dst32; | ||
156 | u32 pval[4], v, v1, mask; | ||
157 | int i, j, w, f; | ||
158 | |||
159 | src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); | ||
160 | dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); | ||
161 | |||
162 | mask = 0xff00ff; | ||
163 | f = 0; | ||
164 | w = width; | ||
165 | if ((dx + width) & 15) | ||
166 | f = 1; | ||
167 | if (sx & 15) { | ||
168 | f |= 2; | ||
169 | w += 8; | ||
170 | } | ||
171 | w >>= 4; | ||
172 | for (i = height; i; i--) { | ||
173 | src32 = (u32 *)src; | ||
174 | dst32 = (u32 *)dst; | ||
175 | |||
176 | if (f & 1) { | ||
177 | pval[0] = dst32[-1] & mask; | ||
178 | pval[1] = dst32[-2] & mask; | ||
179 | } else { | ||
180 | pval[0] = (*--src32 >> 8) & mask; | ||
181 | pval[1] = (*--src32 >> 8) & mask; | ||
182 | } | ||
183 | |||
184 | for (j = w; j > 0; j--) { | ||
185 | v = *--src32; | ||
186 | v1 = v & mask; | ||
187 | *--dst32 = pval[0] | (v1 << 8); | ||
188 | pval[0] = (v ^ v1) >> 8; | ||
189 | v = *--src32; | ||
190 | v1 = v & mask; | ||
191 | *--dst32 = pval[1] | (v1 << 8); | ||
192 | pval[1] = (v ^ v1) >> 8; | ||
193 | } | ||
194 | |||
195 | if (!(f & 2)) { | ||
196 | dst32[-1] = (dst32[-1] & mask) | pval[0]; | ||
197 | dst32[-2] = (dst32[-2] & mask) | pval[1]; | ||
198 | } | ||
199 | |||
200 | src -= next_line; | ||
201 | dst -= next_line; | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | |||
207 | void atafb_iplan2p4_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
208 | int sy, int sx, int height, int width) | ||
209 | { | ||
210 | u32 *dest; | ||
211 | int rows, i; | ||
212 | u32 cval[4]; | ||
213 | |||
214 | dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL)); | ||
215 | if (sx & 15) { | ||
216 | u8 *dest8 = (u8 *)dest + 1; | ||
217 | |||
218 | expand8_col2mask(color, cval); | ||
219 | |||
220 | for (i = height; i; i--) { | ||
221 | fill8_col(dest8, cval); | ||
222 | dest8 += next_line; | ||
223 | } | ||
224 | dest += BPL / 2; | ||
225 | width -= 8; | ||
226 | } | ||
227 | |||
228 | expand16_col2mask(color, cval); | ||
229 | rows = width >> 4; | ||
230 | if (rows) { | ||
231 | u32 *d = dest; | ||
232 | u32 off = next_line - rows * BPL * 2; | ||
233 | for (i = height; i; i--) { | ||
234 | d = fill16_col(d, rows, cval); | ||
235 | d = (u32 *)((long)d + off); | ||
236 | } | ||
237 | dest += rows * BPL / 2; | ||
238 | width &= 15; | ||
239 | } | ||
240 | |||
241 | if (width) { | ||
242 | u8 *dest8 = (u8 *)dest; | ||
243 | |||
244 | expand8_col2mask(color, cval); | ||
245 | |||
246 | for (i = height; i; i--) { | ||
247 | fill8_col(dest8, cval); | ||
248 | dest8 += next_line; | ||
249 | } | ||
250 | } | ||
251 | } | ||
252 | |||
253 | void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line, | ||
254 | int dy, int dx, u32 width, | ||
255 | const u8 *data, u32 bgcolor, u32 fgcolor) | ||
256 | { | ||
257 | u32 *dest; | ||
258 | const u16 *data16; | ||
259 | int rows; | ||
260 | u32 fgm[4], bgm[4], m; | ||
261 | |||
262 | dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL)); | ||
263 | if (dx & 15) { | ||
264 | fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++); | ||
265 | dest += BPL / 2; | ||
266 | width -= 8; | ||
267 | } | ||
268 | |||
269 | if (width >= 16) { | ||
270 | data16 = (const u16 *)data; | ||
271 | expand16_2col2mask(fgcolor, bgcolor, fgm, bgm); | ||
272 | |||
273 | for (rows = width / 16; rows; rows--) { | ||
274 | u16 d = *data16++; | ||
275 | m = d | ((u32)d << 16); | ||
276 | *dest++ = (m & fgm[0]) ^ bgm[0]; | ||
277 | *dest++ = (m & fgm[1]) ^ bgm[1]; | ||
278 | } | ||
279 | |||
280 | data = (const u8 *)data16; | ||
281 | width &= 15; | ||
282 | } | ||
283 | |||
284 | if (width) | ||
285 | fill8_2col((u8 *)dest, fgcolor, bgcolor, *data); | ||
286 | } | ||
287 | |||
288 | #ifdef MODULE | ||
289 | MODULE_LICENSE("GPL"); | ||
290 | |||
291 | int init_module(void) | ||
292 | { | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | void cleanup_module(void) | ||
297 | { | ||
298 | } | ||
299 | #endif /* MODULE */ | ||
300 | |||
301 | |||
302 | /* | ||
303 | * Visible symbols for modules | ||
304 | */ | ||
305 | |||
306 | EXPORT_SYMBOL(atafb_iplan2p4_copyarea); | ||
307 | EXPORT_SYMBOL(atafb_iplan2p4_fillrect); | ||
308 | EXPORT_SYMBOL(atafb_iplan2p4_linefill); | ||
diff --git a/drivers/video/atafb_iplan2p8.c b/drivers/video/atafb_iplan2p8.c new file mode 100644 index 000000000000..356fb52ce443 --- /dev/null +++ b/drivers/video/atafb_iplan2p8.c | |||
@@ -0,0 +1,345 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/iplan2p8.c -- Low level frame buffer operations for | ||
3 | * interleaved bitplanes à la Atari (8 | ||
4 | * planes, 2 bytes interleave) | ||
5 | * | ||
6 | * Created 5 Apr 1997 by Geert Uytterhoeven | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file COPYING in the main directory of this archive for | ||
10 | * more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/fb.h> | ||
16 | |||
17 | #include <asm/setup.h> | ||
18 | |||
19 | #include "atafb.h" | ||
20 | |||
21 | #define BPL 8 | ||
22 | #include "atafb_utils.h" | ||
23 | |||
24 | |||
25 | /* Copies a 8 plane column from 's', height 'h', to 'd'. */ | ||
26 | |||
27 | /* This expands a 8 bit color into two longs for two movepl (8 plane) | ||
28 | * operations. | ||
29 | */ | ||
30 | |||
31 | void atafb_iplan2p8_copyarea(struct fb_info *info, u_long next_line, | ||
32 | int sy, int sx, int dy, int dx, | ||
33 | int height, int width) | ||
34 | { | ||
35 | /* bmove() has to distinguish two major cases: If both, source and | ||
36 | * destination, start at even addresses or both are at odd | ||
37 | * addresses, just the first odd and last even column (if present) | ||
38 | * require special treatment (memmove_col()). The rest between | ||
39 | * then can be copied by normal operations, because all adjacent | ||
40 | * bytes are affected and are to be stored in the same order. | ||
41 | * The pathological case is when the move should go from an odd | ||
42 | * address to an even or vice versa. Since the bytes in the plane | ||
43 | * words must be assembled in new order, it seems wisest to make | ||
44 | * all movements by memmove_col(). | ||
45 | */ | ||
46 | |||
47 | u8 *src, *dst; | ||
48 | u32 *s, *d; | ||
49 | int w, l , i, j; | ||
50 | u_int colsize; | ||
51 | u_int upwards = (dy < sy) || (dy == sy && dx < sx); | ||
52 | |||
53 | colsize = height; | ||
54 | if (!((sx ^ dx) & 15)) { | ||
55 | /* odd->odd or even->even */ | ||
56 | |||
57 | if (upwards) { | ||
58 | src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); | ||
59 | dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); | ||
60 | if (sx & 15) { | ||
61 | memmove32_col(dst, src, 0xff00ff, height, next_line - BPL * 2); | ||
62 | src += BPL * 2; | ||
63 | dst += BPL * 2; | ||
64 | width -= 8; | ||
65 | } | ||
66 | w = width >> 4; | ||
67 | if (w) { | ||
68 | s = (u32 *)src; | ||
69 | d = (u32 *)dst; | ||
70 | w *= BPL / 2; | ||
71 | l = next_line - w * 4; | ||
72 | for (j = height; j > 0; j--) { | ||
73 | for (i = w; i > 0; i--) | ||
74 | *d++ = *s++; | ||
75 | s = (u32 *)((u8 *)s + l); | ||
76 | d = (u32 *)((u8 *)d + l); | ||
77 | } | ||
78 | } | ||
79 | if (width & 15) | ||
80 | memmove32_col(dst + width / (8 / BPL), src + width / (8 / BPL), | ||
81 | 0xff00ff00, height, next_line - BPL * 2); | ||
82 | } else { | ||
83 | src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); | ||
84 | dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); | ||
85 | |||
86 | if ((sx + width) & 15) { | ||
87 | src -= BPL * 2; | ||
88 | dst -= BPL * 2; | ||
89 | memmove32_col(dst, src, 0xff00ff00, colsize, -next_line - BPL * 2); | ||
90 | width -= 8; | ||
91 | } | ||
92 | w = width >> 4; | ||
93 | if (w) { | ||
94 | s = (u32 *)src; | ||
95 | d = (u32 *)dst; | ||
96 | w *= BPL / 2; | ||
97 | l = next_line - w * 4; | ||
98 | for (j = height; j > 0; j--) { | ||
99 | for (i = w; i > 0; i--) | ||
100 | *--d = *--s; | ||
101 | s = (u32 *)((u8 *)s - l); | ||
102 | d = (u32 *)((u8 *)d - l); | ||
103 | } | ||
104 | } | ||
105 | if (sx & 15) | ||
106 | memmove32_col(dst - (width - 16) / (8 / BPL), | ||
107 | src - (width - 16) / (8 / BPL), | ||
108 | 0xff00ff, colsize, -next_line - BPL * 2); | ||
109 | } | ||
110 | } else { | ||
111 | /* odd->even or even->odd */ | ||
112 | if (upwards) { | ||
113 | u32 *src32, *dst32; | ||
114 | u32 pval[4], v, v1, mask; | ||
115 | int i, j, w, f; | ||
116 | |||
117 | src = (u8 *)info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL); | ||
118 | dst = (u8 *)info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL); | ||
119 | |||
120 | mask = 0xff00ff00; | ||
121 | f = 0; | ||
122 | w = width; | ||
123 | if (sx & 15) { | ||
124 | f = 1; | ||
125 | w += 8; | ||
126 | } | ||
127 | if ((sx + width) & 15) | ||
128 | f |= 2; | ||
129 | w >>= 4; | ||
130 | for (i = height; i; i--) { | ||
131 | src32 = (u32 *)src; | ||
132 | dst32 = (u32 *)dst; | ||
133 | |||
134 | if (f & 1) { | ||
135 | pval[0] = (*src32++ << 8) & mask; | ||
136 | pval[1] = (*src32++ << 8) & mask; | ||
137 | pval[2] = (*src32++ << 8) & mask; | ||
138 | pval[3] = (*src32++ << 8) & mask; | ||
139 | } else { | ||
140 | pval[0] = dst32[0] & mask; | ||
141 | pval[1] = dst32[1] & mask; | ||
142 | pval[2] = dst32[2] & mask; | ||
143 | pval[3] = dst32[3] & mask; | ||
144 | } | ||
145 | |||
146 | for (j = w; j > 0; j--) { | ||
147 | v = *src32++; | ||
148 | v1 = v & mask; | ||
149 | *dst32++ = pval[0] | (v1 >> 8); | ||
150 | pval[0] = (v ^ v1) << 8; | ||
151 | v = *src32++; | ||
152 | v1 = v & mask; | ||
153 | *dst32++ = pval[1] | (v1 >> 8); | ||
154 | pval[1] = (v ^ v1) << 8; | ||
155 | v = *src32++; | ||
156 | v1 = v & mask; | ||
157 | *dst32++ = pval[2] | (v1 >> 8); | ||
158 | pval[2] = (v ^ v1) << 8; | ||
159 | v = *src32++; | ||
160 | v1 = v & mask; | ||
161 | *dst32++ = pval[3] | (v1 >> 8); | ||
162 | pval[3] = (v ^ v1) << 8; | ||
163 | } | ||
164 | |||
165 | if (f & 2) { | ||
166 | dst32[0] = (dst32[0] & mask) | pval[0]; | ||
167 | dst32[1] = (dst32[1] & mask) | pval[1]; | ||
168 | dst32[2] = (dst32[2] & mask) | pval[2]; | ||
169 | dst32[3] = (dst32[3] & mask) | pval[3]; | ||
170 | } | ||
171 | |||
172 | src += next_line; | ||
173 | dst += next_line; | ||
174 | } | ||
175 | } else { | ||
176 | u32 *src32, *dst32; | ||
177 | u32 pval[4], v, v1, mask; | ||
178 | int i, j, w, f; | ||
179 | |||
180 | src = (u8 *)info->screen_base + (sy - 1) * next_line + ((sx + width + 8) & ~15) / (8 / BPL); | ||
181 | dst = (u8 *)info->screen_base + (dy - 1) * next_line + ((dx + width + 8) & ~15) / (8 / BPL); | ||
182 | |||
183 | mask = 0xff00ff; | ||
184 | f = 0; | ||
185 | w = width; | ||
186 | if ((dx + width) & 15) | ||
187 | f = 1; | ||
188 | if (sx & 15) { | ||
189 | f |= 2; | ||
190 | w += 8; | ||
191 | } | ||
192 | w >>= 4; | ||
193 | for (i = height; i; i--) { | ||
194 | src32 = (u32 *)src; | ||
195 | dst32 = (u32 *)dst; | ||
196 | |||
197 | if (f & 1) { | ||
198 | pval[0] = dst32[-1] & mask; | ||
199 | pval[1] = dst32[-2] & mask; | ||
200 | pval[2] = dst32[-3] & mask; | ||
201 | pval[3] = dst32[-4] & mask; | ||
202 | } else { | ||
203 | pval[0] = (*--src32 >> 8) & mask; | ||
204 | pval[1] = (*--src32 >> 8) & mask; | ||
205 | pval[2] = (*--src32 >> 8) & mask; | ||
206 | pval[3] = (*--src32 >> 8) & mask; | ||
207 | } | ||
208 | |||
209 | for (j = w; j > 0; j--) { | ||
210 | v = *--src32; | ||
211 | v1 = v & mask; | ||
212 | *--dst32 = pval[0] | (v1 << 8); | ||
213 | pval[0] = (v ^ v1) >> 8; | ||
214 | v = *--src32; | ||
215 | v1 = v & mask; | ||
216 | *--dst32 = pval[1] | (v1 << 8); | ||
217 | pval[1] = (v ^ v1) >> 8; | ||
218 | v = *--src32; | ||
219 | v1 = v & mask; | ||
220 | *--dst32 = pval[2] | (v1 << 8); | ||
221 | pval[2] = (v ^ v1) >> 8; | ||
222 | v = *--src32; | ||
223 | v1 = v & mask; | ||
224 | *--dst32 = pval[3] | (v1 << 8); | ||
225 | pval[3] = (v ^ v1) >> 8; | ||
226 | } | ||
227 | |||
228 | if (!(f & 2)) { | ||
229 | dst32[-1] = (dst32[-1] & mask) | pval[0]; | ||
230 | dst32[-2] = (dst32[-2] & mask) | pval[1]; | ||
231 | dst32[-3] = (dst32[-3] & mask) | pval[2]; | ||
232 | dst32[-4] = (dst32[-4] & mask) | pval[3]; | ||
233 | } | ||
234 | |||
235 | src -= next_line; | ||
236 | dst -= next_line; | ||
237 | } | ||
238 | } | ||
239 | } | ||
240 | } | ||
241 | |||
242 | void atafb_iplan2p8_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
243 | int sy, int sx, int height, int width) | ||
244 | { | ||
245 | u32 *dest; | ||
246 | int rows, i; | ||
247 | u32 cval[4]; | ||
248 | |||
249 | dest = (u32 *)(info->screen_base + sy * next_line + (sx & ~15) / (8 / BPL)); | ||
250 | if (sx & 15) { | ||
251 | u8 *dest8 = (u8 *)dest + 1; | ||
252 | |||
253 | expand8_col2mask(color, cval); | ||
254 | |||
255 | for (i = height; i; i--) { | ||
256 | fill8_col(dest8, cval); | ||
257 | dest8 += next_line; | ||
258 | } | ||
259 | dest += BPL / 2; | ||
260 | width -= 8; | ||
261 | } | ||
262 | |||
263 | expand16_col2mask(color, cval); | ||
264 | rows = width >> 4; | ||
265 | if (rows) { | ||
266 | u32 *d = dest; | ||
267 | u32 off = next_line - rows * BPL * 2; | ||
268 | for (i = height; i; i--) { | ||
269 | d = fill16_col(d, rows, cval); | ||
270 | d = (u32 *)((long)d + off); | ||
271 | } | ||
272 | dest += rows * BPL / 2; | ||
273 | width &= 15; | ||
274 | } | ||
275 | |||
276 | if (width) { | ||
277 | u8 *dest8 = (u8 *)dest; | ||
278 | |||
279 | expand8_col2mask(color, cval); | ||
280 | |||
281 | for (i = height; i; i--) { | ||
282 | fill8_col(dest8, cval); | ||
283 | dest8 += next_line; | ||
284 | } | ||
285 | } | ||
286 | } | ||
287 | |||
288 | void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line, | ||
289 | int dy, int dx, u32 width, | ||
290 | const u8 *data, u32 bgcolor, u32 fgcolor) | ||
291 | { | ||
292 | u32 *dest; | ||
293 | const u16 *data16; | ||
294 | int rows; | ||
295 | u32 fgm[4], bgm[4], m; | ||
296 | |||
297 | dest = (u32 *)(info->screen_base + dy * next_line + (dx & ~15) / (8 / BPL)); | ||
298 | if (dx & 15) { | ||
299 | fill8_2col((u8 *)dest + 1, fgcolor, bgcolor, *data++); | ||
300 | dest += BPL / 2; | ||
301 | width -= 8; | ||
302 | } | ||
303 | |||
304 | if (width >= 16) { | ||
305 | data16 = (const u16 *)data; | ||
306 | expand16_2col2mask(fgcolor, bgcolor, fgm, bgm); | ||
307 | |||
308 | for (rows = width / 16; rows; rows--) { | ||
309 | u16 d = *data16++; | ||
310 | m = d | ((u32)d << 16); | ||
311 | *dest++ = (m & fgm[0]) ^ bgm[0]; | ||
312 | *dest++ = (m & fgm[1]) ^ bgm[1]; | ||
313 | *dest++ = (m & fgm[2]) ^ bgm[2]; | ||
314 | *dest++ = (m & fgm[3]) ^ bgm[3]; | ||
315 | } | ||
316 | |||
317 | data = (const u8 *)data16; | ||
318 | width &= 15; | ||
319 | } | ||
320 | |||
321 | if (width) | ||
322 | fill8_2col((u8 *)dest, fgcolor, bgcolor, *data); | ||
323 | } | ||
324 | |||
325 | #ifdef MODULE | ||
326 | MODULE_LICENSE("GPL"); | ||
327 | |||
328 | int init_module(void) | ||
329 | { | ||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | void cleanup_module(void) | ||
334 | { | ||
335 | } | ||
336 | #endif /* MODULE */ | ||
337 | |||
338 | |||
339 | /* | ||
340 | * Visible symbols for modules | ||
341 | */ | ||
342 | |||
343 | EXPORT_SYMBOL(atafb_iplan2p8_copyarea); | ||
344 | EXPORT_SYMBOL(atafb_iplan2p8_fillrect); | ||
345 | EXPORT_SYMBOL(atafb_iplan2p8_linefill); | ||
diff --git a/drivers/video/atafb_mfb.c b/drivers/video/atafb_mfb.c new file mode 100644 index 000000000000..6a352d62eecf --- /dev/null +++ b/drivers/video/atafb_mfb.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/mfb.c -- Low level frame buffer operations for | ||
3 | * monochrome | ||
4 | * | ||
5 | * Created 5 Apr 1997 by Geert Uytterhoeven | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file COPYING in the main directory of this archive for | ||
9 | * more details. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/string.h> | ||
14 | #include <linux/fb.h> | ||
15 | |||
16 | #include "atafb.h" | ||
17 | #include "atafb_utils.h" | ||
18 | |||
19 | |||
20 | /* | ||
21 | * Monochrome | ||
22 | */ | ||
23 | |||
24 | void atafb_mfb_copyarea(struct fb_info *info, u_long next_line, | ||
25 | int sy, int sx, int dy, int dx, | ||
26 | int height, int width) | ||
27 | { | ||
28 | u8 *src, *dest; | ||
29 | u_int rows; | ||
30 | |||
31 | if (sx == 0 && dx == 0 && width == next_line) { | ||
32 | src = (u8 *)info->screen_base + sy * (width >> 3); | ||
33 | dest = (u8 *)info->screen_base + dy * (width >> 3); | ||
34 | fb_memmove(dest, src, height * (width >> 3)); | ||
35 | } else if (dy <= sy) { | ||
36 | src = (u8 *)info->screen_base + sy * next_line + (sx >> 3); | ||
37 | dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3); | ||
38 | for (rows = height; rows--;) { | ||
39 | fb_memmove(dest, src, width >> 3); | ||
40 | src += next_line; | ||
41 | dest += next_line; | ||
42 | } | ||
43 | } else { | ||
44 | src = (u8 *)info->screen_base + (sy + height - 1) * next_line + (sx >> 3); | ||
45 | dest = (u8 *)info->screen_base + (dy + height - 1) * next_line + (dx >> 3); | ||
46 | for (rows = height; rows--;) { | ||
47 | fb_memmove(dest, src, width >> 3); | ||
48 | src -= next_line; | ||
49 | dest -= next_line; | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | |||
54 | void atafb_mfb_fillrect(struct fb_info *info, u_long next_line, u32 color, | ||
55 | int sy, int sx, int height, int width) | ||
56 | { | ||
57 | u8 *dest; | ||
58 | u_int rows; | ||
59 | |||
60 | dest = (u8 *)info->screen_base + sy * next_line + (sx >> 3); | ||
61 | |||
62 | if (sx == 0 && width == next_line) { | ||
63 | if (color) | ||
64 | fb_memset255(dest, height * (width >> 3)); | ||
65 | else | ||
66 | fb_memclear(dest, height * (width >> 3)); | ||
67 | } else { | ||
68 | for (rows = height; rows--; dest += next_line) { | ||
69 | if (color) | ||
70 | fb_memset255(dest, width >> 3); | ||
71 | else | ||
72 | fb_memclear_small(dest, width >> 3); | ||
73 | } | ||
74 | } | ||
75 | } | ||
76 | |||
77 | void atafb_mfb_linefill(struct fb_info *info, u_long next_line, | ||
78 | int dy, int dx, u32 width, | ||
79 | const u8 *data, u32 bgcolor, u32 fgcolor) | ||
80 | { | ||
81 | u8 *dest; | ||
82 | u_int rows; | ||
83 | |||
84 | dest = (u8 *)info->screen_base + dy * next_line + (dx >> 3); | ||
85 | |||
86 | for (rows = width / 8; rows--; /* check margins */ ) { | ||
87 | // use fast_memmove or fb_memmove | ||
88 | *dest++ = *data++; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | #ifdef MODULE | ||
93 | MODULE_LICENSE("GPL"); | ||
94 | |||
95 | int init_module(void) | ||
96 | { | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | void cleanup_module(void) | ||
101 | { | ||
102 | } | ||
103 | #endif /* MODULE */ | ||
104 | |||
105 | |||
106 | /* | ||
107 | * Visible symbols for modules | ||
108 | */ | ||
109 | |||
110 | EXPORT_SYMBOL(atafb_mfb_copyarea); | ||
111 | EXPORT_SYMBOL(atafb_mfb_fillrect); | ||
112 | EXPORT_SYMBOL(atafb_mfb_linefill); | ||
diff --git a/drivers/video/atafb_utils.h b/drivers/video/atafb_utils.h new file mode 100644 index 000000000000..ac9e19dc5057 --- /dev/null +++ b/drivers/video/atafb_utils.h | |||
@@ -0,0 +1,400 @@ | |||
1 | #ifndef _VIDEO_ATAFB_UTILS_H | ||
2 | #define _VIDEO_ATAFB_UTILS_H | ||
3 | |||
4 | /* ================================================================= */ | ||
5 | /* Utility Assembler Functions */ | ||
6 | /* ================================================================= */ | ||
7 | |||
8 | /* ====================================================================== */ | ||
9 | |||
10 | /* Those of a delicate disposition might like to skip the next couple of | ||
11 | * pages. | ||
12 | * | ||
13 | * These functions are drop in replacements for memmove and | ||
14 | * memset(_, 0, _). However their five instances add at least a kilobyte | ||
15 | * to the object file. You have been warned. | ||
16 | * | ||
17 | * Not a great fan of assembler for the sake of it, but I think | ||
18 | * that these routines are at least 10 times faster than their C | ||
19 | * equivalents for large blits, and that's important to the lowest level of | ||
20 | * a graphics driver. Question is whether some scheme with the blitter | ||
21 | * would be faster. I suspect not for simple text system - not much | ||
22 | * asynchrony. | ||
23 | * | ||
24 | * Code is very simple, just gruesome expansion. Basic strategy is to | ||
25 | * increase data moved/cleared at each step to 16 bytes to reduce | ||
26 | * instruction per data move overhead. movem might be faster still | ||
27 | * For more than 15 bytes, we try to align the write direction on a | ||
28 | * longword boundary to get maximum speed. This is even more gruesome. | ||
29 | * Unaligned read/write used requires 68020+ - think this is a problem? | ||
30 | * | ||
31 | * Sorry! | ||
32 | */ | ||
33 | |||
34 | |||
35 | /* ++roman: I've optimized Robert's original versions in some minor | ||
36 | * aspects, e.g. moveq instead of movel, let gcc choose the registers, | ||
37 | * use movem in some places... | ||
38 | * For other modes than 1 plane, lots of more such assembler functions | ||
39 | * were needed (e.g. the ones using movep or expanding color values). | ||
40 | */ | ||
41 | |||
42 | /* ++andreas: more optimizations: | ||
43 | subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc | ||
44 | addal is faster than addaw | ||
45 | movep is rather expensive compared to ordinary move's | ||
46 | some functions rewritten in C for clarity, no speed loss */ | ||
47 | |||
48 | static inline void *fb_memclear_small(void *s, size_t count) | ||
49 | { | ||
50 | if (!count) | ||
51 | return 0; | ||
52 | |||
53 | asm volatile ("\n" | ||
54 | " lsr.l #1,%1 ; jcc 1f ; move.b %2,-(%0)\n" | ||
55 | "1: lsr.l #1,%1 ; jcc 1f ; move.w %2,-(%0)\n" | ||
56 | "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0)\n" | ||
57 | "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n" | ||
58 | "1:" | ||
59 | : "=a" (s), "=d" (count) | ||
60 | : "d" (0), "0" ((char *)s + count), "1" (count)); | ||
61 | asm volatile ("\n" | ||
62 | " subq.l #1,%1\n" | ||
63 | " jcs 3f\n" | ||
64 | " move.l %2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n" | ||
65 | "2: movem.l %2/%%d4/%%d5/%%d6,-(%0)\n" | ||
66 | " dbra %1,2b\n" | ||
67 | "3:" | ||
68 | : "=a" (s), "=d" (count) | ||
69 | : "d" (0), "0" (s), "1" (count) | ||
70 | : "d4", "d5", "d6" | ||
71 | ); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | |||
77 | static inline void *fb_memclear(void *s, size_t count) | ||
78 | { | ||
79 | if (!count) | ||
80 | return 0; | ||
81 | |||
82 | if (count < 16) { | ||
83 | asm volatile ("\n" | ||
84 | " lsr.l #1,%1 ; jcc 1f ; clr.b (%0)+\n" | ||
85 | "1: lsr.l #1,%1 ; jcc 1f ; clr.w (%0)+\n" | ||
86 | "1: lsr.l #1,%1 ; jcc 1f ; clr.l (%0)+\n" | ||
87 | "1: lsr.l #1,%1 ; jcc 1f ; clr.l (%0)+ ; clr.l (%0)+\n" | ||
88 | "1:" | ||
89 | : "=a" (s), "=d" (count) | ||
90 | : "0" (s), "1" (count)); | ||
91 | } else { | ||
92 | long tmp; | ||
93 | asm volatile ("\n" | ||
94 | " move.l %1,%2\n" | ||
95 | " lsr.l #1,%2 ; jcc 1f ; clr.b (%0)+ ; subq.w #1,%1\n" | ||
96 | " lsr.l #1,%2 ; jcs 2f\n" /* %0 increased=>bit 2 switched*/ | ||
97 | " clr.w (%0)+ ; subq.w #2,%1 ; jra 2f\n" | ||
98 | "1: lsr.l #1,%2 ; jcc 2f\n" | ||
99 | " clr.w (%0)+ ; subq.w #2,%1\n" | ||
100 | "2: move.w %1,%2; lsr.l #2,%1 ; jeq 6f\n" | ||
101 | " lsr.l #1,%1 ; jcc 3f ; clr.l (%0)+\n" | ||
102 | "3: lsr.l #1,%1 ; jcc 4f ; clr.l (%0)+ ; clr.l (%0)+\n" | ||
103 | "4: subq.l #1,%1 ; jcs 6f\n" | ||
104 | "5: clr.l (%0)+; clr.l (%0)+ ; clr.l (%0)+ ; clr.l (%0)+\n" | ||
105 | " dbra %1,5b ; clr.w %1; subq.l #1,%1; jcc 5b\n" | ||
106 | "6: move.w %2,%1; btst #1,%1 ; jeq 7f ; clr.w (%0)+\n" | ||
107 | "7: btst #0,%1 ; jeq 8f ; clr.b (%0)+\n" | ||
108 | "8:" | ||
109 | : "=a" (s), "=d" (count), "=d" (tmp) | ||
110 | : "0" (s), "1" (count)); | ||
111 | } | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | |||
117 | static inline void *fb_memset255(void *s, size_t count) | ||
118 | { | ||
119 | if (!count) | ||
120 | return 0; | ||
121 | |||
122 | asm volatile ("\n" | ||
123 | " lsr.l #1,%1 ; jcc 1f ; move.b %2,-(%0)\n" | ||
124 | "1: lsr.l #1,%1 ; jcc 1f ; move.w %2,-(%0)\n" | ||
125 | "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0)\n" | ||
126 | "1: lsr.l #1,%1 ; jcc 1f ; move.l %2,-(%0) ; move.l %2,-(%0)\n" | ||
127 | "1:" | ||
128 | : "=a" (s), "=d" (count) | ||
129 | : "d" (-1), "0" ((char *)s+count), "1" (count)); | ||
130 | asm volatile ("\n" | ||
131 | " subq.l #1,%1 ; jcs 3f\n" | ||
132 | " move.l %2,%%d4; move.l %2,%%d5; move.l %2,%%d6\n" | ||
133 | "2: movem.l %2/%%d4/%%d5/%%d6,-(%0)\n" | ||
134 | " dbra %1,2b\n" | ||
135 | "3:" | ||
136 | : "=a" (s), "=d" (count) | ||
137 | : "d" (-1), "0" (s), "1" (count) | ||
138 | : "d4", "d5", "d6"); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | |||
144 | static inline void *fb_memmove(void *d, const void *s, size_t count) | ||
145 | { | ||
146 | if (d < s) { | ||
147 | if (count < 16) { | ||
148 | asm volatile ("\n" | ||
149 | " lsr.l #1,%2 ; jcc 1f ; move.b (%1)+,(%0)+\n" | ||
150 | "1: lsr.l #1,%2 ; jcc 1f ; move.w (%1)+,(%0)+\n" | ||
151 | "1: lsr.l #1,%2 ; jcc 1f ; move.l (%1)+,(%0)+\n" | ||
152 | "1: lsr.l #1,%2 ; jcc 1f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n" | ||
153 | "1:" | ||
154 | : "=a" (d), "=a" (s), "=d" (count) | ||
155 | : "0" (d), "1" (s), "2" (count)); | ||
156 | } else { | ||
157 | long tmp; | ||
158 | asm volatile ("\n" | ||
159 | " move.l %0,%3\n" | ||
160 | " lsr.l #1,%3 ; jcc 1f ; move.b (%1)+,(%0)+ ; subqw #1,%2\n" | ||
161 | " lsr.l #1,%3 ; jcs 2f\n" /* %0 increased=>bit 2 switched*/ | ||
162 | " move.w (%1)+,(%0)+ ; subqw #2,%2 ; jra 2f\n" | ||
163 | "1: lsr.l #1,%3 ; jcc 2f\n" | ||
164 | " move.w (%1)+,(%0)+ ; subqw #2,%2\n" | ||
165 | "2: move.w %2,%-; lsr.l #2,%2 ; jeq 6f\n" | ||
166 | " lsr.l #1,%2 ; jcc 3f ; move.l (%1)+,(%0)+\n" | ||
167 | "3: lsr.l #1,%2 ; jcc 4f ; move.l (%1)+,(%0)+ ; move.l (%1)+,(%0)+\n" | ||
168 | "4: subq.l #1,%2 ; jcs 6f\n" | ||
169 | "5: move.l (%1)+,(%0)+; move.l (%1)+,(%0)+\n" | ||
170 | " move.l (%1)+,(%0)+; move.l (%1)+,(%0)+\n" | ||
171 | " dbra %2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n" | ||
172 | "6: move.w %+,%2; btst #1,%2 ; jeq 7f ; move.w (%1)+,(%0)+\n" | ||
173 | "7: btst #0,%2 ; jeq 8f ; move.b (%1)+,(%0)+\n" | ||
174 | "8:" | ||
175 | : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp) | ||
176 | : "0" (d), "1" (s), "2" (count)); | ||
177 | } | ||
178 | } else { | ||
179 | if (count < 16) { | ||
180 | asm volatile ("\n" | ||
181 | " lsr.l #1,%2 ; jcc 1f ; move.b -(%1),-(%0)\n" | ||
182 | "1: lsr.l #1,%2 ; jcc 1f ; move.w -(%1),-(%0)\n" | ||
183 | "1: lsr.l #1,%2 ; jcc 1f ; move.l -(%1),-(%0)\n" | ||
184 | "1: lsr.l #1,%2 ; jcc 1f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n" | ||
185 | "1:" | ||
186 | : "=a" (d), "=a" (s), "=d" (count) | ||
187 | : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)); | ||
188 | } else { | ||
189 | long tmp; | ||
190 | |||
191 | asm volatile ("\n" | ||
192 | " move.l %0,%3\n" | ||
193 | " lsr.l #1,%3 ; jcc 1f ; move.b -(%1),-(%0) ; subqw #1,%2\n" | ||
194 | " lsr.l #1,%3 ; jcs 2f\n" /* %0 increased=>bit 2 switched*/ | ||
195 | " move.w -(%1),-(%0) ; subqw #2,%2 ; jra 2f\n" | ||
196 | "1: lsr.l #1,%3 ; jcc 2f\n" | ||
197 | " move.w -(%1),-(%0) ; subqw #2,%2\n" | ||
198 | "2: move.w %2,%-; lsr.l #2,%2 ; jeq 6f\n" | ||
199 | " lsr.l #1,%2 ; jcc 3f ; move.l -(%1),-(%0)\n" | ||
200 | "3: lsr.l #1,%2 ; jcc 4f ; move.l -(%1),-(%0) ; move.l -(%1),-(%0)\n" | ||
201 | "4: subq.l #1,%2 ; jcs 6f\n" | ||
202 | "5: move.l -(%1),-(%0); move.l -(%1),-(%0)\n" | ||
203 | " move.l -(%1),-(%0); move.l -(%1),-(%0)\n" | ||
204 | " dbra %2,5b ; clr.w %2; subq.l #1,%2; jcc 5b\n" | ||
205 | "6: move.w %+,%2; btst #1,%2 ; jeq 7f ; move.w -(%1),-(%0)\n" | ||
206 | "7: btst #0,%2 ; jeq 8f ; move.b -(%1),-(%0)\n" | ||
207 | "8:" | ||
208 | : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp) | ||
209 | : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | |||
217 | /* ++andreas: Simple and fast version of memmove, assumes size is | ||
218 | divisible by 16, suitable for moving the whole screen bitplane */ | ||
219 | static inline void fast_memmove(char *dst, const char *src, size_t size) | ||
220 | { | ||
221 | if (!size) | ||
222 | return; | ||
223 | if (dst < src) | ||
224 | asm volatile ("\n" | ||
225 | "1: movem.l (%0)+,%%d0/%%d1/%%a0/%%a1\n" | ||
226 | " movem.l %%d0/%%d1/%%a0/%%a1,%1@\n" | ||
227 | " addq.l #8,%1; addq.l #8,%1\n" | ||
228 | " dbra %2,1b\n" | ||
229 | " clr.w %2; subq.l #1,%2\n" | ||
230 | " jcc 1b" | ||
231 | : "=a" (src), "=a" (dst), "=d" (size) | ||
232 | : "0" (src), "1" (dst), "2" (size / 16 - 1) | ||
233 | : "d0", "d1", "a0", "a1", "memory"); | ||
234 | else | ||
235 | asm volatile ("\n" | ||
236 | "1: subq.l #8,%0; subq.l #8,%0\n" | ||
237 | " movem.l %0@,%%d0/%%d1/%%a0/%%a1\n" | ||
238 | " movem.l %%d0/%%d1/%%a0/%%a1,-(%1)\n" | ||
239 | " dbra %2,1b\n" | ||
240 | " clr.w %2; subq.l #1,%2\n" | ||
241 | " jcc 1b" | ||
242 | : "=a" (src), "=a" (dst), "=d" (size) | ||
243 | : "0" (src + size), "1" (dst + size), "2" (size / 16 - 1) | ||
244 | : "d0", "d1", "a0", "a1", "memory"); | ||
245 | } | ||
246 | |||
247 | #ifdef BPL | ||
248 | |||
249 | /* | ||
250 | * This expands a up to 8 bit color into two longs | ||
251 | * for movel operations. | ||
252 | */ | ||
253 | static const u32 four2long[] = { | ||
254 | 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff, | ||
255 | 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff, | ||
256 | 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff, | ||
257 | 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff, | ||
258 | }; | ||
259 | |||
260 | static inline void expand8_col2mask(u8 c, u32 m[]) | ||
261 | { | ||
262 | m[0] = four2long[c & 15]; | ||
263 | #if BPL > 4 | ||
264 | m[1] = four2long[c >> 4]; | ||
265 | #endif | ||
266 | } | ||
267 | |||
268 | static inline void expand8_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[]) | ||
269 | { | ||
270 | fgm[0] = four2long[fg & 15] ^ (bgm[0] = four2long[bg & 15]); | ||
271 | #if BPL > 4 | ||
272 | fgm[1] = four2long[fg >> 4] ^ (bgm[1] = four2long[bg >> 4]); | ||
273 | #endif | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | * set an 8bit value to a color | ||
278 | */ | ||
279 | static inline void fill8_col(u8 *dst, u32 m[]) | ||
280 | { | ||
281 | u32 tmp = m[0]; | ||
282 | dst[0] = tmp; | ||
283 | dst[2] = (tmp >>= 8); | ||
284 | #if BPL > 2 | ||
285 | dst[4] = (tmp >>= 8); | ||
286 | dst[6] = tmp >> 8; | ||
287 | #endif | ||
288 | #if BPL > 4 | ||
289 | tmp = m[1]; | ||
290 | dst[8] = tmp; | ||
291 | dst[10] = (tmp >>= 8); | ||
292 | dst[12] = (tmp >>= 8); | ||
293 | dst[14] = tmp >> 8; | ||
294 | #endif | ||
295 | } | ||
296 | |||
297 | /* | ||
298 | * set an 8bit value according to foreground/background color | ||
299 | */ | ||
300 | static inline void fill8_2col(u8 *dst, u8 fg, u8 bg, u32 mask) | ||
301 | { | ||
302 | u32 fgm[2], bgm[2], tmp; | ||
303 | |||
304 | expand8_2col2mask(fg, bg, fgm, bgm); | ||
305 | |||
306 | mask |= mask << 8; | ||
307 | #if BPL > 2 | ||
308 | mask |= mask << 16; | ||
309 | #endif | ||
310 | tmp = (mask & fgm[0]) ^ bgm[0]; | ||
311 | dst[0] = tmp; | ||
312 | dst[2] = (tmp >>= 8); | ||
313 | #if BPL > 2 | ||
314 | dst[4] = (tmp >>= 8); | ||
315 | dst[6] = tmp >> 8; | ||
316 | #endif | ||
317 | #if BPL > 4 | ||
318 | tmp = (mask & fgm[1]) ^ bgm[1]; | ||
319 | dst[8] = tmp; | ||
320 | dst[10] = (tmp >>= 8); | ||
321 | dst[12] = (tmp >>= 8); | ||
322 | dst[14] = tmp >> 8; | ||
323 | #endif | ||
324 | } | ||
325 | |||
326 | static const u32 two2word[] = { | ||
327 | 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff | ||
328 | }; | ||
329 | |||
330 | static inline void expand16_col2mask(u8 c, u32 m[]) | ||
331 | { | ||
332 | m[0] = two2word[c & 3]; | ||
333 | #if BPL > 2 | ||
334 | m[1] = two2word[(c >> 2) & 3]; | ||
335 | #endif | ||
336 | #if BPL > 4 | ||
337 | m[2] = two2word[(c >> 4) & 3]; | ||
338 | m[3] = two2word[c >> 6]; | ||
339 | #endif | ||
340 | } | ||
341 | |||
342 | static inline void expand16_2col2mask(u8 fg, u8 bg, u32 fgm[], u32 bgm[]) | ||
343 | { | ||
344 | bgm[0] = two2word[bg & 3]; | ||
345 | fgm[0] = two2word[fg & 3] ^ bgm[0]; | ||
346 | #if BPL > 2 | ||
347 | bgm[1] = two2word[(bg >> 2) & 3]; | ||
348 | fgm[1] = two2word[(fg >> 2) & 3] ^ bgm[1]; | ||
349 | #endif | ||
350 | #if BPL > 4 | ||
351 | bgm[2] = two2word[(bg >> 4) & 3]; | ||
352 | fgm[2] = two2word[(fg >> 4) & 3] ^ bgm[2]; | ||
353 | bgm[3] = two2word[bg >> 6]; | ||
354 | fgm[3] = two2word[fg >> 6] ^ bgm[3]; | ||
355 | #endif | ||
356 | } | ||
357 | |||
358 | static inline u32 *fill16_col(u32 *dst, int rows, u32 m[]) | ||
359 | { | ||
360 | while (rows) { | ||
361 | *dst++ = m[0]; | ||
362 | #if BPL > 2 | ||
363 | *dst++ = m[1]; | ||
364 | #endif | ||
365 | #if BPL > 4 | ||
366 | *dst++ = m[2]; | ||
367 | *dst++ = m[3]; | ||
368 | #endif | ||
369 | rows--; | ||
370 | } | ||
371 | return dst; | ||
372 | } | ||
373 | |||
374 | static inline void memmove32_col(void *dst, void *src, u32 mask, u32 h, u32 bytes) | ||
375 | { | ||
376 | u32 *s, *d, v; | ||
377 | |||
378 | s = src; | ||
379 | d = dst; | ||
380 | do { | ||
381 | v = (*s++ & mask) | (*d & ~mask); | ||
382 | *d++ = v; | ||
383 | #if BPL > 2 | ||
384 | v = (*s++ & mask) | (*d & ~mask); | ||
385 | *d++ = v; | ||
386 | #endif | ||
387 | #if BPL > 4 | ||
388 | v = (*s++ & mask) | (*d & ~mask); | ||
389 | *d++ = v; | ||
390 | v = (*s++ & mask) | (*d & ~mask); | ||
391 | *d++ = v; | ||
392 | #endif | ||
393 | d = (u32 *)((u8 *)d + bytes); | ||
394 | s = (u32 *)((u8 *)s + bytes); | ||
395 | } while (--h); | ||
396 | } | ||
397 | |||
398 | #endif | ||
399 | |||
400 | #endif /* _VIDEO_ATAFB_UTILS_H */ | ||
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c index 508479920705..7db9de681716 100644 --- a/drivers/video/aty/radeon_i2c.c +++ b/drivers/video/aty/radeon_i2c.c | |||
@@ -1,7 +1,6 @@ | |||
1 | #include <linux/module.h> | 1 | #include <linux/module.h> |
2 | #include <linux/kernel.h> | 2 | #include <linux/kernel.h> |
3 | #include <linux/delay.h> | 3 | #include <linux/delay.h> |
4 | #include <linux/pci.h> | ||
5 | #include <linux/fb.h> | 4 | #include <linux/fb.h> |
6 | 5 | ||
7 | 6 | ||
diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c index ca93a75f2997..b7655c05da53 100644 --- a/drivers/video/g364fb.c +++ b/drivers/video/g364fb.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/fb.h> | 27 | #include <linux/fb.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/pci.h> | ||
30 | #include <asm/io.h> | 29 | #include <asm/io.h> |
31 | #include <asm/jazz.h> | 30 | #include <asm/jazz.h> |
32 | 31 | ||
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c index f4ede5f6b588..61e4c8759b23 100644 --- a/drivers/video/intelfb/intelfb_i2c.c +++ b/drivers/video/intelfb/intelfb_i2c.c | |||
@@ -104,7 +104,8 @@ static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo, | |||
104 | 104 | ||
105 | chan->dinfo = dinfo; | 105 | chan->dinfo = dinfo; |
106 | chan->reg = reg; | 106 | chan->reg = reg; |
107 | snprintf(chan->adapter.name, I2C_NAME_SIZE, "intelfb %s", name); | 107 | snprintf(chan->adapter.name, sizeof(chan->adapter.name), |
108 | "intelfb %s", name); | ||
108 | chan->adapter.owner = THIS_MODULE; | 109 | chan->adapter.owner = THIS_MODULE; |
109 | chan->adapter.id = I2C_HW_B_INTELFB; | 110 | chan->adapter.id = I2C_HW_B_INTELFB; |
110 | chan->adapter.algo_data = &chan->algo; | 111 | chan->adapter.algo_data = &chan->algo; |
diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/matrox/i2c-matroxfb.c index 5ec718a5fe22..4baab7be58de 100644 --- a/drivers/video/matrox/i2c-matroxfb.c +++ b/drivers/video/matrox/i2c-matroxfb.c | |||
@@ -111,7 +111,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, | |||
111 | b->mask.data = data; | 111 | b->mask.data = data; |
112 | b->mask.clock = clock; | 112 | b->mask.clock = clock; |
113 | b->adapter = matrox_i2c_adapter_template; | 113 | b->adapter = matrox_i2c_adapter_template; |
114 | snprintf(b->adapter.name, I2C_NAME_SIZE, name, | 114 | snprintf(b->adapter.name, sizeof(b->adapter.name), name, |
115 | minfo->fbcon.node); | 115 | minfo->fbcon.node); |
116 | i2c_set_adapdata(&b->adapter, b); | 116 | i2c_set_adapdata(&b->adapter, b); |
117 | b->adapter.algo_data = &b->bac; | 117 | b->adapter.algo_data = &b->bac; |
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 233871655824..e64f8b5d0056 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/fb.h> | 29 | #include <linux/fb.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/pci.h> | ||
32 | #include <linux/nvram.h> | 31 | #include <linux/nvram.h> |
33 | #include <asm/io.h> | 32 | #include <asm/io.h> |
34 | #include <asm/prom.h> | 33 | #include <asm/prom.h> |
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index 81e43cda7d8b..07d1979bc23e 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include <linux/ioctl.h> | 32 | #include <linux/ioctl.h> |
33 | #include <linux/notifier.h> | 33 | #include <linux/notifier.h> |
34 | #include <linux/reboot.h> | 34 | #include <linux/reboot.h> |
35 | #include <linux/kthread.h> | ||
36 | #include <linux/freezer.h> | ||
35 | 37 | ||
36 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
37 | #include <linux/fb.h> | 39 | #include <linux/fb.h> |
@@ -45,7 +47,7 @@ | |||
45 | #include <asm/ps3.h> | 47 | #include <asm/ps3.h> |
46 | 48 | ||
47 | #ifdef PS3FB_DEBUG | 49 | #ifdef PS3FB_DEBUG |
48 | #define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ##args) | 50 | #define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ##args) |
49 | #else | 51 | #else |
50 | #define DPRINTK(fmt, args...) | 52 | #define DPRINTK(fmt, args...) |
51 | #endif | 53 | #endif |
@@ -129,7 +131,6 @@ struct ps3fb_priv { | |||
129 | u64 context_handle, memory_handle; | 131 | u64 context_handle, memory_handle; |
130 | void *xdr_ea; | 132 | void *xdr_ea; |
131 | struct gpu_driver_info *dinfo; | 133 | struct gpu_driver_info *dinfo; |
132 | struct semaphore sem; | ||
133 | u32 res_index; | 134 | u32 res_index; |
134 | 135 | ||
135 | u64 vblank_count; /* frame count */ | 136 | u64 vblank_count; /* frame count */ |
@@ -139,6 +140,8 @@ struct ps3fb_priv { | |||
139 | atomic_t ext_flip; /* on/off flip with vsync */ | 140 | atomic_t ext_flip; /* on/off flip with vsync */ |
140 | atomic_t f_count; /* fb_open count */ | 141 | atomic_t f_count; /* fb_open count */ |
141 | int is_blanked; | 142 | int is_blanked; |
143 | int is_kicked; | ||
144 | struct task_struct *task; | ||
142 | }; | 145 | }; |
143 | static struct ps3fb_priv ps3fb; | 146 | static struct ps3fb_priv ps3fb; |
144 | 147 | ||
@@ -294,10 +297,10 @@ static const struct fb_videomode ps3fb_modedb[] = { | |||
294 | #define VP_OFF(i) (WIDTH(i) * Y_OFF(i) * BPP + X_OFF(i) * BPP) | 297 | #define VP_OFF(i) (WIDTH(i) * Y_OFF(i) * BPP + X_OFF(i) * BPP) |
295 | #define FB_OFF(i) (GPU_OFFSET - VP_OFF(i) % GPU_OFFSET) | 298 | #define FB_OFF(i) (GPU_OFFSET - VP_OFF(i) % GPU_OFFSET) |
296 | 299 | ||
297 | static int ps3fb_mode = 0; | 300 | static int ps3fb_mode; |
298 | module_param(ps3fb_mode, bool, 0); | 301 | module_param(ps3fb_mode, bool, 0); |
299 | 302 | ||
300 | static char *mode_option __initdata = NULL; | 303 | static char *mode_option __initdata; |
301 | 304 | ||
302 | 305 | ||
303 | static int ps3fb_get_res_table(u32 xres, u32 yres) | 306 | static int ps3fb_get_res_table(u32 xres, u32 yres) |
@@ -393,7 +396,7 @@ static int ps3fb_sync(u32 frame) | |||
393 | 396 | ||
394 | if (frame > ps3fb.num_frames - 1) { | 397 | if (frame > ps3fb.num_frames - 1) { |
395 | printk(KERN_WARNING "%s: invalid frame number (%u)\n", | 398 | printk(KERN_WARNING "%s: invalid frame number (%u)\n", |
396 | __FUNCTION__, frame); | 399 | __func__, frame); |
397 | return -EINVAL; | 400 | return -EINVAL; |
398 | } | 401 | } |
399 | offset = xres * yres * BPP * frame; | 402 | offset = xres * yres * BPP * frame; |
@@ -406,23 +409,26 @@ static int ps3fb_sync(u32 frame) | |||
406 | (xres << 16) | yres, | 409 | (xres << 16) | yres, |
407 | xres * BPP); /* line_length */ | 410 | xres * BPP); /* line_length */ |
408 | if (status) | 411 | if (status) |
409 | printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n", | 412 | printk(KERN_ERR |
410 | __FUNCTION__, status); | 413 | "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n", |
414 | __func__, status); | ||
411 | #ifdef HEAD_A | 415 | #ifdef HEAD_A |
412 | status = lv1_gpu_context_attribute(ps3fb.context_handle, | 416 | status = lv1_gpu_context_attribute(ps3fb.context_handle, |
413 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, | 417 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, |
414 | 0, offset, 0, 0); | 418 | 0, offset, 0, 0); |
415 | if (status) | 419 | if (status) |
416 | printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n", | 420 | printk(KERN_ERR |
417 | __FUNCTION__, status); | 421 | "%s: lv1_gpu_context_attribute FLIP failed: %d\n", |
422 | __func__, status); | ||
418 | #endif | 423 | #endif |
419 | #ifdef HEAD_B | 424 | #ifdef HEAD_B |
420 | status = lv1_gpu_context_attribute(ps3fb.context_handle, | 425 | status = lv1_gpu_context_attribute(ps3fb.context_handle, |
421 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, | 426 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, |
422 | 1, offset, 0, 0); | 427 | 1, offset, 0, 0); |
423 | if (status) | 428 | if (status) |
424 | printk(KERN_ERR "%s: lv1_gpu_context_attribute FLIP failed: %d\n", | 429 | printk(KERN_ERR |
425 | __FUNCTION__, status); | 430 | "%s: lv1_gpu_context_attribute FLIP failed: %d\n", |
431 | __func__, status); | ||
426 | #endif | 432 | #endif |
427 | return 0; | 433 | return 0; |
428 | } | 434 | } |
@@ -631,7 +637,7 @@ static int ps3fb_blank(int blank, struct fb_info *info) | |||
631 | { | 637 | { |
632 | int retval; | 638 | int retval; |
633 | 639 | ||
634 | DPRINTK("%s: blank:%d\n", __FUNCTION__, blank); | 640 | DPRINTK("%s: blank:%d\n", __func__, blank); |
635 | switch (blank) { | 641 | switch (blank) { |
636 | case FB_BLANK_POWERDOWN: | 642 | case FB_BLANK_POWERDOWN: |
637 | case FB_BLANK_HSYNC_SUSPEND: | 643 | case FB_BLANK_HSYNC_SUSPEND: |
@@ -677,13 +683,10 @@ EXPORT_SYMBOL_GPL(ps3fb_wait_for_vsync); | |||
677 | 683 | ||
678 | void ps3fb_flip_ctl(int on) | 684 | void ps3fb_flip_ctl(int on) |
679 | { | 685 | { |
680 | if (on) { | 686 | if (on) |
681 | if (atomic_read(&ps3fb.ext_flip) > 0) { | 687 | atomic_dec_if_positive(&ps3fb.ext_flip); |
682 | atomic_dec(&ps3fb.ext_flip); | 688 | else |
683 | } | ||
684 | } else { | ||
685 | atomic_inc(&ps3fb.ext_flip); | 689 | atomic_inc(&ps3fb.ext_flip); |
686 | } | ||
687 | } | 690 | } |
688 | 691 | ||
689 | EXPORT_SYMBOL_GPL(ps3fb_flip_ctl); | 692 | EXPORT_SYMBOL_GPL(ps3fb_flip_ctl); |
@@ -732,6 +735,11 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
732 | if (copy_from_user(&val, argp, sizeof(val))) | 735 | if (copy_from_user(&val, argp, sizeof(val))) |
733 | break; | 736 | break; |
734 | 737 | ||
738 | if (!(val & PS3AV_MODE_MASK)) { | ||
739 | u32 id = ps3av_get_auto_mode(0); | ||
740 | if (id > 0) | ||
741 | val = (val & ~PS3AV_MODE_MASK) | id; | ||
742 | } | ||
735 | DPRINTK("PS3FB_IOCTL_SETMODE:%x\n", val); | 743 | DPRINTK("PS3FB_IOCTL_SETMODE:%x\n", val); |
736 | retval = -EINVAL; | 744 | retval = -EINVAL; |
737 | old_mode = ps3fb_mode; | 745 | old_mode = ps3fb_mode; |
@@ -783,8 +791,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
783 | 791 | ||
784 | case PS3FB_IOCTL_OFF: | 792 | case PS3FB_IOCTL_OFF: |
785 | DPRINTK("PS3FB_IOCTL_OFF:\n"); | 793 | DPRINTK("PS3FB_IOCTL_OFF:\n"); |
786 | if (atomic_read(&ps3fb.ext_flip) > 0) | 794 | atomic_dec_if_positive(&ps3fb.ext_flip); |
787 | atomic_dec(&ps3fb.ext_flip); | ||
788 | retval = 0; | 795 | retval = 0; |
789 | break; | 796 | break; |
790 | 797 | ||
@@ -805,11 +812,14 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
805 | 812 | ||
806 | static int ps3fbd(void *arg) | 813 | static int ps3fbd(void *arg) |
807 | { | 814 | { |
808 | daemonize("ps3fbd"); | 815 | while (!kthread_should_stop()) { |
809 | for (;;) { | 816 | try_to_freeze(); |
810 | down(&ps3fb.sem); | 817 | set_current_state(TASK_INTERRUPTIBLE); |
811 | if (atomic_read(&ps3fb.ext_flip) == 0) | 818 | if (ps3fb.is_kicked) { |
819 | ps3fb.is_kicked = 0; | ||
812 | ps3fb_sync(0); /* single buffer */ | 820 | ps3fb_sync(0); /* single buffer */ |
821 | } | ||
822 | schedule(); | ||
813 | } | 823 | } |
814 | return 0; | 824 | return 0; |
815 | } | 825 | } |
@@ -823,15 +833,18 @@ static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr) | |||
823 | status = lv1_gpu_context_intr(ps3fb.context_handle, &v1); | 833 | status = lv1_gpu_context_intr(ps3fb.context_handle, &v1); |
824 | if (status) { | 834 | if (status) { |
825 | printk(KERN_ERR "%s: lv1_gpu_context_intr failed: %d\n", | 835 | printk(KERN_ERR "%s: lv1_gpu_context_intr failed: %d\n", |
826 | __FUNCTION__, status); | 836 | __func__, status); |
827 | return IRQ_NONE; | 837 | return IRQ_NONE; |
828 | } | 838 | } |
829 | 839 | ||
830 | if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) { | 840 | if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) { |
831 | /* VSYNC */ | 841 | /* VSYNC */ |
832 | ps3fb.vblank_count = head->vblank_count; | 842 | ps3fb.vblank_count = head->vblank_count; |
833 | if (!ps3fb.is_blanked) | 843 | if (ps3fb.task && !ps3fb.is_blanked && |
834 | up(&ps3fb.sem); | 844 | !atomic_read(&ps3fb.ext_flip)) { |
845 | ps3fb.is_kicked = 1; | ||
846 | wake_up_process(ps3fb.task); | ||
847 | } | ||
835 | wake_up_interruptible(&ps3fb.wait_vsync); | 848 | wake_up_interruptible(&ps3fb.wait_vsync); |
836 | } | 849 | } |
837 | 850 | ||
@@ -879,7 +892,7 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev) | |||
879 | dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000); | 892 | dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000); |
880 | 893 | ||
881 | if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) { | 894 | if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) { |
882 | printk(KERN_ERR "%s: version_driver err:%x\n", __FUNCTION__, | 895 | printk(KERN_ERR "%s: version_driver err:%x\n", __func__, |
883 | dinfo->version_driver); | 896 | dinfo->version_driver); |
884 | return -EINVAL; | 897 | return -EINVAL; |
885 | } | 898 | } |
@@ -888,7 +901,7 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev) | |||
888 | error = ps3_alloc_irq(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet, | 901 | error = ps3_alloc_irq(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet, |
889 | &ps3fb.irq_no); | 902 | &ps3fb.irq_no); |
890 | if (error) { | 903 | if (error) { |
891 | printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __FUNCTION__, | 904 | printk(KERN_ERR "%s: ps3_alloc_irq failed %d\n", __func__, |
892 | error); | 905 | error); |
893 | return error; | 906 | return error; |
894 | } | 907 | } |
@@ -896,7 +909,7 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev) | |||
896 | error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED, | 909 | error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED, |
897 | "ps3fb vsync", ps3fb.dev); | 910 | "ps3fb vsync", ps3fb.dev); |
898 | if (error) { | 911 | if (error) { |
899 | printk(KERN_ERR "%s: request_irq failed %d\n", __FUNCTION__, | 912 | printk(KERN_ERR "%s: request_irq failed %d\n", __func__, |
900 | error); | 913 | error); |
901 | ps3_free_irq(ps3fb.irq_no); | 914 | ps3_free_irq(ps3fb.irq_no); |
902 | return error; | 915 | return error; |
@@ -915,7 +928,7 @@ static int ps3fb_xdr_settings(u64 xdr_lpar) | |||
915 | xdr_lpar, ps3fb_videomemory.size, 0); | 928 | xdr_lpar, ps3fb_videomemory.size, 0); |
916 | if (status) { | 929 | if (status) { |
917 | printk(KERN_ERR "%s: lv1_gpu_context_iomap failed: %d\n", | 930 | printk(KERN_ERR "%s: lv1_gpu_context_iomap failed: %d\n", |
918 | __FUNCTION__, status); | 931 | __func__, status); |
919 | return -ENXIO; | 932 | return -ENXIO; |
920 | } | 933 | } |
921 | DPRINTK("video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n", | 934 | DPRINTK("video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n", |
@@ -927,8 +940,9 @@ static int ps3fb_xdr_settings(u64 xdr_lpar) | |||
927 | xdr_lpar, ps3fb_videomemory.size, | 940 | xdr_lpar, ps3fb_videomemory.size, |
928 | GPU_IOIF, 0); | 941 | GPU_IOIF, 0); |
929 | if (status) { | 942 | if (status) { |
930 | printk(KERN_ERR "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n", | 943 | printk(KERN_ERR |
931 | __FUNCTION__, status); | 944 | "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n", |
945 | __func__, status); | ||
932 | return -ENXIO; | 946 | return -ENXIO; |
933 | } | 947 | } |
934 | return 0; | 948 | return 0; |
@@ -968,13 +982,14 @@ static int __init ps3fb_probe(struct platform_device *dev) | |||
968 | u64 xdr_lpar; | 982 | u64 xdr_lpar; |
969 | int status; | 983 | int status; |
970 | unsigned long offset; | 984 | unsigned long offset; |
985 | struct task_struct *task; | ||
971 | 986 | ||
972 | /* get gpu context handle */ | 987 | /* get gpu context handle */ |
973 | status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0, | 988 | status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0, |
974 | &ps3fb.memory_handle, &ddr_lpar); | 989 | &ps3fb.memory_handle, &ddr_lpar); |
975 | if (status) { | 990 | if (status) { |
976 | printk(KERN_ERR "%s: lv1_gpu_memory_allocate failed: %d\n", | 991 | printk(KERN_ERR "%s: lv1_gpu_memory_allocate failed: %d\n", |
977 | __FUNCTION__, status); | 992 | __func__, status); |
978 | goto err; | 993 | goto err; |
979 | } | 994 | } |
980 | DPRINTK("ddr:lpar:0x%lx\n", ddr_lpar); | 995 | DPRINTK("ddr:lpar:0x%lx\n", ddr_lpar); |
@@ -985,14 +1000,14 @@ static int __init ps3fb_probe(struct platform_device *dev) | |||
985 | &lpar_reports, &lpar_reports_size); | 1000 | &lpar_reports, &lpar_reports_size); |
986 | if (status) { | 1001 | if (status) { |
987 | printk(KERN_ERR "%s: lv1_gpu_context_attribute failed: %d\n", | 1002 | printk(KERN_ERR "%s: lv1_gpu_context_attribute failed: %d\n", |
988 | __FUNCTION__, status); | 1003 | __func__, status); |
989 | goto err_gpu_memory_free; | 1004 | goto err_gpu_memory_free; |
990 | } | 1005 | } |
991 | 1006 | ||
992 | /* vsync interrupt */ | 1007 | /* vsync interrupt */ |
993 | ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024); | 1008 | ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024); |
994 | if (!ps3fb.dinfo) { | 1009 | if (!ps3fb.dinfo) { |
995 | printk(KERN_ERR "%s: ioremap failed\n", __FUNCTION__); | 1010 | printk(KERN_ERR "%s: ioremap failed\n", __func__); |
996 | goto err_gpu_context_free; | 1011 | goto err_gpu_context_free; |
997 | } | 1012 | } |
998 | 1013 | ||
@@ -1050,9 +1065,18 @@ static int __init ps3fb_probe(struct platform_device *dev) | |||
1050 | "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n", | 1065 | "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n", |
1051 | info->node, ps3fb_videomemory.size >> 10); | 1066 | info->node, ps3fb_videomemory.size >> 10); |
1052 | 1067 | ||
1053 | kernel_thread(ps3fbd, info, CLONE_KERNEL); | 1068 | task = kthread_run(ps3fbd, info, "ps3fbd"); |
1069 | if (IS_ERR(task)) { | ||
1070 | retval = PTR_ERR(task); | ||
1071 | goto err_unregister_framebuffer; | ||
1072 | } | ||
1073 | |||
1074 | ps3fb.task = task; | ||
1075 | |||
1054 | return 0; | 1076 | return 0; |
1055 | 1077 | ||
1078 | err_unregister_framebuffer: | ||
1079 | unregister_framebuffer(info); | ||
1056 | err_fb_dealloc: | 1080 | err_fb_dealloc: |
1057 | fb_dealloc_cmap(&info->cmap); | 1081 | fb_dealloc_cmap(&info->cmap); |
1058 | err_framebuffer_release: | 1082 | err_framebuffer_release: |
@@ -1083,6 +1107,11 @@ void ps3fb_cleanup(void) | |||
1083 | { | 1107 | { |
1084 | int status; | 1108 | int status; |
1085 | 1109 | ||
1110 | if (ps3fb.task) { | ||
1111 | struct task_struct *task = ps3fb.task; | ||
1112 | ps3fb.task = NULL; | ||
1113 | kthread_stop(task); | ||
1114 | } | ||
1086 | if (ps3fb.irq_no) { | 1115 | if (ps3fb.irq_no) { |
1087 | free_irq(ps3fb.irq_no, ps3fb.dev); | 1116 | free_irq(ps3fb.irq_no, ps3fb.dev); |
1088 | ps3_free_irq(ps3fb.irq_no); | 1117 | ps3_free_irq(ps3fb.irq_no); |
@@ -1137,8 +1166,9 @@ int ps3fb_set_sync(void) | |||
1137 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, | 1166 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, |
1138 | 0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); | 1167 | 0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); |
1139 | if (status) { | 1168 | if (status) { |
1140 | printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n", | 1169 | printk(KERN_ERR |
1141 | __FUNCTION__, status); | 1170 | "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n", |
1171 | __func__, status); | ||
1142 | return -1; | 1172 | return -1; |
1143 | } | 1173 | } |
1144 | #endif | 1174 | #endif |
@@ -1148,8 +1178,9 @@ int ps3fb_set_sync(void) | |||
1148 | 1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); | 1178 | 1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); |
1149 | 1179 | ||
1150 | if (status) { | 1180 | if (status) { |
1151 | printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n", | 1181 | printk(KERN_ERR |
1152 | __FUNCTION__, status); | 1182 | "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n", |
1183 | __func__, status); | ||
1153 | return -1; | 1184 | return -1; |
1154 | } | 1185 | } |
1155 | #endif | 1186 | #endif |
@@ -1174,7 +1205,7 @@ static int __init ps3fb_init(void) | |||
1174 | 1205 | ||
1175 | error = ps3av_dev_open(); | 1206 | error = ps3av_dev_open(); |
1176 | if (error) { | 1207 | if (error) { |
1177 | printk(KERN_ERR "%s: ps3av_dev_open failed\n", __FUNCTION__); | 1208 | printk(KERN_ERR "%s: ps3av_dev_open failed\n", __func__); |
1178 | goto err; | 1209 | goto err; |
1179 | } | 1210 | } |
1180 | 1211 | ||
@@ -1195,7 +1226,6 @@ static int __init ps3fb_init(void) | |||
1195 | 1226 | ||
1196 | atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ | 1227 | atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ |
1197 | atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ | 1228 | atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ |
1198 | init_MUTEX(&ps3fb.sem); | ||
1199 | init_waitqueue_head(&ps3fb.wait_vsync); | 1229 | init_waitqueue_head(&ps3fb.wait_vsync); |
1200 | ps3fb.num_frames = 1; | 1230 | ps3fb.num_frames = 1; |
1201 | 1231 | ||
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 69f3b264a22e..c97709ecbad0 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c | |||
@@ -64,7 +64,6 @@ | |||
64 | #include <linux/fb.h> | 64 | #include <linux/fb.h> |
65 | #include <linux/init.h> | 65 | #include <linux/init.h> |
66 | #include <linux/ioport.h> | 66 | #include <linux/ioport.h> |
67 | #include <linux/pci.h> | ||
68 | 67 | ||
69 | #include <asm/grfioctl.h> /* for HP-UX compatibility */ | 68 | #include <asm/grfioctl.h> /* for HP-UX compatibility */ |
70 | #include <asm/uaccess.h> | 69 | #include <asm/uaccess.h> |
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 06fc19a61192..ad66f070acb8 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c | |||
@@ -51,7 +51,6 @@ | |||
51 | #include <linux/fb.h> | 51 | #include <linux/fb.h> |
52 | #include <linux/selection.h> | 52 | #include <linux/selection.h> |
53 | #include <linux/init.h> | 53 | #include <linux/init.h> |
54 | #include <linux/pci.h> | ||
55 | #include <linux/nvram.h> | 54 | #include <linux/nvram.h> |
56 | #include <linux/adb.h> | 55 | #include <linux/adb.h> |
57 | #include <linux/cuda.h> | 56 | #include <linux/cuda.h> |
diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c index b3ce8859a586..2ce4cebc31d9 100644 --- a/drivers/zorro/proc.c +++ b/drivers/zorro/proc.c | |||
@@ -90,8 +90,9 @@ get_zorro_dev_info(char *buf, char **start, off_t pos, int count) | |||
90 | for (slot = cnt = 0; slot < zorro_num_autocon && count > cnt; slot++) { | 90 | for (slot = cnt = 0; slot < zorro_num_autocon && count > cnt; slot++) { |
91 | struct zorro_dev *z = &zorro_autocon[slot]; | 91 | struct zorro_dev *z = &zorro_autocon[slot]; |
92 | len = sprintf(buf, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot, | 92 | len = sprintf(buf, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot, |
93 | z->id, zorro_resource_start(z), | 93 | z->id, (unsigned long)zorro_resource_start(z), |
94 | zorro_resource_len(z), z->rom.er_Type); | 94 | (unsigned long)zorro_resource_len(z), |
95 | z->rom.er_Type); | ||
95 | at += len; | 96 | at += len; |
96 | if (at >= pos) { | 97 | if (at >= pos) { |
97 | if (!*start) { | 98 | if (!*start) { |
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index 87c29d7b6c17..c3ba0ec334c4 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c | |||
@@ -42,7 +42,8 @@ static ssize_t zorro_show_resource(struct device *dev, struct device_attribute * | |||
42 | struct zorro_dev *z = to_zorro_dev(dev); | 42 | struct zorro_dev *z = to_zorro_dev(dev); |
43 | 43 | ||
44 | return sprintf(buf, "0x%08lx 0x%08lx 0x%08lx\n", | 44 | return sprintf(buf, "0x%08lx 0x%08lx 0x%08lx\n", |
45 | zorro_resource_start(z), zorro_resource_end(z), | 45 | (unsigned long)zorro_resource_start(z), |
46 | (unsigned long)zorro_resource_end(z), | ||
46 | zorro_resource_flags(z)); | 47 | zorro_resource_flags(z)); |
47 | } | 48 | } |
48 | 49 | ||
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index 0f2b40605b06..4cc42b64820c 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c | |||
@@ -164,7 +164,8 @@ static int __init zorro_init(void) | |||
164 | if (request_resource(zorro_find_parent_resource(z), &z->resource)) | 164 | if (request_resource(zorro_find_parent_resource(z), &z->resource)) |
165 | printk(KERN_ERR "Zorro: Address space collision on device %s " | 165 | printk(KERN_ERR "Zorro: Address space collision on device %s " |
166 | "[%lx:%lx]\n", | 166 | "[%lx:%lx]\n", |
167 | z->name, zorro_resource_start(z), zorro_resource_end(z)); | 167 | z->name, (unsigned long)zorro_resource_start(z), |
168 | (unsigned long)zorro_resource_end(z)); | ||
168 | sprintf(z->dev.bus_id, "%02x", i); | 169 | sprintf(z->dev.bus_id, "%02x", i); |
169 | z->dev.parent = &zorro_bus.dev; | 170 | z->dev.parent = &zorro_bus.dev; |
170 | z->dev.bus = &zorro_bus_type; | 171 | z->dev.bus = &zorro_bus_type; |