diff options
Diffstat (limited to 'drivers')
127 files changed, 11015 insertions, 4531 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 652281402c92..5bfa2e9a7c26 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -28,6 +28,7 @@ enum { | |||
28 | FW_STATUS_DONE, | 28 | FW_STATUS_DONE, |
29 | FW_STATUS_ABORT, | 29 | FW_STATUS_ABORT, |
30 | FW_STATUS_READY, | 30 | FW_STATUS_READY, |
31 | FW_STATUS_READY_NOHOTPLUG, | ||
31 | }; | 32 | }; |
32 | 33 | ||
33 | static int loading_timeout = 10; /* In seconds */ | 34 | static int loading_timeout = 10; /* In seconds */ |
@@ -344,7 +345,7 @@ error_kfree: | |||
344 | 345 | ||
345 | static int | 346 | static int |
346 | fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, | 347 | fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, |
347 | const char *fw_name, struct device *device) | 348 | const char *fw_name, struct device *device, int hotplug) |
348 | { | 349 | { |
349 | struct class_device *class_dev; | 350 | struct class_device *class_dev; |
350 | struct firmware_priv *fw_priv; | 351 | struct firmware_priv *fw_priv; |
@@ -376,7 +377,10 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, | |||
376 | goto error_unreg; | 377 | goto error_unreg; |
377 | } | 378 | } |
378 | 379 | ||
379 | set_bit(FW_STATUS_READY, &fw_priv->status); | 380 | if (hotplug) |
381 | set_bit(FW_STATUS_READY, &fw_priv->status); | ||
382 | else | ||
383 | set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status); | ||
380 | *class_dev_p = class_dev; | 384 | *class_dev_p = class_dev; |
381 | goto out; | 385 | goto out; |
382 | 386 | ||
@@ -386,21 +390,9 @@ out: | |||
386 | return retval; | 390 | return retval; |
387 | } | 391 | } |
388 | 392 | ||
389 | /** | 393 | static int |
390 | * request_firmware: - request firmware to hotplug and wait for it | 394 | _request_firmware(const struct firmware **firmware_p, const char *name, |
391 | * Description: | 395 | struct device *device, int hotplug) |
392 | * @firmware will be used to return a firmware image by the name | ||
393 | * of @name for device @device. | ||
394 | * | ||
395 | * Should be called from user context where sleeping is allowed. | ||
396 | * | ||
397 | * @name will be use as $FIRMWARE in the hotplug environment and | ||
398 | * should be distinctive enough not to be confused with any other | ||
399 | * firmware image for this or any other device. | ||
400 | **/ | ||
401 | int | ||
402 | request_firmware(const struct firmware **firmware_p, const char *name, | ||
403 | struct device *device) | ||
404 | { | 396 | { |
405 | struct class_device *class_dev; | 397 | struct class_device *class_dev; |
406 | struct firmware_priv *fw_priv; | 398 | struct firmware_priv *fw_priv; |
@@ -419,22 +411,25 @@ request_firmware(const struct firmware **firmware_p, const char *name, | |||
419 | } | 411 | } |
420 | memset(firmware, 0, sizeof (*firmware)); | 412 | memset(firmware, 0, sizeof (*firmware)); |
421 | 413 | ||
422 | retval = fw_setup_class_device(firmware, &class_dev, name, device); | 414 | retval = fw_setup_class_device(firmware, &class_dev, name, device, |
415 | hotplug); | ||
423 | if (retval) | 416 | if (retval) |
424 | goto error_kfree_fw; | 417 | goto error_kfree_fw; |
425 | 418 | ||
426 | fw_priv = class_get_devdata(class_dev); | 419 | fw_priv = class_get_devdata(class_dev); |
427 | 420 | ||
428 | if (loading_timeout > 0) { | 421 | if (hotplug) { |
429 | fw_priv->timeout.expires = jiffies + loading_timeout * HZ; | 422 | if (loading_timeout > 0) { |
430 | add_timer(&fw_priv->timeout); | 423 | fw_priv->timeout.expires = jiffies + loading_timeout * HZ; |
431 | } | 424 | add_timer(&fw_priv->timeout); |
432 | 425 | } | |
433 | kobject_hotplug(&class_dev->kobj, KOBJ_ADD); | ||
434 | wait_for_completion(&fw_priv->completion); | ||
435 | set_bit(FW_STATUS_DONE, &fw_priv->status); | ||
436 | 426 | ||
437 | del_timer_sync(&fw_priv->timeout); | 427 | kobject_hotplug(&class_dev->kobj, KOBJ_ADD); |
428 | wait_for_completion(&fw_priv->completion); | ||
429 | set_bit(FW_STATUS_DONE, &fw_priv->status); | ||
430 | del_timer_sync(&fw_priv->timeout); | ||
431 | } else | ||
432 | wait_for_completion(&fw_priv->completion); | ||
438 | 433 | ||
439 | down(&fw_lock); | 434 | down(&fw_lock); |
440 | if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) { | 435 | if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) { |
@@ -455,6 +450,26 @@ out: | |||
455 | } | 450 | } |
456 | 451 | ||
457 | /** | 452 | /** |
453 | * request_firmware: - request firmware to hotplug and wait for it | ||
454 | * Description: | ||
455 | * @firmware will be used to return a firmware image by the name | ||
456 | * of @name for device @device. | ||
457 | * | ||
458 | * Should be called from user context where sleeping is allowed. | ||
459 | * | ||
460 | * @name will be use as $FIRMWARE in the hotplug environment and | ||
461 | * should be distinctive enough not to be confused with any other | ||
462 | * firmware image for this or any other device. | ||
463 | **/ | ||
464 | int | ||
465 | request_firmware(const struct firmware **firmware_p, const char *name, | ||
466 | struct device *device) | ||
467 | { | ||
468 | int hotplug = 1; | ||
469 | return _request_firmware(firmware_p, name, device, hotplug); | ||
470 | } | ||
471 | |||
472 | /** | ||
458 | * release_firmware: - release the resource associated with a firmware image | 473 | * release_firmware: - release the resource associated with a firmware image |
459 | **/ | 474 | **/ |
460 | void | 475 | void |
@@ -491,6 +506,7 @@ struct firmware_work { | |||
491 | struct device *device; | 506 | struct device *device; |
492 | void *context; | 507 | void *context; |
493 | void (*cont)(const struct firmware *fw, void *context); | 508 | void (*cont)(const struct firmware *fw, void *context); |
509 | int hotplug; | ||
494 | }; | 510 | }; |
495 | 511 | ||
496 | static int | 512 | static int |
@@ -503,7 +519,8 @@ request_firmware_work_func(void *arg) | |||
503 | return 0; | 519 | return 0; |
504 | } | 520 | } |
505 | daemonize("%s/%s", "firmware", fw_work->name); | 521 | daemonize("%s/%s", "firmware", fw_work->name); |
506 | request_firmware(&fw, fw_work->name, fw_work->device); | 522 | _request_firmware(&fw, fw_work->name, fw_work->device, |
523 | fw_work->hotplug); | ||
507 | fw_work->cont(fw, fw_work->context); | 524 | fw_work->cont(fw, fw_work->context); |
508 | release_firmware(fw); | 525 | release_firmware(fw); |
509 | module_put(fw_work->module); | 526 | module_put(fw_work->module); |
@@ -518,6 +535,9 @@ request_firmware_work_func(void *arg) | |||
518 | * Asynchronous variant of request_firmware() for contexts where | 535 | * Asynchronous variant of request_firmware() for contexts where |
519 | * it is not possible to sleep. | 536 | * it is not possible to sleep. |
520 | * | 537 | * |
538 | * @hotplug invokes hotplug event to copy the firmware image if this flag | ||
539 | * is non-zero else the firmware copy must be done manually. | ||
540 | * | ||
521 | * @cont will be called asynchronously when the firmware request is over. | 541 | * @cont will be called asynchronously when the firmware request is over. |
522 | * | 542 | * |
523 | * @context will be passed over to @cont. | 543 | * @context will be passed over to @cont. |
@@ -527,7 +547,7 @@ request_firmware_work_func(void *arg) | |||
527 | **/ | 547 | **/ |
528 | int | 548 | int |
529 | request_firmware_nowait( | 549 | request_firmware_nowait( |
530 | struct module *module, | 550 | struct module *module, int hotplug, |
531 | const char *name, struct device *device, void *context, | 551 | const char *name, struct device *device, void *context, |
532 | void (*cont)(const struct firmware *fw, void *context)) | 552 | void (*cont)(const struct firmware *fw, void *context)) |
533 | { | 553 | { |
@@ -548,6 +568,7 @@ request_firmware_nowait( | |||
548 | .device = device, | 568 | .device = device, |
549 | .context = context, | 569 | .context = context, |
550 | .cont = cont, | 570 | .cont = cont, |
571 | .hotplug = hotplug, | ||
551 | }; | 572 | }; |
552 | 573 | ||
553 | ret = kernel_thread(request_firmware_work_func, fw_work, | 574 | ret = kernel_thread(request_firmware_work_func, fw_work, |
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 6e231c5a1199..ded33ba31acc 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c | |||
@@ -35,7 +35,7 @@ aoedev_newdev(ulong nframes) | |||
35 | struct aoedev *d; | 35 | struct aoedev *d; |
36 | struct frame *f, *e; | 36 | struct frame *f, *e; |
37 | 37 | ||
38 | d = kcalloc(1, sizeof *d, GFP_ATOMIC); | 38 | d = kzalloc(sizeof *d, GFP_ATOMIC); |
39 | if (d == NULL) | 39 | if (d == NULL) |
40 | return NULL; | 40 | return NULL; |
41 | f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); | 41 | f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); |
diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c index cd056e7e64ec..30c0903c7cdd 100644 --- a/drivers/block/cfq-iosched.c +++ b/drivers/block/cfq-iosched.c | |||
@@ -2260,8 +2260,6 @@ static void cfq_put_cfqd(struct cfq_data *cfqd) | |||
2260 | if (!atomic_dec_and_test(&cfqd->ref)) | 2260 | if (!atomic_dec_and_test(&cfqd->ref)) |
2261 | return; | 2261 | return; |
2262 | 2262 | ||
2263 | blk_put_queue(q); | ||
2264 | |||
2265 | cfq_shutdown_timer_wq(cfqd); | 2263 | cfq_shutdown_timer_wq(cfqd); |
2266 | q->elevator->elevator_data = NULL; | 2264 | q->elevator->elevator_data = NULL; |
2267 | 2265 | ||
@@ -2318,7 +2316,6 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e) | |||
2318 | e->elevator_data = cfqd; | 2316 | e->elevator_data = cfqd; |
2319 | 2317 | ||
2320 | cfqd->queue = q; | 2318 | cfqd->queue = q; |
2321 | atomic_inc(&q->refcnt); | ||
2322 | 2319 | ||
2323 | cfqd->max_queued = q->nr_requests / 4; | 2320 | cfqd->max_queued = q->nr_requests / 4; |
2324 | q->nr_batching = cfq_queued; | 2321 | q->nr_batching = cfq_queued; |
diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c index ff5201e02153..24594c57c323 100644 --- a/drivers/block/deadline-iosched.c +++ b/drivers/block/deadline-iosched.c | |||
@@ -507,18 +507,12 @@ static int deadline_dispatch_requests(struct deadline_data *dd) | |||
507 | const int reads = !list_empty(&dd->fifo_list[READ]); | 507 | const int reads = !list_empty(&dd->fifo_list[READ]); |
508 | const int writes = !list_empty(&dd->fifo_list[WRITE]); | 508 | const int writes = !list_empty(&dd->fifo_list[WRITE]); |
509 | struct deadline_rq *drq; | 509 | struct deadline_rq *drq; |
510 | int data_dir, other_dir; | 510 | int data_dir; |
511 | 511 | ||
512 | /* | 512 | /* |
513 | * batches are currently reads XOR writes | 513 | * batches are currently reads XOR writes |
514 | */ | 514 | */ |
515 | drq = NULL; | 515 | drq = dd->next_drq[WRITE] ? : dd->next_drq[READ]; |
516 | |||
517 | if (dd->next_drq[READ]) | ||
518 | drq = dd->next_drq[READ]; | ||
519 | |||
520 | if (dd->next_drq[WRITE]) | ||
521 | drq = dd->next_drq[WRITE]; | ||
522 | 516 | ||
523 | if (drq) { | 517 | if (drq) { |
524 | /* we have a "next request" */ | 518 | /* we have a "next request" */ |
@@ -544,7 +538,6 @@ static int deadline_dispatch_requests(struct deadline_data *dd) | |||
544 | goto dispatch_writes; | 538 | goto dispatch_writes; |
545 | 539 | ||
546 | data_dir = READ; | 540 | data_dir = READ; |
547 | other_dir = WRITE; | ||
548 | 541 | ||
549 | goto dispatch_find_request; | 542 | goto dispatch_find_request; |
550 | } | 543 | } |
@@ -560,7 +553,6 @@ dispatch_writes: | |||
560 | dd->starved = 0; | 553 | dd->starved = 0; |
561 | 554 | ||
562 | data_dir = WRITE; | 555 | data_dir = WRITE; |
563 | other_dir = READ; | ||
564 | 556 | ||
565 | goto dispatch_find_request; | 557 | goto dispatch_find_request; |
566 | } | 558 | } |
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index 47fd3659a061..d42840cc0d1d 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c | |||
@@ -45,7 +45,7 @@ int get_blkdev_list(char *p, int used) | |||
45 | struct blk_major_name *n; | 45 | struct blk_major_name *n; |
46 | int i, len; | 46 | int i, len; |
47 | 47 | ||
48 | len = sprintf(p, "\nBlock devices:\n"); | 48 | len = snprintf(p, (PAGE_SIZE-used), "\nBlock devices:\n"); |
49 | 49 | ||
50 | down(&block_subsys_sem); | 50 | down(&block_subsys_sem); |
51 | for (i = 0; i < ARRAY_SIZE(major_names); i++) { | 51 | for (i = 0; i < ARRAY_SIZE(major_names); i++) { |
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 3c818544475e..b4b17958d101 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c | |||
@@ -235,8 +235,8 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn) | |||
235 | * set defaults | 235 | * set defaults |
236 | */ | 236 | */ |
237 | q->nr_requests = BLKDEV_MAX_RQ; | 237 | q->nr_requests = BLKDEV_MAX_RQ; |
238 | q->max_phys_segments = MAX_PHYS_SEGMENTS; | 238 | blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS); |
239 | q->max_hw_segments = MAX_HW_SEGMENTS; | 239 | blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS); |
240 | q->make_request_fn = mfn; | 240 | q->make_request_fn = mfn; |
241 | q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; | 241 | q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; |
242 | q->backing_dev_info.state = 0; | 242 | q->backing_dev_info.state = 0; |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index a1de06d76de6..2bc9d64db106 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -138,7 +138,7 @@ config CYZ_INTR | |||
138 | 138 | ||
139 | config DIGIEPCA | 139 | config DIGIEPCA |
140 | tristate "Digiboard Intelligent Async Support" | 140 | tristate "Digiboard Intelligent Async Support" |
141 | depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP && (!64BIT || BROKEN) | 141 | depends on SERIAL_NONSTANDARD |
142 | ---help--- | 142 | ---help--- |
143 | This is a driver for Digi International's Xx, Xeve, and Xem series | 143 | This is a driver for Digi International's Xx, Xeve, and Xem series |
144 | of cards which provide multiple serial ports. You would need | 144 | of cards which provide multiple serial ports. You would need |
diff --git a/drivers/char/digi1.h b/drivers/char/digi1.h index 184378d23f8c..94d4eab5d3ca 100644 --- a/drivers/char/digi1.h +++ b/drivers/char/digi1.h | |||
@@ -1,46 +1,46 @@ | |||
1 | /* Definitions for DigiBoard ditty(1) command. */ | 1 | /* Definitions for DigiBoard ditty(1) command. */ |
2 | 2 | ||
3 | #if !defined(TIOCMODG) | 3 | #if !defined(TIOCMODG) |
4 | #define TIOCMODG ('d'<<8) | 250 /* get modem ctrl state */ | 4 | #define TIOCMODG (('d'<<8) | 250) /* get modem ctrl state */ |
5 | #define TIOCMODS ('d'<<8) | 251 /* set modem ctrl state */ | 5 | #define TIOCMODS (('d'<<8) | 251) /* set modem ctrl state */ |
6 | #endif | 6 | #endif |
7 | 7 | ||
8 | #if !defined(TIOCMSET) | 8 | #if !defined(TIOCMSET) |
9 | #define TIOCMSET ('d'<<8) | 252 /* set modem ctrl state */ | 9 | #define TIOCMSET (('d'<<8) | 252) /* set modem ctrl state */ |
10 | #define TIOCMGET ('d'<<8) | 253 /* set modem ctrl state */ | 10 | #define TIOCMGET (('d'<<8) | 253) /* set modem ctrl state */ |
11 | #endif | 11 | #endif |
12 | 12 | ||
13 | #if !defined(TIOCMBIC) | 13 | #if !defined(TIOCMBIC) |
14 | #define TIOCMBIC ('d'<<8) | 254 /* set modem ctrl state */ | 14 | #define TIOCMBIC (('d'<<8) | 254) /* set modem ctrl state */ |
15 | #define TIOCMBIS ('d'<<8) | 255 /* set modem ctrl state */ | 15 | #define TIOCMBIS (('d'<<8) | 255) /* set modem ctrl state */ |
16 | #endif | 16 | #endif |
17 | 17 | ||
18 | #if !defined(TIOCSDTR) | 18 | #if !defined(TIOCSDTR) |
19 | #define TIOCSDTR ('e'<<8) | 0 /* set DTR */ | 19 | #define TIOCSDTR (('e'<<8) | 0) /* set DTR */ |
20 | #define TIOCCDTR ('e'<<8) | 1 /* clear DTR */ | 20 | #define TIOCCDTR (('e'<<8) | 1) /* clear DTR */ |
21 | #endif | 21 | #endif |
22 | 22 | ||
23 | /************************************************************************ | 23 | /************************************************************************ |
24 | * Ioctl command arguments for DIGI parameters. | 24 | * Ioctl command arguments for DIGI parameters. |
25 | ************************************************************************/ | 25 | ************************************************************************/ |
26 | #define DIGI_GETA ('e'<<8) | 94 /* Read params */ | 26 | #define DIGI_GETA (('e'<<8) | 94) /* Read params */ |
27 | 27 | ||
28 | #define DIGI_SETA ('e'<<8) | 95 /* Set params */ | 28 | #define DIGI_SETA (('e'<<8) | 95) /* Set params */ |
29 | #define DIGI_SETAW ('e'<<8) | 96 /* Drain & set params */ | 29 | #define DIGI_SETAW (('e'<<8) | 96) /* Drain & set params */ |
30 | #define DIGI_SETAF ('e'<<8) | 97 /* Drain, flush & set params */ | 30 | #define DIGI_SETAF (('e'<<8) | 97) /* Drain, flush & set params */ |
31 | 31 | ||
32 | #define DIGI_GETFLOW ('e'<<8) | 99 /* Get startc/stopc flow */ | 32 | #define DIGI_GETFLOW (('e'<<8) | 99) /* Get startc/stopc flow */ |
33 | /* control characters */ | 33 | /* control characters */ |
34 | #define DIGI_SETFLOW ('e'<<8) | 100 /* Set startc/stopc flow */ | 34 | #define DIGI_SETFLOW (('e'<<8) | 100) /* Set startc/stopc flow */ |
35 | /* control characters */ | 35 | /* control characters */ |
36 | #define DIGI_GETAFLOW ('e'<<8) | 101 /* Get Aux. startc/stopc */ | 36 | #define DIGI_GETAFLOW (('e'<<8) | 101) /* Get Aux. startc/stopc */ |
37 | /* flow control chars */ | 37 | /* flow control chars */ |
38 | #define DIGI_SETAFLOW ('e'<<8) | 102 /* Set Aux. startc/stopc */ | 38 | #define DIGI_SETAFLOW (('e'<<8) | 102) /* Set Aux. startc/stopc */ |
39 | /* flow control chars */ | 39 | /* flow control chars */ |
40 | 40 | ||
41 | #define DIGI_GETINFO ('e'<<8) | 103 /* Fill in digi_info */ | 41 | #define DIGI_GETINFO (('e'<<8) | 103) /* Fill in digi_info */ |
42 | #define DIGI_POLLER ('e'<<8) | 104 /* Turn on/off poller */ | 42 | #define DIGI_POLLER (('e'<<8) | 104) /* Turn on/off poller */ |
43 | #define DIGI_INIT ('e'<<8) | 105 /* Allow things to run. */ | 43 | #define DIGI_INIT (('e'<<8) | 105) /* Allow things to run. */ |
44 | 44 | ||
45 | struct digiflow_struct | 45 | struct digiflow_struct |
46 | { | 46 | { |
diff --git a/drivers/char/digiFep1.h b/drivers/char/digiFep1.h index c47d7fcb8400..3c1f1922c798 100644 --- a/drivers/char/digiFep1.h +++ b/drivers/char/digiFep1.h | |||
@@ -13,88 +13,88 @@ | |||
13 | 13 | ||
14 | struct global_data | 14 | struct global_data |
15 | { | 15 | { |
16 | volatile ushort cin; | 16 | u16 cin; |
17 | volatile ushort cout; | 17 | u16 cout; |
18 | volatile ushort cstart; | 18 | u16 cstart; |
19 | volatile ushort cmax; | 19 | u16 cmax; |
20 | volatile ushort ein; | 20 | u16 ein; |
21 | volatile ushort eout; | 21 | u16 eout; |
22 | volatile ushort istart; | 22 | u16 istart; |
23 | volatile ushort imax; | 23 | u16 imax; |
24 | }; | 24 | }; |
25 | 25 | ||
26 | 26 | ||
27 | struct board_chan | 27 | struct board_chan |
28 | { | 28 | { |
29 | int filler1; | 29 | u32 filler1; |
30 | int filler2; | 30 | u32 filler2; |
31 | volatile ushort tseg; | 31 | u16 tseg; |
32 | volatile ushort tin; | 32 | u16 tin; |
33 | volatile ushort tout; | 33 | u16 tout; |
34 | volatile ushort tmax; | 34 | u16 tmax; |
35 | 35 | ||
36 | volatile ushort rseg; | 36 | u16 rseg; |
37 | volatile ushort rin; | 37 | u16 rin; |
38 | volatile ushort rout; | 38 | u16 rout; |
39 | volatile ushort rmax; | 39 | u16 rmax; |
40 | 40 | ||
41 | volatile ushort tlow; | 41 | u16 tlow; |
42 | volatile ushort rlow; | 42 | u16 rlow; |
43 | volatile ushort rhigh; | 43 | u16 rhigh; |
44 | volatile ushort incr; | 44 | u16 incr; |
45 | 45 | ||
46 | volatile ushort etime; | 46 | u16 etime; |
47 | volatile ushort edelay; | 47 | u16 edelay; |
48 | volatile unchar *dev; | 48 | unchar *dev; |
49 | 49 | ||
50 | volatile ushort iflag; | 50 | u16 iflag; |
51 | volatile ushort oflag; | 51 | u16 oflag; |
52 | volatile ushort cflag; | 52 | u16 cflag; |
53 | volatile ushort gmask; | 53 | u16 gmask; |
54 | 54 | ||
55 | volatile ushort col; | 55 | u16 col; |
56 | volatile ushort delay; | 56 | u16 delay; |
57 | volatile ushort imask; | 57 | u16 imask; |
58 | volatile ushort tflush; | 58 | u16 tflush; |
59 | 59 | ||
60 | int filler3; | 60 | u32 filler3; |
61 | int filler4; | 61 | u32 filler4; |
62 | int filler5; | 62 | u32 filler5; |
63 | int filler6; | 63 | u32 filler6; |
64 | 64 | ||
65 | volatile unchar num; | 65 | u8 num; |
66 | volatile unchar ract; | 66 | u8 ract; |
67 | volatile unchar bstat; | 67 | u8 bstat; |
68 | volatile unchar tbusy; | 68 | u8 tbusy; |
69 | volatile unchar iempty; | 69 | u8 iempty; |
70 | volatile unchar ilow; | 70 | u8 ilow; |
71 | volatile unchar idata; | 71 | u8 idata; |
72 | volatile unchar eflag; | 72 | u8 eflag; |
73 | 73 | ||
74 | volatile unchar tflag; | 74 | u8 tflag; |
75 | volatile unchar rflag; | 75 | u8 rflag; |
76 | volatile unchar xmask; | 76 | u8 xmask; |
77 | volatile unchar xval; | 77 | u8 xval; |
78 | volatile unchar mstat; | 78 | u8 mstat; |
79 | volatile unchar mchange; | 79 | u8 mchange; |
80 | volatile unchar mint; | 80 | u8 mint; |
81 | volatile unchar lstat; | 81 | u8 lstat; |
82 | 82 | ||
83 | volatile unchar mtran; | 83 | u8 mtran; |
84 | volatile unchar orun; | 84 | u8 orun; |
85 | volatile unchar startca; | 85 | u8 startca; |
86 | volatile unchar stopca; | 86 | u8 stopca; |
87 | volatile unchar startc; | 87 | u8 startc; |
88 | volatile unchar stopc; | 88 | u8 stopc; |
89 | volatile unchar vnext; | 89 | u8 vnext; |
90 | volatile unchar hflow; | 90 | u8 hflow; |
91 | 91 | ||
92 | volatile unchar fillc; | 92 | u8 fillc; |
93 | volatile unchar ochar; | 93 | u8 ochar; |
94 | volatile unchar omask; | 94 | u8 omask; |
95 | 95 | ||
96 | unchar filler7; | 96 | u8 filler7; |
97 | unchar filler8[28]; | 97 | u8 filler8[28]; |
98 | }; | 98 | }; |
99 | 99 | ||
100 | 100 | ||
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 6025e1866c7e..58d3738a2b7f 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -6,6 +6,8 @@ | |||
6 | For technical support please email digiLinux@dgii.com or | 6 | For technical support please email digiLinux@dgii.com or |
7 | call Digi tech support at (612) 912-3456 | 7 | call Digi tech support at (612) 912-3456 |
8 | 8 | ||
9 | ** This driver is no longer supported by Digi ** | ||
10 | |||
9 | Much of this design and code came from epca.c which was | 11 | Much of this design and code came from epca.c which was |
10 | copyright (C) 1994, 1995 Troy De Jongh, and subsquently | 12 | copyright (C) 1994, 1995 Troy De Jongh, and subsquently |
11 | modified by David Nugent, Christoph Lameter, Mike McLagan. | 13 | modified by David Nugent, Christoph Lameter, Mike McLagan. |
@@ -43,31 +45,19 @@ | |||
43 | #include <linux/interrupt.h> | 45 | #include <linux/interrupt.h> |
44 | #include <asm/uaccess.h> | 46 | #include <asm/uaccess.h> |
45 | #include <asm/io.h> | 47 | #include <asm/io.h> |
46 | 48 | #include <linux/spinlock.h> | |
47 | #ifdef CONFIG_PCI | ||
48 | #define ENABLE_PCI | ||
49 | #endif /* CONFIG_PCI */ | ||
50 | |||
51 | #define putUser(arg1, arg2) put_user(arg1, (unsigned long __user *)arg2) | ||
52 | #define getUser(arg1, arg2) get_user(arg1, (unsigned __user *)arg2) | ||
53 | |||
54 | #ifdef ENABLE_PCI | ||
55 | #include <linux/pci.h> | 49 | #include <linux/pci.h> |
56 | #include "digiPCI.h" | 50 | #include "digiPCI.h" |
57 | #endif /* ENABLE_PCI */ | 51 | |
58 | 52 | ||
59 | #include "digi1.h" | 53 | #include "digi1.h" |
60 | #include "digiFep1.h" | 54 | #include "digiFep1.h" |
61 | #include "epca.h" | 55 | #include "epca.h" |
62 | #include "epcaconfig.h" | 56 | #include "epcaconfig.h" |
63 | 57 | ||
64 | #if BITS_PER_LONG != 32 | ||
65 | # error FIXME: this driver only works on 32-bit platforms | ||
66 | #endif | ||
67 | |||
68 | /* ---------------------- Begin defines ------------------------ */ | 58 | /* ---------------------- Begin defines ------------------------ */ |
69 | 59 | ||
70 | #define VERSION "1.3.0.1-LK" | 60 | #define VERSION "1.3.0.1-LK2.6" |
71 | 61 | ||
72 | /* This major needs to be submitted to Linux to join the majors list */ | 62 | /* This major needs to be submitted to Linux to join the majors list */ |
73 | 63 | ||
@@ -81,13 +71,17 @@ | |||
81 | 71 | ||
82 | /* ----------------- Begin global definitions ------------------- */ | 72 | /* ----------------- Begin global definitions ------------------- */ |
83 | 73 | ||
84 | static char mesg[100]; | ||
85 | static int nbdevs, num_cards, liloconfig; | 74 | static int nbdevs, num_cards, liloconfig; |
86 | static int digi_poller_inhibited = 1 ; | 75 | static int digi_poller_inhibited = 1 ; |
87 | 76 | ||
88 | static int setup_error_code; | 77 | static int setup_error_code; |
89 | static int invalid_lilo_config; | 78 | static int invalid_lilo_config; |
90 | 79 | ||
80 | /* The ISA boards do window flipping into the same spaces so its only sane | ||
81 | with a single lock. It's still pretty efficient */ | ||
82 | |||
83 | static spinlock_t epca_lock = SPIN_LOCK_UNLOCKED; | ||
84 | |||
91 | /* ----------------------------------------------------------------------- | 85 | /* ----------------------------------------------------------------------- |
92 | MAXBOARDS is typically 12, but ISA and EISA cards are restricted to | 86 | MAXBOARDS is typically 12, but ISA and EISA cards are restricted to |
93 | 7 below. | 87 | 7 below. |
@@ -129,58 +123,58 @@ static struct timer_list epca_timer; | |||
129 | configured. | 123 | configured. |
130 | ----------------------------------------------------------------------- */ | 124 | ----------------------------------------------------------------------- */ |
131 | 125 | ||
132 | static inline void memwinon(struct board_info *b, unsigned int win); | 126 | static void memwinon(struct board_info *b, unsigned int win); |
133 | static inline void memwinoff(struct board_info *b, unsigned int win); | 127 | static void memwinoff(struct board_info *b, unsigned int win); |
134 | static inline void globalwinon(struct channel *ch); | 128 | static void globalwinon(struct channel *ch); |
135 | static inline void rxwinon(struct channel *ch); | 129 | static void rxwinon(struct channel *ch); |
136 | static inline void txwinon(struct channel *ch); | 130 | static void txwinon(struct channel *ch); |
137 | static inline void memoff(struct channel *ch); | 131 | static void memoff(struct channel *ch); |
138 | static inline void assertgwinon(struct channel *ch); | 132 | static void assertgwinon(struct channel *ch); |
139 | static inline void assertmemoff(struct channel *ch); | 133 | static void assertmemoff(struct channel *ch); |
140 | 134 | ||
141 | /* ---- Begin more 'specific' memory functions for cx_like products --- */ | 135 | /* ---- Begin more 'specific' memory functions for cx_like products --- */ |
142 | 136 | ||
143 | static inline void pcxem_memwinon(struct board_info *b, unsigned int win); | 137 | static void pcxem_memwinon(struct board_info *b, unsigned int win); |
144 | static inline void pcxem_memwinoff(struct board_info *b, unsigned int win); | 138 | static void pcxem_memwinoff(struct board_info *b, unsigned int win); |
145 | static inline void pcxem_globalwinon(struct channel *ch); | 139 | static void pcxem_globalwinon(struct channel *ch); |
146 | static inline void pcxem_rxwinon(struct channel *ch); | 140 | static void pcxem_rxwinon(struct channel *ch); |
147 | static inline void pcxem_txwinon(struct channel *ch); | 141 | static void pcxem_txwinon(struct channel *ch); |
148 | static inline void pcxem_memoff(struct channel *ch); | 142 | static void pcxem_memoff(struct channel *ch); |
149 | 143 | ||
150 | /* ------ Begin more 'specific' memory functions for the pcxe ------- */ | 144 | /* ------ Begin more 'specific' memory functions for the pcxe ------- */ |
151 | 145 | ||
152 | static inline void pcxe_memwinon(struct board_info *b, unsigned int win); | 146 | static void pcxe_memwinon(struct board_info *b, unsigned int win); |
153 | static inline void pcxe_memwinoff(struct board_info *b, unsigned int win); | 147 | static void pcxe_memwinoff(struct board_info *b, unsigned int win); |
154 | static inline void pcxe_globalwinon(struct channel *ch); | 148 | static void pcxe_globalwinon(struct channel *ch); |
155 | static inline void pcxe_rxwinon(struct channel *ch); | 149 | static void pcxe_rxwinon(struct channel *ch); |
156 | static inline void pcxe_txwinon(struct channel *ch); | 150 | static void pcxe_txwinon(struct channel *ch); |
157 | static inline void pcxe_memoff(struct channel *ch); | 151 | static void pcxe_memoff(struct channel *ch); |
158 | 152 | ||
159 | /* ---- Begin more 'specific' memory functions for the pc64xe and pcxi ---- */ | 153 | /* ---- Begin more 'specific' memory functions for the pc64xe and pcxi ---- */ |
160 | /* Note : pc64xe and pcxi share the same windowing routines */ | 154 | /* Note : pc64xe and pcxi share the same windowing routines */ |
161 | 155 | ||
162 | static inline void pcxi_memwinon(struct board_info *b, unsigned int win); | 156 | static void pcxi_memwinon(struct board_info *b, unsigned int win); |
163 | static inline void pcxi_memwinoff(struct board_info *b, unsigned int win); | 157 | static void pcxi_memwinoff(struct board_info *b, unsigned int win); |
164 | static inline void pcxi_globalwinon(struct channel *ch); | 158 | static void pcxi_globalwinon(struct channel *ch); |
165 | static inline void pcxi_rxwinon(struct channel *ch); | 159 | static void pcxi_rxwinon(struct channel *ch); |
166 | static inline void pcxi_txwinon(struct channel *ch); | 160 | static void pcxi_txwinon(struct channel *ch); |
167 | static inline void pcxi_memoff(struct channel *ch); | 161 | static void pcxi_memoff(struct channel *ch); |
168 | 162 | ||
169 | /* - Begin 'specific' do nothing memory functions needed for some cards - */ | 163 | /* - Begin 'specific' do nothing memory functions needed for some cards - */ |
170 | 164 | ||
171 | static inline void dummy_memwinon(struct board_info *b, unsigned int win); | 165 | static void dummy_memwinon(struct board_info *b, unsigned int win); |
172 | static inline void dummy_memwinoff(struct board_info *b, unsigned int win); | 166 | static void dummy_memwinoff(struct board_info *b, unsigned int win); |
173 | static inline void dummy_globalwinon(struct channel *ch); | 167 | static void dummy_globalwinon(struct channel *ch); |
174 | static inline void dummy_rxwinon(struct channel *ch); | 168 | static void dummy_rxwinon(struct channel *ch); |
175 | static inline void dummy_txwinon(struct channel *ch); | 169 | static void dummy_txwinon(struct channel *ch); |
176 | static inline void dummy_memoff(struct channel *ch); | 170 | static void dummy_memoff(struct channel *ch); |
177 | static inline void dummy_assertgwinon(struct channel *ch); | 171 | static void dummy_assertgwinon(struct channel *ch); |
178 | static inline void dummy_assertmemoff(struct channel *ch); | 172 | static void dummy_assertmemoff(struct channel *ch); |
179 | 173 | ||
180 | /* ------------------- Begin declare functions ----------------------- */ | 174 | /* ------------------- Begin declare functions ----------------------- */ |
181 | 175 | ||
182 | static inline struct channel *verifyChannel(register struct tty_struct *); | 176 | static struct channel *verifyChannel(struct tty_struct *); |
183 | static inline void pc_sched_event(struct channel *, int); | 177 | static void pc_sched_event(struct channel *, int); |
184 | static void epca_error(int, char *); | 178 | static void epca_error(int, char *); |
185 | static void pc_close(struct tty_struct *, struct file *); | 179 | static void pc_close(struct tty_struct *, struct file *); |
186 | static void shutdown(struct channel *); | 180 | static void shutdown(struct channel *); |
@@ -215,15 +209,11 @@ static void pc_unthrottle(struct tty_struct *tty); | |||
215 | static void digi_send_break(struct channel *ch, int msec); | 209 | static void digi_send_break(struct channel *ch, int msec); |
216 | static void setup_empty_event(struct tty_struct *tty, struct channel *ch); | 210 | static void setup_empty_event(struct tty_struct *tty, struct channel *ch); |
217 | void epca_setup(char *, int *); | 211 | void epca_setup(char *, int *); |
218 | void console_print(const char *); | ||
219 | 212 | ||
220 | static int get_termio(struct tty_struct *, struct termio __user *); | 213 | static int get_termio(struct tty_struct *, struct termio __user *); |
221 | static int pc_write(struct tty_struct *, const unsigned char *, int); | 214 | static int pc_write(struct tty_struct *, const unsigned char *, int); |
222 | int pc_init(void); | 215 | static int pc_init(void); |
223 | |||
224 | #ifdef ENABLE_PCI | ||
225 | static int init_PCI(void); | 216 | static int init_PCI(void); |
226 | #endif /* ENABLE_PCI */ | ||
227 | 217 | ||
228 | 218 | ||
229 | /* ------------------------------------------------------------------ | 219 | /* ------------------------------------------------------------------ |
@@ -237,41 +227,41 @@ static int init_PCI(void); | |||
237 | making direct calls deserves what they get. | 227 | making direct calls deserves what they get. |
238 | -------------------------------------------------------------------- */ | 228 | -------------------------------------------------------------------- */ |
239 | 229 | ||
240 | static inline void memwinon(struct board_info *b, unsigned int win) | 230 | static void memwinon(struct board_info *b, unsigned int win) |
241 | { | 231 | { |
242 | (b->memwinon)(b, win); | 232 | (b->memwinon)(b, win); |
243 | } | 233 | } |
244 | 234 | ||
245 | static inline void memwinoff(struct board_info *b, unsigned int win) | 235 | static void memwinoff(struct board_info *b, unsigned int win) |
246 | { | 236 | { |
247 | (b->memwinoff)(b, win); | 237 | (b->memwinoff)(b, win); |
248 | } | 238 | } |
249 | 239 | ||
250 | static inline void globalwinon(struct channel *ch) | 240 | static void globalwinon(struct channel *ch) |
251 | { | 241 | { |
252 | (ch->board->globalwinon)(ch); | 242 | (ch->board->globalwinon)(ch); |
253 | } | 243 | } |
254 | 244 | ||
255 | static inline void rxwinon(struct channel *ch) | 245 | static void rxwinon(struct channel *ch) |
256 | { | 246 | { |
257 | (ch->board->rxwinon)(ch); | 247 | (ch->board->rxwinon)(ch); |
258 | } | 248 | } |
259 | 249 | ||
260 | static inline void txwinon(struct channel *ch) | 250 | static void txwinon(struct channel *ch) |
261 | { | 251 | { |
262 | (ch->board->txwinon)(ch); | 252 | (ch->board->txwinon)(ch); |
263 | } | 253 | } |
264 | 254 | ||
265 | static inline void memoff(struct channel *ch) | 255 | static void memoff(struct channel *ch) |
266 | { | 256 | { |
267 | (ch->board->memoff)(ch); | 257 | (ch->board->memoff)(ch); |
268 | } | 258 | } |
269 | static inline void assertgwinon(struct channel *ch) | 259 | static void assertgwinon(struct channel *ch) |
270 | { | 260 | { |
271 | (ch->board->assertgwinon)(ch); | 261 | (ch->board->assertgwinon)(ch); |
272 | } | 262 | } |
273 | 263 | ||
274 | static inline void assertmemoff(struct channel *ch) | 264 | static void assertmemoff(struct channel *ch) |
275 | { | 265 | { |
276 | (ch->board->assertmemoff)(ch); | 266 | (ch->board->assertmemoff)(ch); |
277 | } | 267 | } |
@@ -281,66 +271,66 @@ static inline void assertmemoff(struct channel *ch) | |||
281 | and CX series cards. | 271 | and CX series cards. |
282 | ------------------------------------------------------------ */ | 272 | ------------------------------------------------------------ */ |
283 | 273 | ||
284 | static inline void pcxem_memwinon(struct board_info *b, unsigned int win) | 274 | static void pcxem_memwinon(struct board_info *b, unsigned int win) |
285 | { | 275 | { |
286 | outb_p(FEPWIN|win, (int)b->port + 1); | 276 | outb_p(FEPWIN|win, b->port + 1); |
287 | } | 277 | } |
288 | 278 | ||
289 | static inline void pcxem_memwinoff(struct board_info *b, unsigned int win) | 279 | static void pcxem_memwinoff(struct board_info *b, unsigned int win) |
290 | { | 280 | { |
291 | outb_p(0, (int)b->port + 1); | 281 | outb_p(0, b->port + 1); |
292 | } | 282 | } |
293 | 283 | ||
294 | static inline void pcxem_globalwinon(struct channel *ch) | 284 | static void pcxem_globalwinon(struct channel *ch) |
295 | { | 285 | { |
296 | outb_p( FEPWIN, (int)ch->board->port + 1); | 286 | outb_p( FEPWIN, (int)ch->board->port + 1); |
297 | } | 287 | } |
298 | 288 | ||
299 | static inline void pcxem_rxwinon(struct channel *ch) | 289 | static void pcxem_rxwinon(struct channel *ch) |
300 | { | 290 | { |
301 | outb_p(ch->rxwin, (int)ch->board->port + 1); | 291 | outb_p(ch->rxwin, (int)ch->board->port + 1); |
302 | } | 292 | } |
303 | 293 | ||
304 | static inline void pcxem_txwinon(struct channel *ch) | 294 | static void pcxem_txwinon(struct channel *ch) |
305 | { | 295 | { |
306 | outb_p(ch->txwin, (int)ch->board->port + 1); | 296 | outb_p(ch->txwin, (int)ch->board->port + 1); |
307 | } | 297 | } |
308 | 298 | ||
309 | static inline void pcxem_memoff(struct channel *ch) | 299 | static void pcxem_memoff(struct channel *ch) |
310 | { | 300 | { |
311 | outb_p(0, (int)ch->board->port + 1); | 301 | outb_p(0, (int)ch->board->port + 1); |
312 | } | 302 | } |
313 | 303 | ||
314 | /* ----------------- Begin pcxe memory window stuff ------------------ */ | 304 | /* ----------------- Begin pcxe memory window stuff ------------------ */ |
315 | 305 | ||
316 | static inline void pcxe_memwinon(struct board_info *b, unsigned int win) | 306 | static void pcxe_memwinon(struct board_info *b, unsigned int win) |
317 | { | 307 | { |
318 | outb_p(FEPWIN | win, (int)b->port + 1); | 308 | outb_p(FEPWIN | win, b->port + 1); |
319 | } | 309 | } |
320 | 310 | ||
321 | static inline void pcxe_memwinoff(struct board_info *b, unsigned int win) | 311 | static void pcxe_memwinoff(struct board_info *b, unsigned int win) |
322 | { | 312 | { |
323 | outb_p(inb((int)b->port) & ~FEPMEM, | 313 | outb_p(inb(b->port) & ~FEPMEM, |
324 | (int)b->port + 1); | 314 | b->port + 1); |
325 | outb_p(0, (int)b->port + 1); | 315 | outb_p(0, b->port + 1); |
326 | } | 316 | } |
327 | 317 | ||
328 | static inline void pcxe_globalwinon(struct channel *ch) | 318 | static void pcxe_globalwinon(struct channel *ch) |
329 | { | 319 | { |
330 | outb_p( FEPWIN, (int)ch->board->port + 1); | 320 | outb_p( FEPWIN, (int)ch->board->port + 1); |
331 | } | 321 | } |
332 | 322 | ||
333 | static inline void pcxe_rxwinon(struct channel *ch) | 323 | static void pcxe_rxwinon(struct channel *ch) |
334 | { | 324 | { |
335 | outb_p(ch->rxwin, (int)ch->board->port + 1); | 325 | outb_p(ch->rxwin, (int)ch->board->port + 1); |
336 | } | 326 | } |
337 | 327 | ||
338 | static inline void pcxe_txwinon(struct channel *ch) | 328 | static void pcxe_txwinon(struct channel *ch) |
339 | { | 329 | { |
340 | outb_p(ch->txwin, (int)ch->board->port + 1); | 330 | outb_p(ch->txwin, (int)ch->board->port + 1); |
341 | } | 331 | } |
342 | 332 | ||
343 | static inline void pcxe_memoff(struct channel *ch) | 333 | static void pcxe_memoff(struct channel *ch) |
344 | { | 334 | { |
345 | outb_p(0, (int)ch->board->port); | 335 | outb_p(0, (int)ch->board->port); |
346 | outb_p(0, (int)ch->board->port + 1); | 336 | outb_p(0, (int)ch->board->port + 1); |
@@ -348,44 +338,44 @@ static inline void pcxe_memoff(struct channel *ch) | |||
348 | 338 | ||
349 | /* ------------- Begin pc64xe and pcxi memory window stuff -------------- */ | 339 | /* ------------- Begin pc64xe and pcxi memory window stuff -------------- */ |
350 | 340 | ||
351 | static inline void pcxi_memwinon(struct board_info *b, unsigned int win) | 341 | static void pcxi_memwinon(struct board_info *b, unsigned int win) |
352 | { | 342 | { |
353 | outb_p(inb((int)b->port) | FEPMEM, (int)b->port); | 343 | outb_p(inb(b->port) | FEPMEM, b->port); |
354 | } | 344 | } |
355 | 345 | ||
356 | static inline void pcxi_memwinoff(struct board_info *b, unsigned int win) | 346 | static void pcxi_memwinoff(struct board_info *b, unsigned int win) |
357 | { | 347 | { |
358 | outb_p(inb((int)b->port) & ~FEPMEM, (int)b->port); | 348 | outb_p(inb(b->port) & ~FEPMEM, b->port); |
359 | } | 349 | } |
360 | 350 | ||
361 | static inline void pcxi_globalwinon(struct channel *ch) | 351 | static void pcxi_globalwinon(struct channel *ch) |
362 | { | 352 | { |
363 | outb_p(FEPMEM, (int)ch->board->port); | 353 | outb_p(FEPMEM, ch->board->port); |
364 | } | 354 | } |
365 | 355 | ||
366 | static inline void pcxi_rxwinon(struct channel *ch) | 356 | static void pcxi_rxwinon(struct channel *ch) |
367 | { | 357 | { |
368 | outb_p(FEPMEM, (int)ch->board->port); | 358 | outb_p(FEPMEM, ch->board->port); |
369 | } | 359 | } |
370 | 360 | ||
371 | static inline void pcxi_txwinon(struct channel *ch) | 361 | static void pcxi_txwinon(struct channel *ch) |
372 | { | 362 | { |
373 | outb_p(FEPMEM, (int)ch->board->port); | 363 | outb_p(FEPMEM, ch->board->port); |
374 | } | 364 | } |
375 | 365 | ||
376 | static inline void pcxi_memoff(struct channel *ch) | 366 | static void pcxi_memoff(struct channel *ch) |
377 | { | 367 | { |
378 | outb_p(0, (int)ch->board->port); | 368 | outb_p(0, ch->board->port); |
379 | } | 369 | } |
380 | 370 | ||
381 | static inline void pcxi_assertgwinon(struct channel *ch) | 371 | static void pcxi_assertgwinon(struct channel *ch) |
382 | { | 372 | { |
383 | epcaassert(inb((int)ch->board->port) & FEPMEM, "Global memory off"); | 373 | epcaassert(inb(ch->board->port) & FEPMEM, "Global memory off"); |
384 | } | 374 | } |
385 | 375 | ||
386 | static inline void pcxi_assertmemoff(struct channel *ch) | 376 | static void pcxi_assertmemoff(struct channel *ch) |
387 | { | 377 | { |
388 | epcaassert(!(inb((int)ch->board->port) & FEPMEM), "Memory on"); | 378 | epcaassert(!(inb(ch->board->port) & FEPMEM), "Memory on"); |
389 | } | 379 | } |
390 | 380 | ||
391 | 381 | ||
@@ -398,185 +388,143 @@ static inline void pcxi_assertmemoff(struct channel *ch) | |||
398 | may or may not do anything. | 388 | may or may not do anything. |
399 | ---------------------------------------------------------------------------*/ | 389 | ---------------------------------------------------------------------------*/ |
400 | 390 | ||
401 | static inline void dummy_memwinon(struct board_info *b, unsigned int win) | 391 | static void dummy_memwinon(struct board_info *b, unsigned int win) |
402 | { | 392 | { |
403 | } | 393 | } |
404 | 394 | ||
405 | static inline void dummy_memwinoff(struct board_info *b, unsigned int win) | 395 | static void dummy_memwinoff(struct board_info *b, unsigned int win) |
406 | { | 396 | { |
407 | } | 397 | } |
408 | 398 | ||
409 | static inline void dummy_globalwinon(struct channel *ch) | 399 | static void dummy_globalwinon(struct channel *ch) |
410 | { | 400 | { |
411 | } | 401 | } |
412 | 402 | ||
413 | static inline void dummy_rxwinon(struct channel *ch) | 403 | static void dummy_rxwinon(struct channel *ch) |
414 | { | 404 | { |
415 | } | 405 | } |
416 | 406 | ||
417 | static inline void dummy_txwinon(struct channel *ch) | 407 | static void dummy_txwinon(struct channel *ch) |
418 | { | 408 | { |
419 | } | 409 | } |
420 | 410 | ||
421 | static inline void dummy_memoff(struct channel *ch) | 411 | static void dummy_memoff(struct channel *ch) |
422 | { | 412 | { |
423 | } | 413 | } |
424 | 414 | ||
425 | static inline void dummy_assertgwinon(struct channel *ch) | 415 | static void dummy_assertgwinon(struct channel *ch) |
426 | { | 416 | { |
427 | } | 417 | } |
428 | 418 | ||
429 | static inline void dummy_assertmemoff(struct channel *ch) | 419 | static void dummy_assertmemoff(struct channel *ch) |
430 | { | 420 | { |
431 | } | 421 | } |
432 | 422 | ||
433 | /* ----------------- Begin verifyChannel function ----------------------- */ | 423 | /* ----------------- Begin verifyChannel function ----------------------- */ |
434 | static inline struct channel *verifyChannel(register struct tty_struct *tty) | 424 | static struct channel *verifyChannel(struct tty_struct *tty) |
435 | { /* Begin verifyChannel */ | 425 | { /* Begin verifyChannel */ |
436 | |||
437 | /* -------------------------------------------------------------------- | 426 | /* -------------------------------------------------------------------- |
438 | This routine basically provides a sanity check. It insures that | 427 | This routine basically provides a sanity check. It insures that |
439 | the channel returned is within the proper range of addresses as | 428 | the channel returned is within the proper range of addresses as |
440 | well as properly initialized. If some bogus info gets passed in | 429 | well as properly initialized. If some bogus info gets passed in |
441 | through tty->driver_data this should catch it. | 430 | through tty->driver_data this should catch it. |
442 | --------------------------------------------------------------------- */ | 431 | --------------------------------------------------------------------- */ |
443 | 432 | if (tty) { | |
444 | if (tty) | 433 | struct channel *ch = (struct channel *)tty->driver_data; |
445 | { /* Begin if tty */ | 434 | if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) { |
446 | |||
447 | register struct channel *ch = (struct channel *)tty->driver_data; | ||
448 | |||
449 | if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) | ||
450 | { | ||
451 | if (ch->magic == EPCA_MAGIC) | 435 | if (ch->magic == EPCA_MAGIC) |
452 | return ch; | 436 | return ch; |
453 | } | 437 | } |
454 | 438 | } | |
455 | } /* End if tty */ | ||
456 | |||
457 | /* Else return a NULL for invalid */ | ||
458 | return NULL; | 439 | return NULL; |
459 | 440 | ||
460 | } /* End verifyChannel */ | 441 | } /* End verifyChannel */ |
461 | 442 | ||
462 | /* ------------------ Begin pc_sched_event ------------------------- */ | 443 | /* ------------------ Begin pc_sched_event ------------------------- */ |
463 | 444 | ||
464 | static inline void pc_sched_event(struct channel *ch, int event) | 445 | static void pc_sched_event(struct channel *ch, int event) |
465 | { /* Begin pc_sched_event */ | 446 | { |
466 | |||
467 | |||
468 | /* ---------------------------------------------------------------------- | 447 | /* ---------------------------------------------------------------------- |
469 | We call this to schedule interrupt processing on some event. The | 448 | We call this to schedule interrupt processing on some event. The |
470 | kernel sees our request and calls the related routine in OUR driver. | 449 | kernel sees our request and calls the related routine in OUR driver. |
471 | -------------------------------------------------------------------------*/ | 450 | -------------------------------------------------------------------------*/ |
472 | |||
473 | ch->event |= 1 << event; | 451 | ch->event |= 1 << event; |
474 | schedule_work(&ch->tqueue); | 452 | schedule_work(&ch->tqueue); |
475 | |||
476 | |||
477 | } /* End pc_sched_event */ | 453 | } /* End pc_sched_event */ |
478 | 454 | ||
479 | /* ------------------ Begin epca_error ------------------------- */ | 455 | /* ------------------ Begin epca_error ------------------------- */ |
480 | 456 | ||
481 | static void epca_error(int line, char *msg) | 457 | static void epca_error(int line, char *msg) |
482 | { /* Begin epca_error */ | 458 | { |
483 | |||
484 | printk(KERN_ERR "epca_error (Digi): line = %d %s\n",line,msg); | 459 | printk(KERN_ERR "epca_error (Digi): line = %d %s\n",line,msg); |
485 | return; | 460 | } |
486 | |||
487 | } /* End epca_error */ | ||
488 | 461 | ||
489 | /* ------------------ Begin pc_close ------------------------- */ | 462 | /* ------------------ Begin pc_close ------------------------- */ |
490 | static void pc_close(struct tty_struct * tty, struct file * filp) | 463 | static void pc_close(struct tty_struct * tty, struct file * filp) |
491 | { /* Begin pc_close */ | 464 | { |
492 | |||
493 | struct channel *ch; | 465 | struct channel *ch; |
494 | unsigned long flags; | 466 | unsigned long flags; |
495 | |||
496 | /* --------------------------------------------------------- | 467 | /* --------------------------------------------------------- |
497 | verifyChannel returns the channel from the tty struct | 468 | verifyChannel returns the channel from the tty struct |
498 | if it is valid. This serves as a sanity check. | 469 | if it is valid. This serves as a sanity check. |
499 | ------------------------------------------------------------- */ | 470 | ------------------------------------------------------------- */ |
500 | 471 | if ((ch = verifyChannel(tty)) != NULL) { /* Begin if ch != NULL */ | |
501 | if ((ch = verifyChannel(tty)) != NULL) | 472 | spin_lock_irqsave(&epca_lock, flags); |
502 | { /* Begin if ch != NULL */ | 473 | if (tty_hung_up_p(filp)) { |
503 | 474 | spin_unlock_irqrestore(&epca_lock, flags); | |
504 | save_flags(flags); | ||
505 | cli(); | ||
506 | |||
507 | if (tty_hung_up_p(filp)) | ||
508 | { | ||
509 | restore_flags(flags); | ||
510 | return; | 475 | return; |
511 | } | 476 | } |
512 | |||
513 | /* Check to see if the channel is open more than once */ | 477 | /* Check to see if the channel is open more than once */ |
514 | if (ch->count-- > 1) | 478 | if (ch->count-- > 1) { |
515 | { /* Begin channel is open more than once */ | 479 | /* Begin channel is open more than once */ |
516 | |||
517 | /* ------------------------------------------------------------- | 480 | /* ------------------------------------------------------------- |
518 | Return without doing anything. Someone might still be using | 481 | Return without doing anything. Someone might still be using |
519 | the channel. | 482 | the channel. |
520 | ---------------------------------------------------------------- */ | 483 | ---------------------------------------------------------------- */ |
521 | 484 | spin_unlock_irqrestore(&epca_lock, flags); | |
522 | restore_flags(flags); | ||
523 | return; | 485 | return; |
524 | } /* End channel is open more than once */ | 486 | } /* End channel is open more than once */ |
525 | 487 | ||
526 | /* Port open only once go ahead with shutdown & reset */ | 488 | /* Port open only once go ahead with shutdown & reset */ |
527 | 489 | if (ch->count < 0) | |
528 | if (ch->count < 0) | 490 | BUG(); |
529 | { | ||
530 | ch->count = 0; | ||
531 | } | ||
532 | 491 | ||
533 | /* --------------------------------------------------------------- | 492 | /* --------------------------------------------------------------- |
534 | Let the rest of the driver know the channel is being closed. | 493 | Let the rest of the driver know the channel is being closed. |
535 | This becomes important if an open is attempted before close | 494 | This becomes important if an open is attempted before close |
536 | is finished. | 495 | is finished. |
537 | ------------------------------------------------------------------ */ | 496 | ------------------------------------------------------------------ */ |
538 | |||
539 | ch->asyncflags |= ASYNC_CLOSING; | 497 | ch->asyncflags |= ASYNC_CLOSING; |
540 | |||
541 | tty->closing = 1; | 498 | tty->closing = 1; |
542 | 499 | ||
543 | if (ch->asyncflags & ASYNC_INITIALIZED) | 500 | spin_unlock_irqrestore(&epca_lock, flags); |
544 | { | 501 | |
502 | if (ch->asyncflags & ASYNC_INITIALIZED) { | ||
545 | /* Setup an event to indicate when the transmit buffer empties */ | 503 | /* Setup an event to indicate when the transmit buffer empties */ |
546 | setup_empty_event(tty, ch); | 504 | setup_empty_event(tty, ch); |
547 | tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ | 505 | tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ |
548 | } | 506 | } |
549 | |||
550 | if (tty->driver->flush_buffer) | 507 | if (tty->driver->flush_buffer) |
551 | tty->driver->flush_buffer(tty); | 508 | tty->driver->flush_buffer(tty); |
552 | 509 | ||
553 | tty_ldisc_flush(tty); | 510 | tty_ldisc_flush(tty); |
554 | shutdown(ch); | 511 | shutdown(ch); |
512 | |||
513 | spin_lock_irqsave(&epca_lock, flags); | ||
555 | tty->closing = 0; | 514 | tty->closing = 0; |
556 | ch->event = 0; | 515 | ch->event = 0; |
557 | ch->tty = NULL; | 516 | ch->tty = NULL; |
517 | spin_unlock_irqrestore(&epca_lock, flags); | ||
558 | 518 | ||
559 | if (ch->blocked_open) | 519 | if (ch->blocked_open) { /* Begin if blocked_open */ |
560 | { /* Begin if blocked_open */ | ||
561 | |||
562 | if (ch->close_delay) | 520 | if (ch->close_delay) |
563 | { | ||
564 | msleep_interruptible(jiffies_to_msecs(ch->close_delay)); | 521 | msleep_interruptible(jiffies_to_msecs(ch->close_delay)); |
565 | } | ||
566 | |||
567 | wake_up_interruptible(&ch->open_wait); | 522 | wake_up_interruptible(&ch->open_wait); |
568 | |||
569 | } /* End if blocked_open */ | 523 | } /* End if blocked_open */ |
570 | |||
571 | ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED | | 524 | ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED | |
572 | ASYNC_CLOSING); | 525 | ASYNC_CLOSING); |
573 | wake_up_interruptible(&ch->close_wait); | 526 | wake_up_interruptible(&ch->close_wait); |
574 | |||
575 | |||
576 | restore_flags(flags); | ||
577 | |||
578 | } /* End if ch != NULL */ | 527 | } /* End if ch != NULL */ |
579 | |||
580 | } /* End pc_close */ | 528 | } /* End pc_close */ |
581 | 529 | ||
582 | /* ------------------ Begin shutdown ------------------------- */ | 530 | /* ------------------ Begin shutdown ------------------------- */ |
@@ -586,15 +534,14 @@ static void shutdown(struct channel *ch) | |||
586 | 534 | ||
587 | unsigned long flags; | 535 | unsigned long flags; |
588 | struct tty_struct *tty; | 536 | struct tty_struct *tty; |
589 | volatile struct board_chan *bc; | 537 | struct board_chan *bc; |
590 | 538 | ||
591 | if (!(ch->asyncflags & ASYNC_INITIALIZED)) | 539 | if (!(ch->asyncflags & ASYNC_INITIALIZED)) |
592 | return; | 540 | return; |
593 | 541 | ||
594 | save_flags(flags); | 542 | spin_lock_irqsave(&epca_lock, flags); |
595 | cli(); | ||
596 | globalwinon(ch); | ||
597 | 543 | ||
544 | globalwinon(ch); | ||
598 | bc = ch->brdchan; | 545 | bc = ch->brdchan; |
599 | 546 | ||
600 | /* ------------------------------------------------------------------ | 547 | /* ------------------------------------------------------------------ |
@@ -604,20 +551,17 @@ static void shutdown(struct channel *ch) | |||
604 | --------------------------------------------------------------------- */ | 551 | --------------------------------------------------------------------- */ |
605 | 552 | ||
606 | if (bc) | 553 | if (bc) |
607 | bc->idata = 0; | 554 | writeb(0, &bc->idata); |
608 | |||
609 | tty = ch->tty; | 555 | tty = ch->tty; |
610 | 556 | ||
611 | /* ---------------------------------------------------------------- | 557 | /* ---------------------------------------------------------------- |
612 | If we're a modem control device and HUPCL is on, drop RTS & DTR. | 558 | If we're a modem control device and HUPCL is on, drop RTS & DTR. |
613 | ------------------------------------------------------------------ */ | 559 | ------------------------------------------------------------------ */ |
614 | 560 | ||
615 | if (tty->termios->c_cflag & HUPCL) | 561 | if (tty->termios->c_cflag & HUPCL) { |
616 | { | ||
617 | ch->omodem &= ~(ch->m_rts | ch->m_dtr); | 562 | ch->omodem &= ~(ch->m_rts | ch->m_dtr); |
618 | fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1); | 563 | fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1); |
619 | } | 564 | } |
620 | |||
621 | memoff(ch); | 565 | memoff(ch); |
622 | 566 | ||
623 | /* ------------------------------------------------------------------ | 567 | /* ------------------------------------------------------------------ |
@@ -628,7 +572,7 @@ static void shutdown(struct channel *ch) | |||
628 | /* Prevent future Digi programmed interrupts from coming active */ | 572 | /* Prevent future Digi programmed interrupts from coming active */ |
629 | 573 | ||
630 | ch->asyncflags &= ~ASYNC_INITIALIZED; | 574 | ch->asyncflags &= ~ASYNC_INITIALIZED; |
631 | restore_flags(flags); | 575 | spin_unlock_irqrestore(&epca_lock, flags); |
632 | 576 | ||
633 | } /* End shutdown */ | 577 | } /* End shutdown */ |
634 | 578 | ||
@@ -636,7 +580,6 @@ static void shutdown(struct channel *ch) | |||
636 | 580 | ||
637 | static void pc_hangup(struct tty_struct *tty) | 581 | static void pc_hangup(struct tty_struct *tty) |
638 | { /* Begin pc_hangup */ | 582 | { /* Begin pc_hangup */ |
639 | |||
640 | struct channel *ch; | 583 | struct channel *ch; |
641 | 584 | ||
642 | /* --------------------------------------------------------- | 585 | /* --------------------------------------------------------- |
@@ -644,25 +587,21 @@ static void pc_hangup(struct tty_struct *tty) | |||
644 | if it is valid. This serves as a sanity check. | 587 | if it is valid. This serves as a sanity check. |
645 | ------------------------------------------------------------- */ | 588 | ------------------------------------------------------------- */ |
646 | 589 | ||
647 | if ((ch = verifyChannel(tty)) != NULL) | 590 | if ((ch = verifyChannel(tty)) != NULL) { /* Begin if ch != NULL */ |
648 | { /* Begin if ch != NULL */ | ||
649 | |||
650 | unsigned long flags; | 591 | unsigned long flags; |
651 | 592 | ||
652 | save_flags(flags); | ||
653 | cli(); | ||
654 | if (tty->driver->flush_buffer) | 593 | if (tty->driver->flush_buffer) |
655 | tty->driver->flush_buffer(tty); | 594 | tty->driver->flush_buffer(tty); |
656 | tty_ldisc_flush(tty); | 595 | tty_ldisc_flush(tty); |
657 | shutdown(ch); | 596 | shutdown(ch); |
658 | 597 | ||
598 | spin_lock_irqsave(&epca_lock, flags); | ||
659 | ch->tty = NULL; | 599 | ch->tty = NULL; |
660 | ch->event = 0; | 600 | ch->event = 0; |
661 | ch->count = 0; | 601 | ch->count = 0; |
662 | restore_flags(flags); | ||
663 | ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED); | 602 | ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED); |
603 | spin_unlock_irqrestore(&epca_lock, flags); | ||
664 | wake_up_interruptible(&ch->open_wait); | 604 | wake_up_interruptible(&ch->open_wait); |
665 | |||
666 | } /* End if ch != NULL */ | 605 | } /* End if ch != NULL */ |
667 | 606 | ||
668 | } /* End pc_hangup */ | 607 | } /* End pc_hangup */ |
@@ -672,18 +611,14 @@ static void pc_hangup(struct tty_struct *tty) | |||
672 | static int pc_write(struct tty_struct * tty, | 611 | static int pc_write(struct tty_struct * tty, |
673 | const unsigned char *buf, int bytesAvailable) | 612 | const unsigned char *buf, int bytesAvailable) |
674 | { /* Begin pc_write */ | 613 | { /* Begin pc_write */ |
675 | 614 | unsigned int head, tail; | |
676 | register unsigned int head, tail; | 615 | int dataLen; |
677 | register int dataLen; | 616 | int size; |
678 | register int size; | 617 | int amountCopied; |
679 | register int amountCopied; | ||
680 | |||
681 | |||
682 | struct channel *ch; | 618 | struct channel *ch; |
683 | unsigned long flags; | 619 | unsigned long flags; |
684 | int remain; | 620 | int remain; |
685 | volatile struct board_chan *bc; | 621 | struct board_chan *bc; |
686 | |||
687 | 622 | ||
688 | /* ---------------------------------------------------------------- | 623 | /* ---------------------------------------------------------------- |
689 | pc_write is primarily called directly by the kernel routine | 624 | pc_write is primarily called directly by the kernel routine |
@@ -706,24 +641,20 @@ static int pc_write(struct tty_struct * tty, | |||
706 | 641 | ||
707 | bc = ch->brdchan; | 642 | bc = ch->brdchan; |
708 | size = ch->txbufsize; | 643 | size = ch->txbufsize; |
709 | |||
710 | amountCopied = 0; | 644 | amountCopied = 0; |
711 | save_flags(flags); | ||
712 | cli(); | ||
713 | 645 | ||
646 | spin_lock_irqsave(&epca_lock, flags); | ||
714 | globalwinon(ch); | 647 | globalwinon(ch); |
715 | 648 | ||
716 | head = bc->tin & (size - 1); | 649 | head = readw(&bc->tin) & (size - 1); |
717 | tail = bc->tout; | 650 | tail = readw(&bc->tout); |
718 | 651 | ||
719 | if (tail != bc->tout) | 652 | if (tail != readw(&bc->tout)) |
720 | tail = bc->tout; | 653 | tail = readw(&bc->tout); |
721 | tail &= (size - 1); | 654 | tail &= (size - 1); |
722 | 655 | ||
723 | /* If head >= tail, head has not wrapped around. */ | 656 | /* If head >= tail, head has not wrapped around. */ |
724 | if (head >= tail) | 657 | if (head >= tail) { /* Begin head has not wrapped */ |
725 | { /* Begin head has not wrapped */ | ||
726 | |||
727 | /* --------------------------------------------------------------- | 658 | /* --------------------------------------------------------------- |
728 | remain (much like dataLen above) represents the total amount of | 659 | remain (much like dataLen above) represents the total amount of |
729 | space available on the card for data. Here dataLen represents | 660 | space available on the card for data. Here dataLen represents |
@@ -731,26 +662,19 @@ static int pc_write(struct tty_struct * tty, | |||
731 | buffer. This is important because a memcpy cannot be told to | 662 | buffer. This is important because a memcpy cannot be told to |
732 | automatically wrap around when it hits the buffer end. | 663 | automatically wrap around when it hits the buffer end. |
733 | ------------------------------------------------------------------ */ | 664 | ------------------------------------------------------------------ */ |
734 | |||
735 | dataLen = size - head; | 665 | dataLen = size - head; |
736 | remain = size - (head - tail) - 1; | 666 | remain = size - (head - tail) - 1; |
737 | 667 | } else { /* Begin head has wrapped around */ | |
738 | } /* End head has not wrapped */ | ||
739 | else | ||
740 | { /* Begin head has wrapped around */ | ||
741 | 668 | ||
742 | remain = tail - head - 1; | 669 | remain = tail - head - 1; |
743 | dataLen = remain; | 670 | dataLen = remain; |
744 | 671 | ||
745 | } /* End head has wrapped around */ | 672 | } /* End head has wrapped around */ |
746 | |||
747 | /* ------------------------------------------------------------------- | 673 | /* ------------------------------------------------------------------- |
748 | Check the space on the card. If we have more data than | 674 | Check the space on the card. If we have more data than |
749 | space; reduce the amount of data to fit the space. | 675 | space; reduce the amount of data to fit the space. |
750 | ---------------------------------------------------------------------- */ | 676 | ---------------------------------------------------------------------- */ |
751 | |||
752 | bytesAvailable = min(remain, bytesAvailable); | 677 | bytesAvailable = min(remain, bytesAvailable); |
753 | |||
754 | txwinon(ch); | 678 | txwinon(ch); |
755 | while (bytesAvailable > 0) | 679 | while (bytesAvailable > 0) |
756 | { /* Begin while there is data to copy onto card */ | 680 | { /* Begin while there is data to copy onto card */ |
@@ -767,26 +691,21 @@ static int pc_write(struct tty_struct * tty, | |||
767 | amountCopied += dataLen; | 691 | amountCopied += dataLen; |
768 | bytesAvailable -= dataLen; | 692 | bytesAvailable -= dataLen; |
769 | 693 | ||
770 | if (head >= size) | 694 | if (head >= size) { |
771 | { | ||
772 | head = 0; | 695 | head = 0; |
773 | dataLen = tail; | 696 | dataLen = tail; |
774 | } | 697 | } |
775 | |||
776 | } /* End while there is data to copy onto card */ | 698 | } /* End while there is data to copy onto card */ |
777 | |||
778 | ch->statusflags |= TXBUSY; | 699 | ch->statusflags |= TXBUSY; |
779 | globalwinon(ch); | 700 | globalwinon(ch); |
780 | bc->tin = head; | 701 | writew(head, &bc->tin); |
781 | 702 | ||
782 | if ((ch->statusflags & LOWWAIT) == 0) | 703 | if ((ch->statusflags & LOWWAIT) == 0) { |
783 | { | ||
784 | ch->statusflags |= LOWWAIT; | 704 | ch->statusflags |= LOWWAIT; |
785 | bc->ilow = 1; | 705 | writeb(1, &bc->ilow); |
786 | } | 706 | } |
787 | memoff(ch); | 707 | memoff(ch); |
788 | restore_flags(flags); | 708 | spin_unlock_irqrestore(&epca_lock, flags); |
789 | |||
790 | return(amountCopied); | 709 | return(amountCopied); |
791 | 710 | ||
792 | } /* End pc_write */ | 711 | } /* End pc_write */ |
@@ -795,11 +714,7 @@ static int pc_write(struct tty_struct * tty, | |||
795 | 714 | ||
796 | static void pc_put_char(struct tty_struct *tty, unsigned char c) | 715 | static void pc_put_char(struct tty_struct *tty, unsigned char c) |
797 | { /* Begin pc_put_char */ | 716 | { /* Begin pc_put_char */ |
798 | |||
799 | |||
800 | pc_write(tty, &c, 1); | 717 | pc_write(tty, &c, 1); |
801 | return; | ||
802 | |||
803 | } /* End pc_put_char */ | 718 | } /* End pc_put_char */ |
804 | 719 | ||
805 | /* ------------------ Begin pc_write_room ------------------------- */ | 720 | /* ------------------ Begin pc_write_room ------------------------- */ |
@@ -811,7 +726,7 @@ static int pc_write_room(struct tty_struct *tty) | |||
811 | struct channel *ch; | 726 | struct channel *ch; |
812 | unsigned long flags; | 727 | unsigned long flags; |
813 | unsigned int head, tail; | 728 | unsigned int head, tail; |
814 | volatile struct board_chan *bc; | 729 | struct board_chan *bc; |
815 | 730 | ||
816 | remain = 0; | 731 | remain = 0; |
817 | 732 | ||
@@ -820,33 +735,29 @@ static int pc_write_room(struct tty_struct *tty) | |||
820 | if it is valid. This serves as a sanity check. | 735 | if it is valid. This serves as a sanity check. |
821 | ------------------------------------------------------------- */ | 736 | ------------------------------------------------------------- */ |
822 | 737 | ||
823 | if ((ch = verifyChannel(tty)) != NULL) | 738 | if ((ch = verifyChannel(tty)) != NULL) { |
824 | { | 739 | spin_lock_irqsave(&epca_lock, flags); |
825 | save_flags(flags); | ||
826 | cli(); | ||
827 | globalwinon(ch); | 740 | globalwinon(ch); |
828 | 741 | ||
829 | bc = ch->brdchan; | 742 | bc = ch->brdchan; |
830 | head = bc->tin & (ch->txbufsize - 1); | 743 | head = readw(&bc->tin) & (ch->txbufsize - 1); |
831 | tail = bc->tout; | 744 | tail = readw(&bc->tout); |
832 | 745 | ||
833 | if (tail != bc->tout) | 746 | if (tail != readw(&bc->tout)) |
834 | tail = bc->tout; | 747 | tail = readw(&bc->tout); |
835 | /* Wrap tail if necessary */ | 748 | /* Wrap tail if necessary */ |
836 | tail &= (ch->txbufsize - 1); | 749 | tail &= (ch->txbufsize - 1); |
837 | 750 | ||
838 | if ((remain = tail - head - 1) < 0 ) | 751 | if ((remain = tail - head - 1) < 0 ) |
839 | remain += ch->txbufsize; | 752 | remain += ch->txbufsize; |
840 | 753 | ||
841 | if (remain && (ch->statusflags & LOWWAIT) == 0) | 754 | if (remain && (ch->statusflags & LOWWAIT) == 0) { |
842 | { | ||
843 | ch->statusflags |= LOWWAIT; | 755 | ch->statusflags |= LOWWAIT; |
844 | bc->ilow = 1; | 756 | writeb(1, &bc->ilow); |
845 | } | 757 | } |
846 | memoff(ch); | 758 | memoff(ch); |
847 | restore_flags(flags); | 759 | spin_unlock_irqrestore(&epca_lock, flags); |
848 | } | 760 | } |
849 | |||
850 | /* Return how much room is left on card */ | 761 | /* Return how much room is left on card */ |
851 | return remain; | 762 | return remain; |
852 | 763 | ||
@@ -862,8 +773,7 @@ static int pc_chars_in_buffer(struct tty_struct *tty) | |||
862 | int remain; | 773 | int remain; |
863 | unsigned long flags; | 774 | unsigned long flags; |
864 | struct channel *ch; | 775 | struct channel *ch; |
865 | volatile struct board_chan *bc; | 776 | struct board_chan *bc; |
866 | |||
867 | 777 | ||
868 | /* --------------------------------------------------------- | 778 | /* --------------------------------------------------------- |
869 | verifyChannel returns the channel from the tty struct | 779 | verifyChannel returns the channel from the tty struct |
@@ -873,34 +783,27 @@ static int pc_chars_in_buffer(struct tty_struct *tty) | |||
873 | if ((ch = verifyChannel(tty)) == NULL) | 783 | if ((ch = verifyChannel(tty)) == NULL) |
874 | return(0); | 784 | return(0); |
875 | 785 | ||
876 | save_flags(flags); | 786 | spin_lock_irqsave(&epca_lock, flags); |
877 | cli(); | ||
878 | globalwinon(ch); | 787 | globalwinon(ch); |
879 | 788 | ||
880 | bc = ch->brdchan; | 789 | bc = ch->brdchan; |
881 | tail = bc->tout; | 790 | tail = readw(&bc->tout); |
882 | head = bc->tin; | 791 | head = readw(&bc->tin); |
883 | ctail = ch->mailbox->cout; | 792 | ctail = readw(&ch->mailbox->cout); |
884 | 793 | ||
885 | if (tail == head && ch->mailbox->cin == ctail && bc->tbusy == 0) | 794 | if (tail == head && readw(&ch->mailbox->cin) == ctail && readb(&bc->tbusy) == 0) |
886 | chars = 0; | 795 | chars = 0; |
887 | else | 796 | else { /* Begin if some space on the card has been used */ |
888 | { /* Begin if some space on the card has been used */ | 797 | head = readw(&bc->tin) & (ch->txbufsize - 1); |
889 | |||
890 | head = bc->tin & (ch->txbufsize - 1); | ||
891 | tail &= (ch->txbufsize - 1); | 798 | tail &= (ch->txbufsize - 1); |
892 | |||
893 | /* -------------------------------------------------------------- | 799 | /* -------------------------------------------------------------- |
894 | The logic here is basically opposite of the above pc_write_room | 800 | The logic here is basically opposite of the above pc_write_room |
895 | here we are finding the amount of bytes in the buffer filled. | 801 | here we are finding the amount of bytes in the buffer filled. |
896 | Not the amount of bytes empty. | 802 | Not the amount of bytes empty. |
897 | ------------------------------------------------------------------- */ | 803 | ------------------------------------------------------------------- */ |
898 | |||
899 | if ((remain = tail - head - 1) < 0 ) | 804 | if ((remain = tail - head - 1) < 0 ) |
900 | remain += ch->txbufsize; | 805 | remain += ch->txbufsize; |
901 | |||
902 | chars = (int)(ch->txbufsize - remain); | 806 | chars = (int)(ch->txbufsize - remain); |
903 | |||
904 | /* ------------------------------------------------------------- | 807 | /* ------------------------------------------------------------- |
905 | Make it possible to wakeup anything waiting for output | 808 | Make it possible to wakeup anything waiting for output |
906 | in tty_ioctl.c, etc. | 809 | in tty_ioctl.c, etc. |
@@ -908,15 +811,12 @@ static int pc_chars_in_buffer(struct tty_struct *tty) | |||
908 | If not already set. Setup an event to indicate when the | 811 | If not already set. Setup an event to indicate when the |
909 | transmit buffer empties | 812 | transmit buffer empties |
910 | ----------------------------------------------------------------- */ | 813 | ----------------------------------------------------------------- */ |
911 | |||
912 | if (!(ch->statusflags & EMPTYWAIT)) | 814 | if (!(ch->statusflags & EMPTYWAIT)) |
913 | setup_empty_event(tty,ch); | 815 | setup_empty_event(tty,ch); |
914 | 816 | ||
915 | } /* End if some space on the card has been used */ | 817 | } /* End if some space on the card has been used */ |
916 | |||
917 | memoff(ch); | 818 | memoff(ch); |
918 | restore_flags(flags); | 819 | spin_unlock_irqrestore(&epca_lock, flags); |
919 | |||
920 | /* Return number of characters residing on card. */ | 820 | /* Return number of characters residing on card. */ |
921 | return(chars); | 821 | return(chars); |
922 | 822 | ||
@@ -930,67 +830,46 @@ static void pc_flush_buffer(struct tty_struct *tty) | |||
930 | unsigned int tail; | 830 | unsigned int tail; |
931 | unsigned long flags; | 831 | unsigned long flags; |
932 | struct channel *ch; | 832 | struct channel *ch; |
933 | volatile struct board_chan *bc; | 833 | struct board_chan *bc; |
934 | |||
935 | |||
936 | /* --------------------------------------------------------- | 834 | /* --------------------------------------------------------- |
937 | verifyChannel returns the channel from the tty struct | 835 | verifyChannel returns the channel from the tty struct |
938 | if it is valid. This serves as a sanity check. | 836 | if it is valid. This serves as a sanity check. |
939 | ------------------------------------------------------------- */ | 837 | ------------------------------------------------------------- */ |
940 | |||
941 | if ((ch = verifyChannel(tty)) == NULL) | 838 | if ((ch = verifyChannel(tty)) == NULL) |
942 | return; | 839 | return; |
943 | 840 | ||
944 | save_flags(flags); | 841 | spin_lock_irqsave(&epca_lock, flags); |
945 | cli(); | ||
946 | |||
947 | globalwinon(ch); | 842 | globalwinon(ch); |
948 | |||
949 | bc = ch->brdchan; | 843 | bc = ch->brdchan; |
950 | tail = bc->tout; | 844 | tail = readw(&bc->tout); |
951 | |||
952 | /* Have FEP move tout pointer; effectively flushing transmit buffer */ | 845 | /* Have FEP move tout pointer; effectively flushing transmit buffer */ |
953 | |||
954 | fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0); | 846 | fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0); |
955 | |||
956 | memoff(ch); | 847 | memoff(ch); |
957 | restore_flags(flags); | 848 | spin_unlock_irqrestore(&epca_lock, flags); |
958 | |||
959 | wake_up_interruptible(&tty->write_wait); | 849 | wake_up_interruptible(&tty->write_wait); |
960 | tty_wakeup(tty); | 850 | tty_wakeup(tty); |
961 | |||
962 | } /* End pc_flush_buffer */ | 851 | } /* End pc_flush_buffer */ |
963 | 852 | ||
964 | /* ------------------ Begin pc_flush_chars ---------------------- */ | 853 | /* ------------------ Begin pc_flush_chars ---------------------- */ |
965 | 854 | ||
966 | static void pc_flush_chars(struct tty_struct *tty) | 855 | static void pc_flush_chars(struct tty_struct *tty) |
967 | { /* Begin pc_flush_chars */ | 856 | { /* Begin pc_flush_chars */ |
968 | |||
969 | struct channel * ch; | 857 | struct channel * ch; |
970 | |||
971 | /* --------------------------------------------------------- | 858 | /* --------------------------------------------------------- |
972 | verifyChannel returns the channel from the tty struct | 859 | verifyChannel returns the channel from the tty struct |
973 | if it is valid. This serves as a sanity check. | 860 | if it is valid. This serves as a sanity check. |
974 | ------------------------------------------------------------- */ | 861 | ------------------------------------------------------------- */ |
975 | 862 | if ((ch = verifyChannel(tty)) != NULL) { | |
976 | if ((ch = verifyChannel(tty)) != NULL) | ||
977 | { | ||
978 | unsigned long flags; | 863 | unsigned long flags; |
979 | 864 | spin_lock_irqsave(&epca_lock, flags); | |
980 | save_flags(flags); | ||
981 | cli(); | ||
982 | |||
983 | /* ---------------------------------------------------------------- | 865 | /* ---------------------------------------------------------------- |
984 | If not already set and the transmitter is busy setup an event | 866 | If not already set and the transmitter is busy setup an event |
985 | to indicate when the transmit empties. | 867 | to indicate when the transmit empties. |
986 | ------------------------------------------------------------------- */ | 868 | ------------------------------------------------------------------- */ |
987 | |||
988 | if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT)) | 869 | if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT)) |
989 | setup_empty_event(tty,ch); | 870 | setup_empty_event(tty,ch); |
990 | 871 | spin_unlock_irqrestore(&epca_lock, flags); | |
991 | restore_flags(flags); | ||
992 | } | 872 | } |
993 | |||
994 | } /* End pc_flush_chars */ | 873 | } /* End pc_flush_chars */ |
995 | 874 | ||
996 | /* ------------------ Begin block_til_ready ---------------------- */ | 875 | /* ------------------ Begin block_til_ready ---------------------- */ |
@@ -998,14 +877,11 @@ static void pc_flush_chars(struct tty_struct *tty) | |||
998 | static int block_til_ready(struct tty_struct *tty, | 877 | static int block_til_ready(struct tty_struct *tty, |
999 | struct file *filp, struct channel *ch) | 878 | struct file *filp, struct channel *ch) |
1000 | { /* Begin block_til_ready */ | 879 | { /* Begin block_til_ready */ |
1001 | |||
1002 | DECLARE_WAITQUEUE(wait,current); | 880 | DECLARE_WAITQUEUE(wait,current); |
1003 | int retval, do_clocal = 0; | 881 | int retval, do_clocal = 0; |
1004 | unsigned long flags; | 882 | unsigned long flags; |
1005 | 883 | ||
1006 | 884 | if (tty_hung_up_p(filp)) { | |
1007 | if (tty_hung_up_p(filp)) | ||
1008 | { | ||
1009 | if (ch->asyncflags & ASYNC_HUP_NOTIFY) | 885 | if (ch->asyncflags & ASYNC_HUP_NOTIFY) |
1010 | retval = -EAGAIN; | 886 | retval = -EAGAIN; |
1011 | else | 887 | else |
@@ -1017,8 +893,7 @@ static int block_til_ready(struct tty_struct *tty, | |||
1017 | If the device is in the middle of being closed, then block | 893 | If the device is in the middle of being closed, then block |
1018 | until it's done, and then try again. | 894 | until it's done, and then try again. |
1019 | -------------------------------------------------------------------- */ | 895 | -------------------------------------------------------------------- */ |
1020 | if (ch->asyncflags & ASYNC_CLOSING) | 896 | if (ch->asyncflags & ASYNC_CLOSING) { |
1021 | { | ||
1022 | interruptible_sleep_on(&ch->close_wait); | 897 | interruptible_sleep_on(&ch->close_wait); |
1023 | 898 | ||
1024 | if (ch->asyncflags & ASYNC_HUP_NOTIFY) | 899 | if (ch->asyncflags & ASYNC_HUP_NOTIFY) |
@@ -1027,43 +902,29 @@ static int block_til_ready(struct tty_struct *tty, | |||
1027 | return -ERESTARTSYS; | 902 | return -ERESTARTSYS; |
1028 | } | 903 | } |
1029 | 904 | ||
1030 | if (filp->f_flags & O_NONBLOCK) | 905 | if (filp->f_flags & O_NONBLOCK) { |
1031 | { | ||
1032 | /* ----------------------------------------------------------------- | 906 | /* ----------------------------------------------------------------- |
1033 | If non-blocking mode is set, then make the check up front | 907 | If non-blocking mode is set, then make the check up front |
1034 | and then exit. | 908 | and then exit. |
1035 | -------------------------------------------------------------------- */ | 909 | -------------------------------------------------------------------- */ |
1036 | |||
1037 | ch->asyncflags |= ASYNC_NORMAL_ACTIVE; | 910 | ch->asyncflags |= ASYNC_NORMAL_ACTIVE; |
1038 | |||
1039 | return 0; | 911 | return 0; |
1040 | } | 912 | } |
1041 | |||
1042 | |||
1043 | if (tty->termios->c_cflag & CLOCAL) | 913 | if (tty->termios->c_cflag & CLOCAL) |
1044 | do_clocal = 1; | 914 | do_clocal = 1; |
1045 | 915 | /* Block waiting for the carrier detect and the line to become free */ | |
1046 | /* Block waiting for the carrier detect and the line to become free */ | ||
1047 | 916 | ||
1048 | retval = 0; | 917 | retval = 0; |
1049 | add_wait_queue(&ch->open_wait, &wait); | 918 | add_wait_queue(&ch->open_wait, &wait); |
1050 | save_flags(flags); | ||
1051 | cli(); | ||
1052 | |||
1053 | 919 | ||
920 | spin_lock_irqsave(&epca_lock, flags); | ||
1054 | /* We dec count so that pc_close will know when to free things */ | 921 | /* We dec count so that pc_close will know when to free things */ |
1055 | if (!tty_hung_up_p(filp)) | 922 | if (!tty_hung_up_p(filp)) |
1056 | ch->count--; | 923 | ch->count--; |
1057 | |||
1058 | restore_flags(flags); | ||
1059 | |||
1060 | ch->blocked_open++; | 924 | ch->blocked_open++; |
1061 | |||
1062 | while(1) | 925 | while(1) |
1063 | { /* Begin forever while */ | 926 | { /* Begin forever while */ |
1064 | |||
1065 | set_current_state(TASK_INTERRUPTIBLE); | 927 | set_current_state(TASK_INTERRUPTIBLE); |
1066 | |||
1067 | if (tty_hung_up_p(filp) || | 928 | if (tty_hung_up_p(filp) || |
1068 | !(ch->asyncflags & ASYNC_INITIALIZED)) | 929 | !(ch->asyncflags & ASYNC_INITIALIZED)) |
1069 | { | 930 | { |
@@ -1073,17 +934,14 @@ static int block_til_ready(struct tty_struct *tty, | |||
1073 | retval = -ERESTARTSYS; | 934 | retval = -ERESTARTSYS; |
1074 | break; | 935 | break; |
1075 | } | 936 | } |
1076 | |||
1077 | if (!(ch->asyncflags & ASYNC_CLOSING) && | 937 | if (!(ch->asyncflags & ASYNC_CLOSING) && |
1078 | (do_clocal || (ch->imodem & ch->dcd))) | 938 | (do_clocal || (ch->imodem & ch->dcd))) |
1079 | break; | 939 | break; |
1080 | 940 | if (signal_pending(current)) { | |
1081 | if (signal_pending(current)) | ||
1082 | { | ||
1083 | retval = -ERESTARTSYS; | 941 | retval = -ERESTARTSYS; |
1084 | break; | 942 | break; |
1085 | } | 943 | } |
1086 | 944 | spin_unlock_irqrestore(&epca_lock, flags); | |
1087 | /* --------------------------------------------------------------- | 945 | /* --------------------------------------------------------------- |
1088 | Allow someone else to be scheduled. We will occasionally go | 946 | Allow someone else to be scheduled. We will occasionally go |
1089 | through this loop until one of the above conditions change. | 947 | through this loop until one of the above conditions change. |
@@ -1091,25 +949,23 @@ static int block_til_ready(struct tty_struct *tty, | |||
1091 | prevent this loop from hogging the cpu. | 949 | prevent this loop from hogging the cpu. |
1092 | ------------------------------------------------------------------ */ | 950 | ------------------------------------------------------------------ */ |
1093 | schedule(); | 951 | schedule(); |
952 | spin_lock_irqsave(&epca_lock, flags); | ||
1094 | 953 | ||
1095 | } /* End forever while */ | 954 | } /* End forever while */ |
1096 | 955 | ||
1097 | current->state = TASK_RUNNING; | 956 | current->state = TASK_RUNNING; |
1098 | remove_wait_queue(&ch->open_wait, &wait); | 957 | remove_wait_queue(&ch->open_wait, &wait); |
1099 | cli(); | ||
1100 | if (!tty_hung_up_p(filp)) | 958 | if (!tty_hung_up_p(filp)) |
1101 | ch->count++; | 959 | ch->count++; |
1102 | restore_flags(flags); | ||
1103 | |||
1104 | ch->blocked_open--; | 960 | ch->blocked_open--; |
1105 | 961 | ||
962 | spin_unlock_irqrestore(&epca_lock, flags); | ||
963 | |||
1106 | if (retval) | 964 | if (retval) |
1107 | return retval; | 965 | return retval; |
1108 | 966 | ||
1109 | ch->asyncflags |= ASYNC_NORMAL_ACTIVE; | 967 | ch->asyncflags |= ASYNC_NORMAL_ACTIVE; |
1110 | |||
1111 | return 0; | 968 | return 0; |
1112 | |||
1113 | } /* End block_til_ready */ | 969 | } /* End block_til_ready */ |
1114 | 970 | ||
1115 | /* ------------------ Begin pc_open ---------------------- */ | 971 | /* ------------------ Begin pc_open ---------------------- */ |
@@ -1120,17 +976,12 @@ static int pc_open(struct tty_struct *tty, struct file * filp) | |||
1120 | struct channel *ch; | 976 | struct channel *ch; |
1121 | unsigned long flags; | 977 | unsigned long flags; |
1122 | int line, retval, boardnum; | 978 | int line, retval, boardnum; |
1123 | volatile struct board_chan *bc; | 979 | struct board_chan *bc; |
1124 | volatile unsigned int head; | 980 | unsigned int head; |
1125 | 981 | ||
1126 | line = tty->index; | 982 | line = tty->index; |
1127 | if (line < 0 || line >= nbdevs) | 983 | if (line < 0 || line >= nbdevs) |
1128 | { | 984 | return -ENODEV; |
1129 | printk(KERN_ERR "<Error> - pc_open : line out of range in pc_open\n"); | ||
1130 | tty->driver_data = NULL; | ||
1131 | return(-ENODEV); | ||
1132 | } | ||
1133 | |||
1134 | 985 | ||
1135 | ch = &digi_channels[line]; | 986 | ch = &digi_channels[line]; |
1136 | boardnum = ch->boardnum; | 987 | boardnum = ch->boardnum; |
@@ -1143,66 +994,49 @@ static int pc_open(struct tty_struct *tty, struct file * filp) | |||
1143 | goes here. | 994 | goes here. |
1144 | ---------------------------------------------------------------------- */ | 995 | ---------------------------------------------------------------------- */ |
1145 | 996 | ||
1146 | if (invalid_lilo_config) | 997 | if (invalid_lilo_config) { |
1147 | { | ||
1148 | if (setup_error_code & INVALID_BOARD_TYPE) | 998 | if (setup_error_code & INVALID_BOARD_TYPE) |
1149 | printk(KERN_ERR "<Error> - pc_open: Invalid board type specified in LILO command\n"); | 999 | printk(KERN_ERR "epca: pc_open: Invalid board type specified in kernel options.\n"); |
1150 | |||
1151 | if (setup_error_code & INVALID_NUM_PORTS) | 1000 | if (setup_error_code & INVALID_NUM_PORTS) |
1152 | printk(KERN_ERR "<Error> - pc_open: Invalid number of ports specified in LILO command\n"); | 1001 | printk(KERN_ERR "epca: pc_open: Invalid number of ports specified in kernel options.\n"); |
1153 | |||
1154 | if (setup_error_code & INVALID_MEM_BASE) | 1002 | if (setup_error_code & INVALID_MEM_BASE) |
1155 | printk(KERN_ERR "<Error> - pc_open: Invalid board memory address specified in LILO command\n"); | 1003 | printk(KERN_ERR "epca: pc_open: Invalid board memory address specified in kernel options.\n"); |
1156 | |||
1157 | if (setup_error_code & INVALID_PORT_BASE) | 1004 | if (setup_error_code & INVALID_PORT_BASE) |
1158 | printk(KERN_ERR "<Error> - pc_open: Invalid board port address specified in LILO command\n"); | 1005 | printk(KERN_ERR "epca; pc_open: Invalid board port address specified in kernel options.\n"); |
1159 | |||
1160 | if (setup_error_code & INVALID_BOARD_STATUS) | 1006 | if (setup_error_code & INVALID_BOARD_STATUS) |
1161 | printk(KERN_ERR "<Error> - pc_open: Invalid board status specified in LILO command\n"); | 1007 | printk(KERN_ERR "epca: pc_open: Invalid board status specified in kernel options.\n"); |
1162 | |||
1163 | if (setup_error_code & INVALID_ALTPIN) | 1008 | if (setup_error_code & INVALID_ALTPIN) |
1164 | printk(KERN_ERR "<Error> - pc_open: Invalid board altpin specified in LILO command\n"); | 1009 | printk(KERN_ERR "epca: pc_open: Invalid board altpin specified in kernel options;\n"); |
1165 | |||
1166 | tty->driver_data = NULL; /* Mark this device as 'down' */ | 1010 | tty->driver_data = NULL; /* Mark this device as 'down' */ |
1167 | return(-ENODEV); | 1011 | return -ENODEV; |
1168 | } | 1012 | } |
1169 | 1013 | if (boardnum >= num_cards || boards[boardnum].status == DISABLED) { | |
1170 | if ((boardnum >= num_cards) || (boards[boardnum].status == DISABLED)) | ||
1171 | { | ||
1172 | tty->driver_data = NULL; /* Mark this device as 'down' */ | 1014 | tty->driver_data = NULL; /* Mark this device as 'down' */ |
1173 | return(-ENODEV); | 1015 | return(-ENODEV); |
1174 | } | 1016 | } |
1175 | 1017 | ||
1176 | if (( bc = ch->brdchan) == 0) | 1018 | if ((bc = ch->brdchan) == 0) { |
1177 | { | ||
1178 | tty->driver_data = NULL; | 1019 | tty->driver_data = NULL; |
1179 | return(-ENODEV); | 1020 | return -ENODEV; |
1180 | } | 1021 | } |
1181 | 1022 | ||
1023 | spin_lock_irqsave(&epca_lock, flags); | ||
1182 | /* ------------------------------------------------------------------ | 1024 | /* ------------------------------------------------------------------ |
1183 | Every time a channel is opened, increment a counter. This is | 1025 | Every time a channel is opened, increment a counter. This is |
1184 | necessary because we do not wish to flush and shutdown the channel | 1026 | necessary because we do not wish to flush and shutdown the channel |
1185 | until the last app holding the channel open, closes it. | 1027 | until the last app holding the channel open, closes it. |
1186 | --------------------------------------------------------------------- */ | 1028 | --------------------------------------------------------------------- */ |
1187 | |||
1188 | ch->count++; | 1029 | ch->count++; |
1189 | |||
1190 | /* ---------------------------------------------------------------- | 1030 | /* ---------------------------------------------------------------- |
1191 | Set a kernel structures pointer to our local channel | 1031 | Set a kernel structures pointer to our local channel |
1192 | structure. This way we can get to it when passed only | 1032 | structure. This way we can get to it when passed only |
1193 | a tty struct. | 1033 | a tty struct. |
1194 | ------------------------------------------------------------------ */ | 1034 | ------------------------------------------------------------------ */ |
1195 | |||
1196 | tty->driver_data = ch; | 1035 | tty->driver_data = ch; |
1197 | |||
1198 | /* ---------------------------------------------------------------- | 1036 | /* ---------------------------------------------------------------- |
1199 | If this is the first time the channel has been opened, initialize | 1037 | If this is the first time the channel has been opened, initialize |
1200 | the tty->termios struct otherwise let pc_close handle it. | 1038 | the tty->termios struct otherwise let pc_close handle it. |
1201 | -------------------------------------------------------------------- */ | 1039 | -------------------------------------------------------------------- */ |
1202 | |||
1203 | save_flags(flags); | ||
1204 | cli(); | ||
1205 | |||
1206 | globalwinon(ch); | 1040 | globalwinon(ch); |
1207 | ch->statusflags = 0; | 1041 | ch->statusflags = 0; |
1208 | 1042 | ||
@@ -1213,8 +1047,8 @@ static int pc_open(struct tty_struct *tty, struct file * filp) | |||
1213 | Set receive head and tail ptrs to each other. This indicates | 1047 | Set receive head and tail ptrs to each other. This indicates |
1214 | no data available to read. | 1048 | no data available to read. |
1215 | ----------------------------------------------------------------- */ | 1049 | ----------------------------------------------------------------- */ |
1216 | head = bc->rin; | 1050 | head = readw(&bc->rin); |
1217 | bc->rout = head; | 1051 | writew(head, &bc->rout); |
1218 | 1052 | ||
1219 | /* Set the channels associated tty structure */ | 1053 | /* Set the channels associated tty structure */ |
1220 | ch->tty = tty; | 1054 | ch->tty = tty; |
@@ -1224,122 +1058,74 @@ static int pc_open(struct tty_struct *tty, struct file * filp) | |||
1224 | issues, etc.... It effect both control flags and input flags. | 1058 | issues, etc.... It effect both control flags and input flags. |
1225 | -------------------------------------------------------------------- */ | 1059 | -------------------------------------------------------------------- */ |
1226 | epcaparam(tty,ch); | 1060 | epcaparam(tty,ch); |
1227 | |||
1228 | ch->asyncflags |= ASYNC_INITIALIZED; | 1061 | ch->asyncflags |= ASYNC_INITIALIZED; |
1229 | memoff(ch); | 1062 | memoff(ch); |
1230 | 1063 | spin_unlock_irqrestore(&epca_lock, flags); | |
1231 | restore_flags(flags); | ||
1232 | 1064 | ||
1233 | retval = block_til_ready(tty, filp, ch); | 1065 | retval = block_til_ready(tty, filp, ch); |
1234 | if (retval) | 1066 | if (retval) |
1235 | { | ||
1236 | return retval; | 1067 | return retval; |
1237 | } | ||
1238 | |||
1239 | /* ------------------------------------------------------------- | 1068 | /* ------------------------------------------------------------- |
1240 | Set this again in case a hangup set it to zero while this | 1069 | Set this again in case a hangup set it to zero while this |
1241 | open() was waiting for the line... | 1070 | open() was waiting for the line... |
1242 | --------------------------------------------------------------- */ | 1071 | --------------------------------------------------------------- */ |
1072 | spin_lock_irqsave(&epca_lock, flags); | ||
1243 | ch->tty = tty; | 1073 | ch->tty = tty; |
1244 | |||
1245 | save_flags(flags); | ||
1246 | cli(); | ||
1247 | globalwinon(ch); | 1074 | globalwinon(ch); |
1248 | |||
1249 | /* Enable Digi Data events */ | 1075 | /* Enable Digi Data events */ |
1250 | bc->idata = 1; | 1076 | writeb(1, &bc->idata); |
1251 | |||
1252 | memoff(ch); | 1077 | memoff(ch); |
1253 | restore_flags(flags); | 1078 | spin_unlock_irqrestore(&epca_lock, flags); |
1254 | |||
1255 | return 0; | 1079 | return 0; |
1256 | |||
1257 | } /* End pc_open */ | 1080 | } /* End pc_open */ |
1258 | 1081 | ||
1259 | #ifdef MODULE | ||
1260 | static int __init epca_module_init(void) | 1082 | static int __init epca_module_init(void) |
1261 | { /* Begin init_module */ | 1083 | { /* Begin init_module */ |
1262 | 1084 | return pc_init(); | |
1263 | unsigned long flags; | ||
1264 | |||
1265 | save_flags(flags); | ||
1266 | cli(); | ||
1267 | |||
1268 | pc_init(); | ||
1269 | |||
1270 | restore_flags(flags); | ||
1271 | |||
1272 | return(0); | ||
1273 | } | 1085 | } |
1274 | 1086 | ||
1275 | module_init(epca_module_init); | 1087 | module_init(epca_module_init); |
1276 | #endif | ||
1277 | 1088 | ||
1278 | #ifdef ENABLE_PCI | ||
1279 | static struct pci_driver epca_driver; | 1089 | static struct pci_driver epca_driver; |
1280 | #endif | ||
1281 | |||
1282 | #ifdef MODULE | ||
1283 | /* -------------------- Begin cleanup_module ---------------------- */ | ||
1284 | 1090 | ||
1285 | static void __exit epca_module_exit(void) | 1091 | static void __exit epca_module_exit(void) |
1286 | { | 1092 | { |
1287 | |||
1288 | int count, crd; | 1093 | int count, crd; |
1289 | struct board_info *bd; | 1094 | struct board_info *bd; |
1290 | struct channel *ch; | 1095 | struct channel *ch; |
1291 | unsigned long flags; | ||
1292 | 1096 | ||
1293 | del_timer_sync(&epca_timer); | 1097 | del_timer_sync(&epca_timer); |
1294 | 1098 | ||
1295 | save_flags(flags); | ||
1296 | cli(); | ||
1297 | |||
1298 | if ((tty_unregister_driver(pc_driver)) || | 1099 | if ((tty_unregister_driver(pc_driver)) || |
1299 | (tty_unregister_driver(pc_info))) | 1100 | (tty_unregister_driver(pc_info))) |
1300 | { | 1101 | { |
1301 | printk(KERN_WARNING "<Error> - DIGI : cleanup_module failed to un-register tty driver\n"); | 1102 | printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n"); |
1302 | restore_flags(flags); | ||
1303 | return; | 1103 | return; |
1304 | } | 1104 | } |
1305 | put_tty_driver(pc_driver); | 1105 | put_tty_driver(pc_driver); |
1306 | put_tty_driver(pc_info); | 1106 | put_tty_driver(pc_info); |
1307 | 1107 | ||
1308 | for (crd = 0; crd < num_cards; crd++) | 1108 | for (crd = 0; crd < num_cards; crd++) { /* Begin for each card */ |
1309 | { /* Begin for each card */ | ||
1310 | |||
1311 | bd = &boards[crd]; | 1109 | bd = &boards[crd]; |
1312 | |||
1313 | if (!bd) | 1110 | if (!bd) |
1314 | { /* Begin sanity check */ | 1111 | { /* Begin sanity check */ |
1315 | printk(KERN_ERR "<Error> - Digi : cleanup_module failed\n"); | 1112 | printk(KERN_ERR "<Error> - Digi : cleanup_module failed\n"); |
1316 | return; | 1113 | return; |
1317 | } /* End sanity check */ | 1114 | } /* End sanity check */ |
1318 | 1115 | ch = card_ptr[crd]; | |
1319 | ch = card_ptr[crd]; | ||
1320 | |||
1321 | for (count = 0; count < bd->numports; count++, ch++) | 1116 | for (count = 0; count < bd->numports; count++, ch++) |
1322 | { /* Begin for each port */ | 1117 | { /* Begin for each port */ |
1323 | 1118 | if (ch) { | |
1324 | if (ch) | ||
1325 | { | ||
1326 | if (ch->tty) | 1119 | if (ch->tty) |
1327 | tty_hangup(ch->tty); | 1120 | tty_hangup(ch->tty); |
1328 | kfree(ch->tmp_buf); | 1121 | kfree(ch->tmp_buf); |
1329 | } | 1122 | } |
1330 | |||
1331 | } /* End for each port */ | 1123 | } /* End for each port */ |
1332 | } /* End for each card */ | 1124 | } /* End for each card */ |
1333 | |||
1334 | #ifdef ENABLE_PCI | ||
1335 | pci_unregister_driver (&epca_driver); | 1125 | pci_unregister_driver (&epca_driver); |
1336 | #endif | ||
1337 | |||
1338 | restore_flags(flags); | ||
1339 | |||
1340 | } | 1126 | } |
1127 | |||
1341 | module_exit(epca_module_exit); | 1128 | module_exit(epca_module_exit); |
1342 | #endif /* MODULE */ | ||
1343 | 1129 | ||
1344 | static struct tty_operations pc_ops = { | 1130 | static struct tty_operations pc_ops = { |
1345 | .open = pc_open, | 1131 | .open = pc_open, |
@@ -1371,34 +1157,15 @@ static struct tty_operations info_ops = { | |||
1371 | 1157 | ||
1372 | /* ------------------ Begin pc_init ---------------------- */ | 1158 | /* ------------------ Begin pc_init ---------------------- */ |
1373 | 1159 | ||
1374 | int __init pc_init(void) | 1160 | static int __init pc_init(void) |
1375 | { /* Begin pc_init */ | 1161 | { /* Begin pc_init */ |
1376 | |||
1377 | /* ---------------------------------------------------------------- | ||
1378 | pc_init is called by the operating system during boot up prior to | ||
1379 | any open calls being made. In the older versions of Linux (Prior | ||
1380 | to 2.0.0) an entry is made into tty_io.c. A pointer to the last | ||
1381 | memory location (from kernel space) used (kmem_start) is passed | ||
1382 | to pc_init. It is pc_inits responsibility to modify this value | ||
1383 | for any memory that the Digi driver might need and then return | ||
1384 | this value to the operating system. For example if the driver | ||
1385 | wishes to allocate 1K of kernel memory, pc_init would return | ||
1386 | (kmem_start + 1024). This memory (Between kmem_start and kmem_start | ||
1387 | + 1024) would then be available for use exclusively by the driver. | ||
1388 | In this case our driver does not allocate any of this kernel | ||
1389 | memory. | ||
1390 | ------------------------------------------------------------------*/ | ||
1391 | |||
1392 | ulong flags; | ||
1393 | int crd; | 1162 | int crd; |
1394 | struct board_info *bd; | 1163 | struct board_info *bd; |
1395 | unsigned char board_id = 0; | 1164 | unsigned char board_id = 0; |
1396 | 1165 | ||
1397 | #ifdef ENABLE_PCI | ||
1398 | int pci_boards_found, pci_count; | 1166 | int pci_boards_found, pci_count; |
1399 | 1167 | ||
1400 | pci_count = 0; | 1168 | pci_count = 0; |
1401 | #endif /* ENABLE_PCI */ | ||
1402 | 1169 | ||
1403 | pc_driver = alloc_tty_driver(MAX_ALLOC); | 1170 | pc_driver = alloc_tty_driver(MAX_ALLOC); |
1404 | if (!pc_driver) | 1171 | if (!pc_driver) |
@@ -1416,8 +1183,7 @@ int __init pc_init(void) | |||
1416 | Note : If LILO has ran epca_setup then epca_setup will handle defining | 1183 | Note : If LILO has ran epca_setup then epca_setup will handle defining |
1417 | num_cards as well as copying the data into the board structure. | 1184 | num_cards as well as copying the data into the board structure. |
1418 | -------------------------------------------------------------------------- */ | 1185 | -------------------------------------------------------------------------- */ |
1419 | if (!liloconfig) | 1186 | if (!liloconfig) { /* Begin driver has been configured via. epcaconfig */ |
1420 | { /* Begin driver has been configured via. epcaconfig */ | ||
1421 | 1187 | ||
1422 | nbdevs = NBDEVS; | 1188 | nbdevs = NBDEVS; |
1423 | num_cards = NUMCARDS; | 1189 | num_cards = NUMCARDS; |
@@ -1440,8 +1206,6 @@ int __init pc_init(void) | |||
1440 | 1206 | ||
1441 | printk(KERN_INFO "DIGI epca driver version %s loaded.\n",VERSION); | 1207 | printk(KERN_INFO "DIGI epca driver version %s loaded.\n",VERSION); |
1442 | 1208 | ||
1443 | #ifdef ENABLE_PCI | ||
1444 | |||
1445 | /* ------------------------------------------------------------------ | 1209 | /* ------------------------------------------------------------------ |
1446 | NOTE : This code assumes that the number of ports found in | 1210 | NOTE : This code assumes that the number of ports found in |
1447 | the boards array is correct. This could be wrong if | 1211 | the boards array is correct. This could be wrong if |
@@ -1467,8 +1231,6 @@ int __init pc_init(void) | |||
1467 | pci_boards_found += init_PCI(); | 1231 | pci_boards_found += init_PCI(); |
1468 | num_cards += pci_boards_found; | 1232 | num_cards += pci_boards_found; |
1469 | 1233 | ||
1470 | #endif /* ENABLE_PCI */ | ||
1471 | |||
1472 | pc_driver->owner = THIS_MODULE; | 1234 | pc_driver->owner = THIS_MODULE; |
1473 | pc_driver->name = "ttyD"; | 1235 | pc_driver->name = "ttyD"; |
1474 | pc_driver->devfs_name = "tts/D"; | 1236 | pc_driver->devfs_name = "tts/D"; |
@@ -1499,9 +1261,6 @@ int __init pc_init(void) | |||
1499 | tty_set_operations(pc_info, &info_ops); | 1261 | tty_set_operations(pc_info, &info_ops); |
1500 | 1262 | ||
1501 | 1263 | ||
1502 | save_flags(flags); | ||
1503 | cli(); | ||
1504 | |||
1505 | for (crd = 0; crd < num_cards; crd++) | 1264 | for (crd = 0; crd < num_cards; crd++) |
1506 | { /* Begin for each card */ | 1265 | { /* Begin for each card */ |
1507 | 1266 | ||
@@ -1610,11 +1369,7 @@ int __init pc_init(void) | |||
1610 | if ((board_id & 0x30) == 0x30) | 1369 | if ((board_id & 0x30) == 0x30) |
1611 | bd->memory_seg = 0x8000; | 1370 | bd->memory_seg = 0x8000; |
1612 | 1371 | ||
1613 | } /* End it is an XI card */ | 1372 | } else printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n",(int)bd->port); |
1614 | else | ||
1615 | { | ||
1616 | printk(KERN_ERR "<Error> - Board at 0x%x doesn't appear to be an XI\n",(int)bd->port); | ||
1617 | } | ||
1618 | break; | 1373 | break; |
1619 | 1374 | ||
1620 | } /* End switch on bd->type */ | 1375 | } /* End switch on bd->type */ |
@@ -1634,9 +1389,6 @@ int __init pc_init(void) | |||
1634 | init_timer(&epca_timer); | 1389 | init_timer(&epca_timer); |
1635 | epca_timer.function = epcapoll; | 1390 | epca_timer.function = epcapoll; |
1636 | mod_timer(&epca_timer, jiffies + HZ/25); | 1391 | mod_timer(&epca_timer, jiffies + HZ/25); |
1637 | |||
1638 | restore_flags(flags); | ||
1639 | |||
1640 | return 0; | 1392 | return 0; |
1641 | 1393 | ||
1642 | } /* End pc_init */ | 1394 | } /* End pc_init */ |
@@ -1647,10 +1399,10 @@ static void post_fep_init(unsigned int crd) | |||
1647 | { /* Begin post_fep_init */ | 1399 | { /* Begin post_fep_init */ |
1648 | 1400 | ||
1649 | int i; | 1401 | int i; |
1650 | unchar *memaddr; | 1402 | unsigned char *memaddr; |
1651 | volatile struct global_data *gd; | 1403 | struct global_data *gd; |
1652 | struct board_info *bd; | 1404 | struct board_info *bd; |
1653 | volatile struct board_chan *bc; | 1405 | struct board_chan *bc; |
1654 | struct channel *ch; | 1406 | struct channel *ch; |
1655 | int shrinkmem = 0, lowwater ; | 1407 | int shrinkmem = 0, lowwater ; |
1656 | 1408 | ||
@@ -1669,9 +1421,7 @@ static void post_fep_init(unsigned int crd) | |||
1669 | after DIGI_INIT has been called will return the proper values. | 1421 | after DIGI_INIT has been called will return the proper values. |
1670 | ------------------------------------------------------------------- */ | 1422 | ------------------------------------------------------------------- */ |
1671 | 1423 | ||
1672 | if (bd->type >= PCIXEM) /* If the board in question is PCI */ | 1424 | if (bd->type >= PCIXEM) { /* Begin get PCI number of ports */ |
1673 | { /* Begin get PCI number of ports */ | ||
1674 | |||
1675 | /* -------------------------------------------------------------------- | 1425 | /* -------------------------------------------------------------------- |
1676 | Below we use XEMPORTS as a memory offset regardless of which PCI | 1426 | Below we use XEMPORTS as a memory offset regardless of which PCI |
1677 | card it is. This is because all of the supported PCI cards have | 1427 | card it is. This is because all of the supported PCI cards have |
@@ -1685,15 +1435,15 @@ static void post_fep_init(unsigned int crd) | |||
1685 | (FYI - The id should be located at 0x1ac (And may use up to 4 bytes | 1435 | (FYI - The id should be located at 0x1ac (And may use up to 4 bytes |
1686 | if the box in question is a XEM or CX)). | 1436 | if the box in question is a XEM or CX)). |
1687 | ------------------------------------------------------------------------ */ | 1437 | ------------------------------------------------------------------------ */ |
1688 | 1438 | /* PCI cards are already remapped at this point ISA are not */ | |
1689 | bd->numports = (unsigned short)*(unsigned char *)bus_to_virt((unsigned long) | 1439 | bd->numports = readw(bd->re_map_membase + XEMPORTS); |
1690 | (bd->re_map_membase + XEMPORTS)); | ||
1691 | |||
1692 | |||
1693 | epcaassert(bd->numports <= 64,"PCI returned a invalid number of ports"); | 1440 | epcaassert(bd->numports <= 64,"PCI returned a invalid number of ports"); |
1694 | nbdevs += (bd->numports); | 1441 | nbdevs += (bd->numports); |
1695 | 1442 | } else { | |
1696 | } /* End get PCI number of ports */ | 1443 | /* Fix up the mappings for ISA/EISA etc */ |
1444 | /* FIXME: 64K - can we be smarter ? */ | ||
1445 | bd->re_map_membase = ioremap(bd->membase, 0x10000); | ||
1446 | } | ||
1697 | 1447 | ||
1698 | if (crd != 0) | 1448 | if (crd != 0) |
1699 | card_ptr[crd] = card_ptr[crd-1] + boards[crd-1].numports; | 1449 | card_ptr[crd] = card_ptr[crd-1] + boards[crd-1].numports; |
@@ -1701,19 +1451,9 @@ static void post_fep_init(unsigned int crd) | |||
1701 | card_ptr[crd] = &digi_channels[crd]; /* <- For card 0 only */ | 1451 | card_ptr[crd] = &digi_channels[crd]; /* <- For card 0 only */ |
1702 | 1452 | ||
1703 | ch = card_ptr[crd]; | 1453 | ch = card_ptr[crd]; |
1704 | |||
1705 | |||
1706 | epcaassert(ch <= &digi_channels[nbdevs - 1], "ch out of range"); | 1454 | epcaassert(ch <= &digi_channels[nbdevs - 1], "ch out of range"); |
1707 | 1455 | ||
1708 | memaddr = (unchar *)bd->re_map_membase; | 1456 | memaddr = bd->re_map_membase; |
1709 | |||
1710 | /* | ||
1711 | The below command is necessary because newer kernels (2.1.x and | ||
1712 | up) do not have a 1:1 virtual to physical mapping. The below | ||
1713 | call adjust for that. | ||
1714 | */ | ||
1715 | |||
1716 | memaddr = (unsigned char *)bus_to_virt((unsigned long)memaddr); | ||
1717 | 1457 | ||
1718 | /* ----------------------------------------------------------------- | 1458 | /* ----------------------------------------------------------------- |
1719 | The below assignment will set bc to point at the BEGINING of | 1459 | The below assignment will set bc to point at the BEGINING of |
@@ -1721,7 +1461,7 @@ static void post_fep_init(unsigned int crd) | |||
1721 | 8 and 64 of these structures. | 1461 | 8 and 64 of these structures. |
1722 | -------------------------------------------------------------------- */ | 1462 | -------------------------------------------------------------------- */ |
1723 | 1463 | ||
1724 | bc = (volatile struct board_chan *)((ulong)memaddr + CHANSTRUCT); | 1464 | bc = (struct board_chan *)(memaddr + CHANSTRUCT); |
1725 | 1465 | ||
1726 | /* ------------------------------------------------------------------- | 1466 | /* ------------------------------------------------------------------- |
1727 | The below assignment will set gd to point at the BEGINING of | 1467 | The below assignment will set gd to point at the BEGINING of |
@@ -1730,20 +1470,18 @@ static void post_fep_init(unsigned int crd) | |||
1730 | pointer begins at 0xd10. | 1470 | pointer begins at 0xd10. |
1731 | ---------------------------------------------------------------------- */ | 1471 | ---------------------------------------------------------------------- */ |
1732 | 1472 | ||
1733 | gd = (volatile struct global_data *)((ulong)memaddr + GLOBAL); | 1473 | gd = (struct global_data *)(memaddr + GLOBAL); |
1734 | 1474 | ||
1735 | /* -------------------------------------------------------------------- | 1475 | /* -------------------------------------------------------------------- |
1736 | XEPORTS (address 0xc22) points at the number of channels the | 1476 | XEPORTS (address 0xc22) points at the number of channels the |
1737 | card supports. (For 64XE, XI, XEM, and XR use 0xc02) | 1477 | card supports. (For 64XE, XI, XEM, and XR use 0xc02) |
1738 | ----------------------------------------------------------------------- */ | 1478 | ----------------------------------------------------------------------- */ |
1739 | 1479 | ||
1740 | if (((bd->type == PCXEVE) | (bd->type == PCXE)) && | 1480 | if ((bd->type == PCXEVE || bd->type == PCXE) && (readw(memaddr + XEPORTS) < 3)) |
1741 | (*(ushort *)((ulong)memaddr + XEPORTS) < 3)) | ||
1742 | shrinkmem = 1; | 1481 | shrinkmem = 1; |
1743 | if (bd->type < PCIXEM) | 1482 | if (bd->type < PCIXEM) |
1744 | if (!request_region((int)bd->port, 4, board_desc[bd->type])) | 1483 | if (!request_region((int)bd->port, 4, board_desc[bd->type])) |
1745 | return; | 1484 | return; |
1746 | |||
1747 | memwinon(bd, 0); | 1485 | memwinon(bd, 0); |
1748 | 1486 | ||
1749 | /* -------------------------------------------------------------------- | 1487 | /* -------------------------------------------------------------------- |
@@ -1753,17 +1491,16 @@ static void post_fep_init(unsigned int crd) | |||
1753 | 1491 | ||
1754 | /* For every port on the card do ..... */ | 1492 | /* For every port on the card do ..... */ |
1755 | 1493 | ||
1756 | for (i = 0; i < bd->numports; i++, ch++, bc++) | 1494 | for (i = 0; i < bd->numports; i++, ch++, bc++) { /* Begin for each port */ |
1757 | { /* Begin for each port */ | 1495 | unsigned long flags; |
1758 | 1496 | ||
1759 | ch->brdchan = bc; | 1497 | ch->brdchan = bc; |
1760 | ch->mailbox = gd; | 1498 | ch->mailbox = gd; |
1761 | INIT_WORK(&ch->tqueue, do_softint, ch); | 1499 | INIT_WORK(&ch->tqueue, do_softint, ch); |
1762 | ch->board = &boards[crd]; | 1500 | ch->board = &boards[crd]; |
1763 | 1501 | ||
1764 | switch (bd->type) | 1502 | spin_lock_irqsave(&epca_lock, flags); |
1765 | { /* Begin switch bd->type */ | 1503 | switch (bd->type) { |
1766 | |||
1767 | /* ---------------------------------------------------------------- | 1504 | /* ---------------------------------------------------------------- |
1768 | Since some of the boards use different bitmaps for their | 1505 | Since some of the boards use different bitmaps for their |
1769 | control signals we cannot hard code these values and retain | 1506 | control signals we cannot hard code these values and retain |
@@ -1796,14 +1533,12 @@ static void post_fep_init(unsigned int crd) | |||
1796 | 1533 | ||
1797 | } /* End switch bd->type */ | 1534 | } /* End switch bd->type */ |
1798 | 1535 | ||
1799 | if (boards[crd].altpin) | 1536 | if (boards[crd].altpin) { |
1800 | { | ||
1801 | ch->dsr = ch->m_dcd; | 1537 | ch->dsr = ch->m_dcd; |
1802 | ch->dcd = ch->m_dsr; | 1538 | ch->dcd = ch->m_dsr; |
1803 | ch->digiext.digi_flags |= DIGI_ALTPIN; | 1539 | ch->digiext.digi_flags |= DIGI_ALTPIN; |
1804 | } | 1540 | } |
1805 | else | 1541 | else { |
1806 | { | ||
1807 | ch->dcd = ch->m_dcd; | 1542 | ch->dcd = ch->m_dcd; |
1808 | ch->dsr = ch->m_dsr; | 1543 | ch->dsr = ch->m_dsr; |
1809 | } | 1544 | } |
@@ -1813,14 +1548,12 @@ static void post_fep_init(unsigned int crd) | |||
1813 | ch->magic = EPCA_MAGIC; | 1548 | ch->magic = EPCA_MAGIC; |
1814 | ch->tty = NULL; | 1549 | ch->tty = NULL; |
1815 | 1550 | ||
1816 | if (shrinkmem) | 1551 | if (shrinkmem) { |
1817 | { | ||
1818 | fepcmd(ch, SETBUFFER, 32, 0, 0, 0); | 1552 | fepcmd(ch, SETBUFFER, 32, 0, 0, 0); |
1819 | shrinkmem = 0; | 1553 | shrinkmem = 0; |
1820 | } | 1554 | } |
1821 | 1555 | ||
1822 | switch (bd->type) | 1556 | switch (bd->type) { |
1823 | { /* Begin switch bd->type */ | ||
1824 | 1557 | ||
1825 | case PCIXEM: | 1558 | case PCIXEM: |
1826 | case PCIXRJ: | 1559 | case PCIXRJ: |
@@ -1878,13 +1611,13 @@ static void post_fep_init(unsigned int crd) | |||
1878 | 1611 | ||
1879 | fepcmd(ch, SRXHWATER, (3 * ch->rxbufsize / 4), 0, 10, 0); | 1612 | fepcmd(ch, SRXHWATER, (3 * ch->rxbufsize / 4), 0, 10, 0); |
1880 | 1613 | ||
1881 | bc->edelay = 100; | 1614 | writew(100, &bc->edelay); |
1882 | bc->idata = 1; | 1615 | writeb(1, &bc->idata); |
1883 | 1616 | ||
1884 | ch->startc = bc->startc; | 1617 | ch->startc = readb(&bc->startc); |
1885 | ch->stopc = bc->stopc; | 1618 | ch->stopc = readb(&bc->stopc); |
1886 | ch->startca = bc->startca; | 1619 | ch->startca = readb(&bc->startca); |
1887 | ch->stopca = bc->stopca; | 1620 | ch->stopca = readb(&bc->stopca); |
1888 | 1621 | ||
1889 | ch->fepcflag = 0; | 1622 | ch->fepcflag = 0; |
1890 | ch->fepiflag = 0; | 1623 | ch->fepiflag = 0; |
@@ -1899,27 +1632,23 @@ static void post_fep_init(unsigned int crd) | |||
1899 | ch->blocked_open = 0; | 1632 | ch->blocked_open = 0; |
1900 | init_waitqueue_head(&ch->open_wait); | 1633 | init_waitqueue_head(&ch->open_wait); |
1901 | init_waitqueue_head(&ch->close_wait); | 1634 | init_waitqueue_head(&ch->close_wait); |
1635 | |||
1636 | spin_unlock_irqrestore(&epca_lock, flags); | ||
1637 | |||
1902 | ch->tmp_buf = kmalloc(ch->txbufsize,GFP_KERNEL); | 1638 | ch->tmp_buf = kmalloc(ch->txbufsize,GFP_KERNEL); |
1903 | if (!(ch->tmp_buf)) | 1639 | if (!ch->tmp_buf) { |
1904 | { | ||
1905 | printk(KERN_ERR "POST FEP INIT : kmalloc failed for port 0x%x\n",i); | 1640 | printk(KERN_ERR "POST FEP INIT : kmalloc failed for port 0x%x\n",i); |
1906 | release_region((int)bd->port, 4); | 1641 | release_region((int)bd->port, 4); |
1907 | while(i-- > 0) | 1642 | while(i-- > 0) |
1908 | kfree((ch--)->tmp_buf); | 1643 | kfree((ch--)->tmp_buf); |
1909 | return; | 1644 | return; |
1910 | } | 1645 | } else |
1911 | else | ||
1912 | memset((void *)ch->tmp_buf,0,ch->txbufsize); | 1646 | memset((void *)ch->tmp_buf,0,ch->txbufsize); |
1913 | } /* End for each port */ | 1647 | } /* End for each port */ |
1914 | 1648 | ||
1915 | printk(KERN_INFO | 1649 | printk(KERN_INFO |
1916 | "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n", | 1650 | "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n", |
1917 | VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports); | 1651 | VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports); |
1918 | sprintf(mesg, | ||
1919 | "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n", | ||
1920 | VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports); | ||
1921 | console_print(mesg); | ||
1922 | |||
1923 | memwinoff(bd, 0); | 1652 | memwinoff(bd, 0); |
1924 | 1653 | ||
1925 | } /* End post_fep_init */ | 1654 | } /* End post_fep_init */ |
@@ -1943,9 +1672,6 @@ static void epcapoll(unsigned long ignored) | |||
1943 | buffer empty) and acts on those events. | 1672 | buffer empty) and acts on those events. |
1944 | ----------------------------------------------------------------------- */ | 1673 | ----------------------------------------------------------------------- */ |
1945 | 1674 | ||
1946 | save_flags(flags); | ||
1947 | cli(); | ||
1948 | |||
1949 | for (crd = 0; crd < num_cards; crd++) | 1675 | for (crd = 0; crd < num_cards; crd++) |
1950 | { /* Begin for each card */ | 1676 | { /* Begin for each card */ |
1951 | 1677 | ||
@@ -1961,6 +1687,8 @@ static void epcapoll(unsigned long ignored) | |||
1961 | some legacy boards. | 1687 | some legacy boards. |
1962 | ---------------------------------------------------------------- */ | 1688 | ---------------------------------------------------------------- */ |
1963 | 1689 | ||
1690 | spin_lock_irqsave(&epca_lock, flags); | ||
1691 | |||
1964 | assertmemoff(ch); | 1692 | assertmemoff(ch); |
1965 | 1693 | ||
1966 | globalwinon(ch); | 1694 | globalwinon(ch); |
@@ -1970,21 +1698,19 @@ static void epcapoll(unsigned long ignored) | |||
1970 | the transmit or receive queue. | 1698 | the transmit or receive queue. |
1971 | ------------------------------------------------------------------- */ | 1699 | ------------------------------------------------------------------- */ |
1972 | 1700 | ||
1973 | head = ch->mailbox->ein; | 1701 | head = readw(&ch->mailbox->ein); |
1974 | tail = ch->mailbox->eout; | 1702 | tail = readw(&ch->mailbox->eout); |
1975 | 1703 | ||
1976 | /* If head isn't equal to tail we have an event */ | 1704 | /* If head isn't equal to tail we have an event */ |
1977 | 1705 | ||
1978 | if (head != tail) | 1706 | if (head != tail) |
1979 | doevent(crd); | 1707 | doevent(crd); |
1980 | |||
1981 | memoff(ch); | 1708 | memoff(ch); |
1982 | 1709 | ||
1983 | } /* End for each card */ | 1710 | spin_unlock_irqrestore(&epca_lock, flags); |
1984 | 1711 | ||
1712 | } /* End for each card */ | ||
1985 | mod_timer(&epca_timer, jiffies + (HZ / 25)); | 1713 | mod_timer(&epca_timer, jiffies + (HZ / 25)); |
1986 | |||
1987 | restore_flags(flags); | ||
1988 | } /* End epcapoll */ | 1714 | } /* End epcapoll */ |
1989 | 1715 | ||
1990 | /* --------------------- Begin doevent ------------------------ */ | 1716 | /* --------------------- Begin doevent ------------------------ */ |
@@ -1992,53 +1718,42 @@ static void epcapoll(unsigned long ignored) | |||
1992 | static void doevent(int crd) | 1718 | static void doevent(int crd) |
1993 | { /* Begin doevent */ | 1719 | { /* Begin doevent */ |
1994 | 1720 | ||
1995 | volatile unchar *eventbuf; | 1721 | void *eventbuf; |
1996 | struct channel *ch, *chan0; | 1722 | struct channel *ch, *chan0; |
1997 | static struct tty_struct *tty; | 1723 | static struct tty_struct *tty; |
1998 | volatile struct board_info *bd; | 1724 | struct board_info *bd; |
1999 | volatile struct board_chan *bc; | 1725 | struct board_chan *bc; |
2000 | register volatile unsigned int tail, head; | 1726 | unsigned int tail, head; |
2001 | register int event, channel; | 1727 | int event, channel; |
2002 | register int mstat, lstat; | 1728 | int mstat, lstat; |
2003 | 1729 | ||
2004 | /* ------------------------------------------------------------------- | 1730 | /* ------------------------------------------------------------------- |
2005 | This subroutine is called by epcapoll when an event is detected | 1731 | This subroutine is called by epcapoll when an event is detected |
2006 | in the event queue. This routine responds to those events. | 1732 | in the event queue. This routine responds to those events. |
2007 | --------------------------------------------------------------------- */ | 1733 | --------------------------------------------------------------------- */ |
2008 | |||
2009 | bd = &boards[crd]; | 1734 | bd = &boards[crd]; |
2010 | 1735 | ||
2011 | chan0 = card_ptr[crd]; | 1736 | chan0 = card_ptr[crd]; |
2012 | epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range"); | 1737 | epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range"); |
2013 | |||
2014 | assertgwinon(chan0); | 1738 | assertgwinon(chan0); |
2015 | 1739 | while ((tail = readw(&chan0->mailbox->eout)) != (head = readw(&chan0->mailbox->ein))) | |
2016 | while ((tail = chan0->mailbox->eout) != (head = chan0->mailbox->ein)) | ||
2017 | { /* Begin while something in event queue */ | 1740 | { /* Begin while something in event queue */ |
2018 | |||
2019 | assertgwinon(chan0); | 1741 | assertgwinon(chan0); |
2020 | 1742 | eventbuf = bd->re_map_membase + tail + ISTART; | |
2021 | eventbuf = (volatile unchar *)bus_to_virt((ulong)(bd->re_map_membase + tail + ISTART)); | ||
2022 | |||
2023 | /* Get the channel the event occurred on */ | 1743 | /* Get the channel the event occurred on */ |
2024 | channel = eventbuf[0]; | 1744 | channel = readb(eventbuf); |
2025 | |||
2026 | /* Get the actual event code that occurred */ | 1745 | /* Get the actual event code that occurred */ |
2027 | event = eventbuf[1]; | 1746 | event = readb(eventbuf + 1); |
2028 | |||
2029 | /* ---------------------------------------------------------------- | 1747 | /* ---------------------------------------------------------------- |
2030 | The two assignments below get the current modem status (mstat) | 1748 | The two assignments below get the current modem status (mstat) |
2031 | and the previous modem status (lstat). These are useful becuase | 1749 | and the previous modem status (lstat). These are useful becuase |
2032 | an event could signal a change in modem signals itself. | 1750 | an event could signal a change in modem signals itself. |
2033 | ------------------------------------------------------------------- */ | 1751 | ------------------------------------------------------------------- */ |
2034 | 1752 | mstat = readb(eventbuf + 2); | |
2035 | mstat = eventbuf[2]; | 1753 | lstat = readb(eventbuf + 3); |
2036 | lstat = eventbuf[3]; | ||
2037 | 1754 | ||
2038 | ch = chan0 + channel; | 1755 | ch = chan0 + channel; |
2039 | 1756 | if ((unsigned)channel >= bd->numports || !ch) { | |
2040 | if ((unsigned)channel >= bd->numports || !ch) | ||
2041 | { | ||
2042 | if (channel >= bd->numports) | 1757 | if (channel >= bd->numports) |
2043 | ch = chan0; | 1758 | ch = chan0; |
2044 | bc = ch->brdchan; | 1759 | bc = ch->brdchan; |
@@ -2048,97 +1763,53 @@ static void doevent(int crd) | |||
2048 | if ((bc = ch->brdchan) == NULL) | 1763 | if ((bc = ch->brdchan) == NULL) |
2049 | goto next; | 1764 | goto next; |
2050 | 1765 | ||
2051 | if (event & DATA_IND) | 1766 | if (event & DATA_IND) { /* Begin DATA_IND */ |
2052 | { /* Begin DATA_IND */ | ||
2053 | |||
2054 | receive_data(ch); | 1767 | receive_data(ch); |
2055 | assertgwinon(ch); | 1768 | assertgwinon(ch); |
2056 | |||
2057 | } /* End DATA_IND */ | 1769 | } /* End DATA_IND */ |
2058 | /* else *//* Fix for DCD transition missed bug */ | 1770 | /* else *//* Fix for DCD transition missed bug */ |
2059 | if (event & MODEMCHG_IND) | 1771 | if (event & MODEMCHG_IND) { /* Begin MODEMCHG_IND */ |
2060 | { /* Begin MODEMCHG_IND */ | ||
2061 | |||
2062 | /* A modem signal change has been indicated */ | 1772 | /* A modem signal change has been indicated */ |
2063 | |||
2064 | ch->imodem = mstat; | 1773 | ch->imodem = mstat; |
2065 | 1774 | if (ch->asyncflags & ASYNC_CHECK_CD) { | |
2066 | if (ch->asyncflags & ASYNC_CHECK_CD) | ||
2067 | { | ||
2068 | if (mstat & ch->dcd) /* We are now receiving dcd */ | 1775 | if (mstat & ch->dcd) /* We are now receiving dcd */ |
2069 | wake_up_interruptible(&ch->open_wait); | 1776 | wake_up_interruptible(&ch->open_wait); |
2070 | else | 1777 | else |
2071 | pc_sched_event(ch, EPCA_EVENT_HANGUP); /* No dcd; hangup */ | 1778 | pc_sched_event(ch, EPCA_EVENT_HANGUP); /* No dcd; hangup */ |
2072 | } | 1779 | } |
2073 | |||
2074 | } /* End MODEMCHG_IND */ | 1780 | } /* End MODEMCHG_IND */ |
2075 | |||
2076 | tty = ch->tty; | 1781 | tty = ch->tty; |
2077 | if (tty) | 1782 | if (tty) { /* Begin if valid tty */ |
2078 | { /* Begin if valid tty */ | 1783 | if (event & BREAK_IND) { /* Begin if BREAK_IND */ |
2079 | |||
2080 | if (event & BREAK_IND) | ||
2081 | { /* Begin if BREAK_IND */ | ||
2082 | |||
2083 | /* A break has been indicated */ | 1784 | /* A break has been indicated */ |
2084 | |||
2085 | tty->flip.count++; | 1785 | tty->flip.count++; |
2086 | *tty->flip.flag_buf_ptr++ = TTY_BREAK; | 1786 | *tty->flip.flag_buf_ptr++ = TTY_BREAK; |
2087 | |||
2088 | *tty->flip.char_buf_ptr++ = 0; | 1787 | *tty->flip.char_buf_ptr++ = 0; |
2089 | |||
2090 | tty_schedule_flip(tty); | 1788 | tty_schedule_flip(tty); |
2091 | 1789 | } else if (event & LOWTX_IND) { /* Begin LOWTX_IND */ | |
2092 | } /* End if BREAK_IND */ | ||
2093 | else | ||
2094 | if (event & LOWTX_IND) | ||
2095 | { /* Begin LOWTX_IND */ | ||
2096 | |||
2097 | if (ch->statusflags & LOWWAIT) | 1790 | if (ch->statusflags & LOWWAIT) |
2098 | { /* Begin if LOWWAIT */ | 1791 | { /* Begin if LOWWAIT */ |
2099 | |||
2100 | ch->statusflags &= ~LOWWAIT; | 1792 | ch->statusflags &= ~LOWWAIT; |
2101 | tty_wakeup(tty); | 1793 | tty_wakeup(tty); |
2102 | wake_up_interruptible(&tty->write_wait); | 1794 | wake_up_interruptible(&tty->write_wait); |
2103 | |||
2104 | } /* End if LOWWAIT */ | 1795 | } /* End if LOWWAIT */ |
2105 | 1796 | } else if (event & EMPTYTX_IND) { /* Begin EMPTYTX_IND */ | |
2106 | } /* End LOWTX_IND */ | ||
2107 | else | ||
2108 | if (event & EMPTYTX_IND) | ||
2109 | { /* Begin EMPTYTX_IND */ | ||
2110 | |||
2111 | /* This event is generated by setup_empty_event */ | 1797 | /* This event is generated by setup_empty_event */ |
2112 | |||
2113 | ch->statusflags &= ~TXBUSY; | 1798 | ch->statusflags &= ~TXBUSY; |
2114 | if (ch->statusflags & EMPTYWAIT) | 1799 | if (ch->statusflags & EMPTYWAIT) { /* Begin if EMPTYWAIT */ |
2115 | { /* Begin if EMPTYWAIT */ | ||
2116 | |||
2117 | ch->statusflags &= ~EMPTYWAIT; | 1800 | ch->statusflags &= ~EMPTYWAIT; |
2118 | tty_wakeup(tty); | 1801 | tty_wakeup(tty); |
2119 | |||
2120 | wake_up_interruptible(&tty->write_wait); | 1802 | wake_up_interruptible(&tty->write_wait); |
2121 | |||
2122 | } /* End if EMPTYWAIT */ | 1803 | } /* End if EMPTYWAIT */ |
2123 | |||
2124 | } /* End EMPTYTX_IND */ | 1804 | } /* End EMPTYTX_IND */ |
2125 | |||
2126 | } /* End if valid tty */ | 1805 | } /* End if valid tty */ |
2127 | |||
2128 | |||
2129 | next: | 1806 | next: |
2130 | globalwinon(ch); | 1807 | globalwinon(ch); |
2131 | 1808 | BUG_ON(!bc); | |
2132 | if (!bc) | 1809 | writew(1, &bc->idata); |
2133 | printk(KERN_ERR "<Error> - bc == NULL in doevent!\n"); | 1810 | writew((tail + 4) & (IMAX - ISTART - 4), &chan0->mailbox->eout); |
2134 | else | ||
2135 | bc->idata = 1; | ||
2136 | |||
2137 | chan0->mailbox->eout = (tail + 4) & (IMAX - ISTART - 4); | ||
2138 | globalwinon(chan0); | 1811 | globalwinon(chan0); |
2139 | |||
2140 | } /* End while something in event queue */ | 1812 | } /* End while something in event queue */ |
2141 | |||
2142 | } /* End doevent */ | 1813 | } /* End doevent */ |
2143 | 1814 | ||
2144 | /* --------------------- Begin fepcmd ------------------------ */ | 1815 | /* --------------------- Begin fepcmd ------------------------ */ |
@@ -2146,7 +1817,6 @@ static void doevent(int crd) | |||
2146 | static void fepcmd(struct channel *ch, int cmd, int word_or_byte, | 1817 | static void fepcmd(struct channel *ch, int cmd, int word_or_byte, |
2147 | int byte2, int ncmds, int bytecmd) | 1818 | int byte2, int ncmds, int bytecmd) |
2148 | { /* Begin fepcmd */ | 1819 | { /* Begin fepcmd */ |
2149 | |||
2150 | unchar *memaddr; | 1820 | unchar *memaddr; |
2151 | unsigned int head, cmdTail, cmdStart, cmdMax; | 1821 | unsigned int head, cmdTail, cmdStart, cmdMax; |
2152 | long count; | 1822 | long count; |
@@ -2155,93 +1825,57 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte, | |||
2155 | /* This is the routine in which commands may be passed to the card. */ | 1825 | /* This is the routine in which commands may be passed to the card. */ |
2156 | 1826 | ||
2157 | if (ch->board->status == DISABLED) | 1827 | if (ch->board->status == DISABLED) |
2158 | { | ||
2159 | return; | 1828 | return; |
2160 | } | ||
2161 | |||
2162 | assertgwinon(ch); | 1829 | assertgwinon(ch); |
2163 | |||
2164 | /* Remember head (As well as max) is just an offset not a base addr */ | 1830 | /* Remember head (As well as max) is just an offset not a base addr */ |
2165 | head = ch->mailbox->cin; | 1831 | head = readw(&ch->mailbox->cin); |
2166 | |||
2167 | /* cmdStart is a base address */ | 1832 | /* cmdStart is a base address */ |
2168 | cmdStart = ch->mailbox->cstart; | 1833 | cmdStart = readw(&ch->mailbox->cstart); |
2169 | |||
2170 | /* ------------------------------------------------------------------ | 1834 | /* ------------------------------------------------------------------ |
2171 | We do the addition below because we do not want a max pointer | 1835 | We do the addition below because we do not want a max pointer |
2172 | relative to cmdStart. We want a max pointer that points at the | 1836 | relative to cmdStart. We want a max pointer that points at the |
2173 | physical end of the command queue. | 1837 | physical end of the command queue. |
2174 | -------------------------------------------------------------------- */ | 1838 | -------------------------------------------------------------------- */ |
2175 | 1839 | cmdMax = (cmdStart + 4 + readw(&ch->mailbox->cmax)); | |
2176 | cmdMax = (cmdStart + 4 + (ch->mailbox->cmax)); | ||
2177 | |||
2178 | memaddr = ch->board->re_map_membase; | 1840 | memaddr = ch->board->re_map_membase; |
2179 | 1841 | ||
2180 | /* | 1842 | if (head >= (cmdMax - cmdStart) || (head & 03)) { |
2181 | The below command is necessary because newer kernels (2.1.x and | 1843 | printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__, cmd, head); |
2182 | up) do not have a 1:1 virtual to physical mapping. The below | 1844 | printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__, cmdMax, cmdStart); |
2183 | call adjust for that. | ||
2184 | */ | ||
2185 | |||
2186 | memaddr = (unsigned char *)bus_to_virt((unsigned long)memaddr); | ||
2187 | |||
2188 | if (head >= (cmdMax - cmdStart) || (head & 03)) | ||
2189 | { | ||
2190 | printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__, | ||
2191 | cmd, head); | ||
2192 | printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__, | ||
2193 | cmdMax, cmdStart); | ||
2194 | return; | 1845 | return; |
2195 | } | 1846 | } |
2196 | 1847 | if (bytecmd) { | |
2197 | if (bytecmd) | 1848 | writeb(cmd, memaddr + head + cmdStart + 0); |
2198 | { | 1849 | writeb(ch->channelnum, memaddr + head + cmdStart + 1); |
2199 | *(volatile unchar *)(memaddr + head + cmdStart + 0) = (unchar)cmd; | ||
2200 | |||
2201 | *(volatile unchar *)(memaddr + head + cmdStart + 1) = (unchar)ch->channelnum; | ||
2202 | /* Below word_or_byte is bits to set */ | 1850 | /* Below word_or_byte is bits to set */ |
2203 | *(volatile unchar *)(memaddr + head + cmdStart + 2) = (unchar)word_or_byte; | 1851 | writeb(word_or_byte, memaddr + head + cmdStart + 2); |
2204 | /* Below byte2 is bits to reset */ | 1852 | /* Below byte2 is bits to reset */ |
2205 | *(volatile unchar *)(memaddr + head + cmdStart + 3) = (unchar)byte2; | 1853 | writeb(byte2, memaddr + head + cmdStart + 3); |
2206 | 1854 | } else { | |
2207 | } | 1855 | writeb(cmd, memaddr + head + cmdStart + 0); |
2208 | else | 1856 | writeb(ch->channelnum, memaddr + head + cmdStart + 1); |
2209 | { | 1857 | writeb(word_or_byte, memaddr + head + cmdStart + 2); |
2210 | *(volatile unchar *)(memaddr + head + cmdStart + 0) = (unchar)cmd; | ||
2211 | *(volatile unchar *)(memaddr + head + cmdStart + 1) = (unchar)ch->channelnum; | ||
2212 | *(volatile ushort*)(memaddr + head + cmdStart + 2) = (ushort)word_or_byte; | ||
2213 | } | 1858 | } |
2214 | |||
2215 | head = (head + 4) & (cmdMax - cmdStart - 4); | 1859 | head = (head + 4) & (cmdMax - cmdStart - 4); |
2216 | ch->mailbox->cin = head; | 1860 | writew(head, &ch->mailbox->cin); |
2217 | |||
2218 | count = FEPTIMEOUT; | 1861 | count = FEPTIMEOUT; |
2219 | 1862 | ||
2220 | for (;;) | 1863 | for (;;) { /* Begin forever loop */ |
2221 | { /* Begin forever loop */ | ||
2222 | |||
2223 | count--; | 1864 | count--; |
2224 | if (count == 0) | 1865 | if (count == 0) { |
2225 | { | ||
2226 | printk(KERN_ERR "<Error> - Fep not responding in fepcmd()\n"); | 1866 | printk(KERN_ERR "<Error> - Fep not responding in fepcmd()\n"); |
2227 | return; | 1867 | return; |
2228 | } | 1868 | } |
2229 | 1869 | head = readw(&ch->mailbox->cin); | |
2230 | head = ch->mailbox->cin; | 1870 | cmdTail = readw(&ch->mailbox->cout); |
2231 | cmdTail = ch->mailbox->cout; | ||
2232 | |||
2233 | n = (head - cmdTail) & (cmdMax - cmdStart - 4); | 1871 | n = (head - cmdTail) & (cmdMax - cmdStart - 4); |
2234 | |||
2235 | /* ---------------------------------------------------------- | 1872 | /* ---------------------------------------------------------- |
2236 | Basically this will break when the FEP acknowledges the | 1873 | Basically this will break when the FEP acknowledges the |
2237 | command by incrementing cmdTail (Making it equal to head). | 1874 | command by incrementing cmdTail (Making it equal to head). |
2238 | ------------------------------------------------------------- */ | 1875 | ------------------------------------------------------------- */ |
2239 | |||
2240 | if (n <= ncmds * (sizeof(short) * 4)) | 1876 | if (n <= ncmds * (sizeof(short) * 4)) |
2241 | break; /* Well nearly forever :-) */ | 1877 | break; /* Well nearly forever :-) */ |
2242 | |||
2243 | } /* End forever loop */ | 1878 | } /* End forever loop */ |
2244 | |||
2245 | } /* End fepcmd */ | 1879 | } /* End fepcmd */ |
2246 | 1880 | ||
2247 | /* --------------------------------------------------------------------- | 1881 | /* --------------------------------------------------------------------- |
@@ -2255,11 +1889,9 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte, | |||
2255 | 1889 | ||
2256 | static unsigned termios2digi_h(struct channel *ch, unsigned cflag) | 1890 | static unsigned termios2digi_h(struct channel *ch, unsigned cflag) |
2257 | { /* Begin termios2digi_h */ | 1891 | { /* Begin termios2digi_h */ |
2258 | |||
2259 | unsigned res = 0; | 1892 | unsigned res = 0; |
2260 | 1893 | ||
2261 | if (cflag & CRTSCTS) | 1894 | if (cflag & CRTSCTS) { |
2262 | { | ||
2263 | ch->digiext.digi_flags |= (RTSPACE | CTSPACE); | 1895 | ch->digiext.digi_flags |= (RTSPACE | CTSPACE); |
2264 | res |= ((ch->m_cts) | (ch->m_rts)); | 1896 | res |= ((ch->m_cts) | (ch->m_rts)); |
2265 | } | 1897 | } |
@@ -2295,7 +1927,6 @@ static unsigned termios2digi_i(struct channel *ch, unsigned iflag) | |||
2295 | 1927 | ||
2296 | unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | | 1928 | unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | |
2297 | INPCK | ISTRIP|IXON|IXANY|IXOFF); | 1929 | INPCK | ISTRIP|IXON|IXANY|IXOFF); |
2298 | |||
2299 | if (ch->digiext.digi_flags & DIGI_AIXON) | 1930 | if (ch->digiext.digi_flags & DIGI_AIXON) |
2300 | res |= IAIXON; | 1931 | res |= IAIXON; |
2301 | return res; | 1932 | return res; |
@@ -2308,28 +1939,15 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag) | |||
2308 | { /* Begin termios2digi_c */ | 1939 | { /* Begin termios2digi_c */ |
2309 | 1940 | ||
2310 | unsigned res = 0; | 1941 | unsigned res = 0; |
2311 | 1942 | if (cflag & CBAUDEX) { /* Begin detected CBAUDEX */ | |
2312 | #ifdef SPEED_HACK | ||
2313 | /* CL: HACK to force 115200 at 38400 and 57600 at 19200 Baud */ | ||
2314 | if ((cflag & CBAUD)== B38400) cflag=cflag - B38400 + B115200; | ||
2315 | if ((cflag & CBAUD)== B19200) cflag=cflag - B19200 + B57600; | ||
2316 | #endif /* SPEED_HACK */ | ||
2317 | |||
2318 | if (cflag & CBAUDEX) | ||
2319 | { /* Begin detected CBAUDEX */ | ||
2320 | |||
2321 | ch->digiext.digi_flags |= DIGI_FAST; | 1943 | ch->digiext.digi_flags |= DIGI_FAST; |
2322 | |||
2323 | /* ------------------------------------------------------------- | 1944 | /* ------------------------------------------------------------- |
2324 | HUPCL bit is used by FEP to indicate fast baud | 1945 | HUPCL bit is used by FEP to indicate fast baud |
2325 | table is to be used. | 1946 | table is to be used. |
2326 | ----------------------------------------------------------------- */ | 1947 | ----------------------------------------------------------------- */ |
2327 | |||
2328 | res |= FEP_HUPCL; | 1948 | res |= FEP_HUPCL; |
2329 | |||
2330 | } /* End detected CBAUDEX */ | 1949 | } /* End detected CBAUDEX */ |
2331 | else ch->digiext.digi_flags &= ~DIGI_FAST; | 1950 | else ch->digiext.digi_flags &= ~DIGI_FAST; |
2332 | |||
2333 | /* ------------------------------------------------------------------- | 1951 | /* ------------------------------------------------------------------- |
2334 | CBAUD has bit position 0x1000 set these days to indicate Linux | 1952 | CBAUD has bit position 0x1000 set these days to indicate Linux |
2335 | baud rate remap. Digi hardware can't handle the bit assignment. | 1953 | baud rate remap. Digi hardware can't handle the bit assignment. |
@@ -2337,7 +1955,6 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag) | |||
2337 | bit out. | 1955 | bit out. |
2338 | ---------------------------------------------------------------------- */ | 1956 | ---------------------------------------------------------------------- */ |
2339 | res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE); | 1957 | res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE); |
2340 | |||
2341 | /* ------------------------------------------------------------- | 1958 | /* ------------------------------------------------------------- |
2342 | This gets a little confusing. The Digi cards have their own | 1959 | This gets a little confusing. The Digi cards have their own |
2343 | representation of c_cflags controling baud rate. For the most | 1960 | representation of c_cflags controling baud rate. For the most |
@@ -2357,10 +1974,8 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag) | |||
2357 | should be checked for a screened out prior to termios2digi_c | 1974 | should be checked for a screened out prior to termios2digi_c |
2358 | returning. Since CLOCAL isn't used by the board this can be | 1975 | returning. Since CLOCAL isn't used by the board this can be |
2359 | ignored as long as the returned value is used only by Digi hardware. | 1976 | ignored as long as the returned value is used only by Digi hardware. |
2360 | ----------------------------------------------------------------- */ | 1977 | ----------------------------------------------------------------- */ |
2361 | 1978 | if (cflag & CBAUDEX) { | |
2362 | if (cflag & CBAUDEX) | ||
2363 | { | ||
2364 | /* ------------------------------------------------------------- | 1979 | /* ------------------------------------------------------------- |
2365 | The below code is trying to guarantee that only baud rates | 1980 | The below code is trying to guarantee that only baud rates |
2366 | 115200 and 230400 are remapped. We use exclusive or because | 1981 | 115200 and 230400 are remapped. We use exclusive or because |
@@ -2371,138 +1986,96 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag) | |||
2371 | 1986 | ||
2372 | if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) || | 1987 | if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) || |
2373 | (!((cflag & 0x7) ^ (B230400 & ~CBAUDEX)))) | 1988 | (!((cflag & 0x7) ^ (B230400 & ~CBAUDEX)))) |
2374 | { | ||
2375 | res += 1; | 1989 | res += 1; |
2376 | } | ||
2377 | } | 1990 | } |
2378 | |||
2379 | return res; | 1991 | return res; |
2380 | 1992 | ||
2381 | } /* End termios2digi_c */ | 1993 | } /* End termios2digi_c */ |
2382 | 1994 | ||
2383 | /* --------------------- Begin epcaparam ----------------------- */ | 1995 | /* --------------------- Begin epcaparam ----------------------- */ |
2384 | 1996 | ||
1997 | /* Caller must hold the locks */ | ||
2385 | static void epcaparam(struct tty_struct *tty, struct channel *ch) | 1998 | static void epcaparam(struct tty_struct *tty, struct channel *ch) |
2386 | { /* Begin epcaparam */ | 1999 | { /* Begin epcaparam */ |
2387 | 2000 | ||
2388 | unsigned int cmdHead; | 2001 | unsigned int cmdHead; |
2389 | struct termios *ts; | 2002 | struct termios *ts; |
2390 | volatile struct board_chan *bc; | 2003 | struct board_chan *bc; |
2391 | unsigned mval, hflow, cflag, iflag; | 2004 | unsigned mval, hflow, cflag, iflag; |
2392 | 2005 | ||
2393 | bc = ch->brdchan; | 2006 | bc = ch->brdchan; |
2394 | epcaassert(bc !=0, "bc out of range"); | 2007 | epcaassert(bc !=0, "bc out of range"); |
2395 | 2008 | ||
2396 | assertgwinon(ch); | 2009 | assertgwinon(ch); |
2397 | |||
2398 | ts = tty->termios; | 2010 | ts = tty->termios; |
2399 | 2011 | if ((ts->c_cflag & CBAUD) == 0) { /* Begin CBAUD detected */ | |
2400 | if ((ts->c_cflag & CBAUD) == 0) | 2012 | cmdHead = readw(&bc->rin); |
2401 | { /* Begin CBAUD detected */ | ||
2402 | |||
2403 | cmdHead = bc->rin; | ||
2404 | bc->rout = cmdHead; | 2013 | bc->rout = cmdHead; |
2405 | cmdHead = bc->tin; | 2014 | cmdHead = readw(&bc->tin); |
2406 | |||
2407 | /* Changing baud in mid-stream transmission can be wonderful */ | 2015 | /* Changing baud in mid-stream transmission can be wonderful */ |
2408 | /* --------------------------------------------------------------- | 2016 | /* --------------------------------------------------------------- |
2409 | Flush current transmit buffer by setting cmdTail pointer (tout) | 2017 | Flush current transmit buffer by setting cmdTail pointer (tout) |
2410 | to cmdHead pointer (tin). Hopefully the transmit buffer is empty. | 2018 | to cmdHead pointer (tin). Hopefully the transmit buffer is empty. |
2411 | ----------------------------------------------------------------- */ | 2019 | ----------------------------------------------------------------- */ |
2412 | |||
2413 | fepcmd(ch, STOUT, (unsigned) cmdHead, 0, 0, 0); | 2020 | fepcmd(ch, STOUT, (unsigned) cmdHead, 0, 0, 0); |
2414 | mval = 0; | 2021 | mval = 0; |
2415 | 2022 | } else { /* Begin CBAUD not detected */ | |
2416 | } /* End CBAUD detected */ | ||
2417 | else | ||
2418 | { /* Begin CBAUD not detected */ | ||
2419 | |||
2420 | /* ------------------------------------------------------------------- | 2023 | /* ------------------------------------------------------------------- |
2421 | c_cflags have changed but that change had nothing to do with BAUD. | 2024 | c_cflags have changed but that change had nothing to do with BAUD. |
2422 | Propagate the change to the card. | 2025 | Propagate the change to the card. |
2423 | ---------------------------------------------------------------------- */ | 2026 | ---------------------------------------------------------------------- */ |
2424 | |||
2425 | cflag = termios2digi_c(ch, ts->c_cflag); | 2027 | cflag = termios2digi_c(ch, ts->c_cflag); |
2426 | 2028 | if (cflag != ch->fepcflag) { | |
2427 | if (cflag != ch->fepcflag) | ||
2428 | { | ||
2429 | ch->fepcflag = cflag; | 2029 | ch->fepcflag = cflag; |
2430 | /* Set baud rate, char size, stop bits, parity */ | 2030 | /* Set baud rate, char size, stop bits, parity */ |
2431 | fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0); | 2031 | fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0); |
2432 | } | 2032 | } |
2433 | |||
2434 | |||
2435 | /* ---------------------------------------------------------------- | 2033 | /* ---------------------------------------------------------------- |
2436 | If the user has not forced CLOCAL and if the device is not a | 2034 | If the user has not forced CLOCAL and if the device is not a |
2437 | CALLOUT device (Which is always CLOCAL) we set flags such that | 2035 | CALLOUT device (Which is always CLOCAL) we set flags such that |
2438 | the driver will wait on carrier detect. | 2036 | the driver will wait on carrier detect. |
2439 | ------------------------------------------------------------------- */ | 2037 | ------------------------------------------------------------------- */ |
2440 | |||
2441 | if (ts->c_cflag & CLOCAL) | 2038 | if (ts->c_cflag & CLOCAL) |
2442 | { /* Begin it is a cud device or a ttyD device with CLOCAL on */ | ||
2443 | ch->asyncflags &= ~ASYNC_CHECK_CD; | 2039 | ch->asyncflags &= ~ASYNC_CHECK_CD; |
2444 | } /* End it is a cud device or a ttyD device with CLOCAL on */ | ||
2445 | else | 2040 | else |
2446 | { /* Begin it is a ttyD device */ | ||
2447 | ch->asyncflags |= ASYNC_CHECK_CD; | 2041 | ch->asyncflags |= ASYNC_CHECK_CD; |
2448 | } /* End it is a ttyD device */ | ||
2449 | |||
2450 | mval = ch->m_dtr | ch->m_rts; | 2042 | mval = ch->m_dtr | ch->m_rts; |
2451 | |||
2452 | } /* End CBAUD not detected */ | 2043 | } /* End CBAUD not detected */ |
2453 | |||
2454 | iflag = termios2digi_i(ch, ts->c_iflag); | 2044 | iflag = termios2digi_i(ch, ts->c_iflag); |
2455 | |||
2456 | /* Check input mode flags */ | 2045 | /* Check input mode flags */ |
2457 | 2046 | if (iflag != ch->fepiflag) { | |
2458 | if (iflag != ch->fepiflag) | ||
2459 | { | ||
2460 | ch->fepiflag = iflag; | 2047 | ch->fepiflag = iflag; |
2461 | |||
2462 | /* --------------------------------------------------------------- | 2048 | /* --------------------------------------------------------------- |
2463 | Command sets channels iflag structure on the board. Such things | 2049 | Command sets channels iflag structure on the board. Such things |
2464 | as input soft flow control, handling of parity errors, and | 2050 | as input soft flow control, handling of parity errors, and |
2465 | break handling are all set here. | 2051 | break handling are all set here. |
2466 | ------------------------------------------------------------------- */ | 2052 | ------------------------------------------------------------------- */ |
2467 | |||
2468 | /* break handling, parity handling, input stripping, flow control chars */ | 2053 | /* break handling, parity handling, input stripping, flow control chars */ |
2469 | fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0); | 2054 | fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0); |
2470 | } | 2055 | } |
2471 | |||
2472 | /* --------------------------------------------------------------- | 2056 | /* --------------------------------------------------------------- |
2473 | Set the board mint value for this channel. This will cause hardware | 2057 | Set the board mint value for this channel. This will cause hardware |
2474 | events to be generated each time the DCD signal (Described in mint) | 2058 | events to be generated each time the DCD signal (Described in mint) |
2475 | changes. | 2059 | changes. |
2476 | ------------------------------------------------------------------- */ | 2060 | ------------------------------------------------------------------- */ |
2477 | bc->mint = ch->dcd; | 2061 | writeb(ch->dcd, &bc->mint); |
2478 | |||
2479 | if ((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD)) | 2062 | if ((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD)) |
2480 | if (ch->digiext.digi_flags & DIGI_FORCEDCD) | 2063 | if (ch->digiext.digi_flags & DIGI_FORCEDCD) |
2481 | bc->mint = 0; | 2064 | writeb(0, &bc->mint); |
2482 | 2065 | ch->imodem = readb(&bc->mstat); | |
2483 | ch->imodem = bc->mstat; | ||
2484 | |||
2485 | hflow = termios2digi_h(ch, ts->c_cflag); | 2066 | hflow = termios2digi_h(ch, ts->c_cflag); |
2486 | 2067 | if (hflow != ch->hflow) { | |
2487 | if (hflow != ch->hflow) | ||
2488 | { | ||
2489 | ch->hflow = hflow; | 2068 | ch->hflow = hflow; |
2490 | |||
2491 | /* -------------------------------------------------------------- | 2069 | /* -------------------------------------------------------------- |
2492 | Hard flow control has been selected but the board is not | 2070 | Hard flow control has been selected but the board is not |
2493 | using it. Activate hard flow control now. | 2071 | using it. Activate hard flow control now. |
2494 | ----------------------------------------------------------------- */ | 2072 | ----------------------------------------------------------------- */ |
2495 | |||
2496 | fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1); | 2073 | fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1); |
2497 | } | 2074 | } |
2498 | |||
2499 | |||
2500 | mval ^= ch->modemfake & (mval ^ ch->modem); | 2075 | mval ^= ch->modemfake & (mval ^ ch->modem); |
2501 | 2076 | ||
2502 | if (ch->omodem ^ mval) | 2077 | if (ch->omodem ^ mval) { |
2503 | { | ||
2504 | ch->omodem = mval; | 2078 | ch->omodem = mval; |
2505 | |||
2506 | /* -------------------------------------------------------------- | 2079 | /* -------------------------------------------------------------- |
2507 | The below command sets the DTR and RTS mstat structure. If | 2080 | The below command sets the DTR and RTS mstat structure. If |
2508 | hard flow control is NOT active these changes will drive the | 2081 | hard flow control is NOT active these changes will drive the |
@@ -2514,87 +2087,65 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) | |||
2514 | /* First reset DTR & RTS; then set them */ | 2087 | /* First reset DTR & RTS; then set them */ |
2515 | fepcmd(ch, SETMODEM, 0, ((ch->m_dtr)|(ch->m_rts)), 0, 1); | 2088 | fepcmd(ch, SETMODEM, 0, ((ch->m_dtr)|(ch->m_rts)), 0, 1); |
2516 | fepcmd(ch, SETMODEM, mval, 0, 0, 1); | 2089 | fepcmd(ch, SETMODEM, mval, 0, 0, 1); |
2517 | |||
2518 | } | 2090 | } |
2519 | 2091 | if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc) { | |
2520 | if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc) | ||
2521 | { | ||
2522 | ch->fepstartc = ch->startc; | 2092 | ch->fepstartc = ch->startc; |
2523 | ch->fepstopc = ch->stopc; | 2093 | ch->fepstopc = ch->stopc; |
2524 | |||
2525 | /* ------------------------------------------------------------ | 2094 | /* ------------------------------------------------------------ |
2526 | The XON / XOFF characters have changed; propagate these | 2095 | The XON / XOFF characters have changed; propagate these |
2527 | changes to the card. | 2096 | changes to the card. |
2528 | --------------------------------------------------------------- */ | 2097 | --------------------------------------------------------------- */ |
2529 | |||
2530 | fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1); | 2098 | fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1); |
2531 | } | 2099 | } |
2532 | 2100 | if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca) { | |
2533 | if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca) | ||
2534 | { | ||
2535 | ch->fepstartca = ch->startca; | 2101 | ch->fepstartca = ch->startca; |
2536 | ch->fepstopca = ch->stopca; | 2102 | ch->fepstopca = ch->stopca; |
2537 | |||
2538 | /* --------------------------------------------------------------- | 2103 | /* --------------------------------------------------------------- |
2539 | Similar to the above, this time the auxilarly XON / XOFF | 2104 | Similar to the above, this time the auxilarly XON / XOFF |
2540 | characters have changed; propagate these changes to the card. | 2105 | characters have changed; propagate these changes to the card. |
2541 | ------------------------------------------------------------------ */ | 2106 | ------------------------------------------------------------------ */ |
2542 | |||
2543 | fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1); | 2107 | fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1); |
2544 | } | 2108 | } |
2545 | |||
2546 | } /* End epcaparam */ | 2109 | } /* End epcaparam */ |
2547 | 2110 | ||
2548 | /* --------------------- Begin receive_data ----------------------- */ | 2111 | /* --------------------- Begin receive_data ----------------------- */ |
2549 | 2112 | /* Caller holds lock */ | |
2550 | static void receive_data(struct channel *ch) | 2113 | static void receive_data(struct channel *ch) |
2551 | { /* Begin receive_data */ | 2114 | { /* Begin receive_data */ |
2552 | 2115 | ||
2553 | unchar *rptr; | 2116 | unchar *rptr; |
2554 | struct termios *ts = NULL; | 2117 | struct termios *ts = NULL; |
2555 | struct tty_struct *tty; | 2118 | struct tty_struct *tty; |
2556 | volatile struct board_chan *bc; | 2119 | struct board_chan *bc; |
2557 | register int dataToRead, wrapgap, bytesAvailable; | 2120 | int dataToRead, wrapgap, bytesAvailable; |
2558 | register unsigned int tail, head; | 2121 | unsigned int tail, head; |
2559 | unsigned int wrapmask; | 2122 | unsigned int wrapmask; |
2560 | int rc; | 2123 | int rc; |
2561 | 2124 | ||
2562 | |||
2563 | /* --------------------------------------------------------------- | 2125 | /* --------------------------------------------------------------- |
2564 | This routine is called by doint when a receive data event | 2126 | This routine is called by doint when a receive data event |
2565 | has taken place. | 2127 | has taken place. |
2566 | ------------------------------------------------------------------- */ | 2128 | ------------------------------------------------------------------- */ |
2567 | 2129 | ||
2568 | globalwinon(ch); | 2130 | globalwinon(ch); |
2569 | |||
2570 | if (ch->statusflags & RXSTOPPED) | 2131 | if (ch->statusflags & RXSTOPPED) |
2571 | return; | 2132 | return; |
2572 | |||
2573 | tty = ch->tty; | 2133 | tty = ch->tty; |
2574 | if (tty) | 2134 | if (tty) |
2575 | ts = tty->termios; | 2135 | ts = tty->termios; |
2576 | |||
2577 | bc = ch->brdchan; | 2136 | bc = ch->brdchan; |
2578 | 2137 | BUG_ON(!bc); | |
2579 | if (!bc) | ||
2580 | { | ||
2581 | printk(KERN_ERR "<Error> - bc is NULL in receive_data!\n"); | ||
2582 | return; | ||
2583 | } | ||
2584 | |||
2585 | wrapmask = ch->rxbufsize - 1; | 2138 | wrapmask = ch->rxbufsize - 1; |
2586 | 2139 | ||
2587 | /* --------------------------------------------------------------------- | 2140 | /* --------------------------------------------------------------------- |
2588 | Get the head and tail pointers to the receiver queue. Wrap the | 2141 | Get the head and tail pointers to the receiver queue. Wrap the |
2589 | head pointer if it has reached the end of the buffer. | 2142 | head pointer if it has reached the end of the buffer. |
2590 | ------------------------------------------------------------------------ */ | 2143 | ------------------------------------------------------------------------ */ |
2591 | 2144 | head = readw(&bc->rin); | |
2592 | head = bc->rin; | ||
2593 | head &= wrapmask; | 2145 | head &= wrapmask; |
2594 | tail = bc->rout & wrapmask; | 2146 | tail = readw(&bc->rout) & wrapmask; |
2595 | 2147 | ||
2596 | bytesAvailable = (head - tail) & wrapmask; | 2148 | bytesAvailable = (head - tail) & wrapmask; |
2597 | |||
2598 | if (bytesAvailable == 0) | 2149 | if (bytesAvailable == 0) |
2599 | return; | 2150 | return; |
2600 | 2151 | ||
@@ -2602,8 +2153,7 @@ static void receive_data(struct channel *ch) | |||
2602 | If CREAD bit is off or device not open, set TX tail to head | 2153 | If CREAD bit is off or device not open, set TX tail to head |
2603 | --------------------------------------------------------------------- */ | 2154 | --------------------------------------------------------------------- */ |
2604 | 2155 | ||
2605 | if (!tty || !ts || !(ts->c_cflag & CREAD)) | 2156 | if (!tty || !ts || !(ts->c_cflag & CREAD)) { |
2606 | { | ||
2607 | bc->rout = head; | 2157 | bc->rout = head; |
2608 | return; | 2158 | return; |
2609 | } | 2159 | } |
@@ -2611,64 +2161,45 @@ static void receive_data(struct channel *ch) | |||
2611 | if (tty->flip.count == TTY_FLIPBUF_SIZE) | 2161 | if (tty->flip.count == TTY_FLIPBUF_SIZE) |
2612 | return; | 2162 | return; |
2613 | 2163 | ||
2614 | if (bc->orun) | 2164 | if (readb(&bc->orun)) { |
2615 | { | 2165 | writeb(0, &bc->orun); |
2616 | bc->orun = 0; | 2166 | printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",tty->name); |
2617 | printk(KERN_WARNING "overrun! DigiBoard device %s\n",tty->name); | ||
2618 | } | 2167 | } |
2619 | |||
2620 | rxwinon(ch); | 2168 | rxwinon(ch); |
2621 | rptr = tty->flip.char_buf_ptr; | 2169 | rptr = tty->flip.char_buf_ptr; |
2622 | rc = tty->flip.count; | 2170 | rc = tty->flip.count; |
2623 | 2171 | while (bytesAvailable > 0) { /* Begin while there is data on the card */ | |
2624 | while (bytesAvailable > 0) | ||
2625 | { /* Begin while there is data on the card */ | ||
2626 | |||
2627 | wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail; | 2172 | wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail; |
2628 | |||
2629 | /* --------------------------------------------------------------- | 2173 | /* --------------------------------------------------------------- |
2630 | Even if head has wrapped around only report the amount of | 2174 | Even if head has wrapped around only report the amount of |
2631 | data to be equal to the size - tail. Remember memcpy can't | 2175 | data to be equal to the size - tail. Remember memcpy can't |
2632 | automaticly wrap around the receive buffer. | 2176 | automaticly wrap around the receive buffer. |
2633 | ----------------------------------------------------------------- */ | 2177 | ----------------------------------------------------------------- */ |
2634 | |||
2635 | dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable; | 2178 | dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable; |
2636 | |||
2637 | /* -------------------------------------------------------------- | 2179 | /* -------------------------------------------------------------- |
2638 | Make sure we don't overflow the buffer | 2180 | Make sure we don't overflow the buffer |
2639 | ----------------------------------------------------------------- */ | 2181 | ----------------------------------------------------------------- */ |
2640 | |||
2641 | if ((rc + dataToRead) > TTY_FLIPBUF_SIZE) | 2182 | if ((rc + dataToRead) > TTY_FLIPBUF_SIZE) |
2642 | dataToRead = TTY_FLIPBUF_SIZE - rc; | 2183 | dataToRead = TTY_FLIPBUF_SIZE - rc; |
2643 | |||
2644 | if (dataToRead == 0) | 2184 | if (dataToRead == 0) |
2645 | break; | 2185 | break; |
2646 | |||
2647 | /* --------------------------------------------------------------- | 2186 | /* --------------------------------------------------------------- |
2648 | Move data read from our card into the line disciplines buffer | 2187 | Move data read from our card into the line disciplines buffer |
2649 | for translation if necessary. | 2188 | for translation if necessary. |
2650 | ------------------------------------------------------------------ */ | 2189 | ------------------------------------------------------------------ */ |
2651 | 2190 | memcpy_fromio(rptr, ch->rxptr + tail, dataToRead); | |
2652 | if ((memcpy(rptr, ch->rxptr + tail, dataToRead)) != rptr) | ||
2653 | printk(KERN_ERR "<Error> - receive_data : memcpy failed\n"); | ||
2654 | |||
2655 | rc += dataToRead; | 2191 | rc += dataToRead; |
2656 | rptr += dataToRead; | 2192 | rptr += dataToRead; |
2657 | tail = (tail + dataToRead) & wrapmask; | 2193 | tail = (tail + dataToRead) & wrapmask; |
2658 | bytesAvailable -= dataToRead; | 2194 | bytesAvailable -= dataToRead; |
2659 | |||
2660 | } /* End while there is data on the card */ | 2195 | } /* End while there is data on the card */ |
2661 | |||
2662 | |||
2663 | tty->flip.count = rc; | 2196 | tty->flip.count = rc; |
2664 | tty->flip.char_buf_ptr = rptr; | 2197 | tty->flip.char_buf_ptr = rptr; |
2665 | globalwinon(ch); | 2198 | globalwinon(ch); |
2666 | bc->rout = tail; | 2199 | writew(tail, &bc->rout); |
2667 | |||
2668 | /* Must be called with global data */ | 2200 | /* Must be called with global data */ |
2669 | tty_schedule_flip(ch->tty); | 2201 | tty_schedule_flip(ch->tty); |
2670 | return; | 2202 | return; |
2671 | |||
2672 | } /* End receive_data */ | 2203 | } /* End receive_data */ |
2673 | 2204 | ||
2674 | static int info_ioctl(struct tty_struct *tty, struct file * file, | 2205 | static int info_ioctl(struct tty_struct *tty, struct file * file, |
@@ -2676,17 +2207,15 @@ static int info_ioctl(struct tty_struct *tty, struct file * file, | |||
2676 | { | 2207 | { |
2677 | switch (cmd) | 2208 | switch (cmd) |
2678 | { /* Begin switch cmd */ | 2209 | { /* Begin switch cmd */ |
2679 | |||
2680 | case DIGI_GETINFO: | 2210 | case DIGI_GETINFO: |
2681 | { /* Begin case DIGI_GETINFO */ | 2211 | { /* Begin case DIGI_GETINFO */ |
2682 | |||
2683 | struct digi_info di ; | 2212 | struct digi_info di ; |
2684 | int brd; | 2213 | int brd; |
2685 | 2214 | ||
2686 | getUser(brd, (unsigned int __user *)arg); | 2215 | if(get_user(brd, (unsigned int __user *)arg)) |
2687 | 2216 | return -EFAULT; | |
2688 | if ((brd < 0) || (brd >= num_cards) || (num_cards == 0)) | 2217 | if (brd < 0 || brd >= num_cards || num_cards == 0) |
2689 | return (-ENODEV); | 2218 | return -ENODEV; |
2690 | 2219 | ||
2691 | memset(&di, 0, sizeof(di)); | 2220 | memset(&di, 0, sizeof(di)); |
2692 | 2221 | ||
@@ -2694,8 +2223,9 @@ static int info_ioctl(struct tty_struct *tty, struct file * file, | |||
2694 | di.status = boards[brd].status; | 2223 | di.status = boards[brd].status; |
2695 | di.type = boards[brd].type ; | 2224 | di.type = boards[brd].type ; |
2696 | di.numports = boards[brd].numports ; | 2225 | di.numports = boards[brd].numports ; |
2697 | di.port = boards[brd].port ; | 2226 | /* Legacy fixups - just move along nothing to see */ |
2698 | di.membase = boards[brd].membase ; | 2227 | di.port = (unsigned char *)boards[brd].port ; |
2228 | di.membase = (unsigned char *)boards[brd].membase ; | ||
2699 | 2229 | ||
2700 | if (copy_to_user((void __user *)arg, &di, sizeof (di))) | 2230 | if (copy_to_user((void __user *)arg, &di, sizeof (di))) |
2701 | return -EFAULT; | 2231 | return -EFAULT; |
@@ -2709,39 +2239,29 @@ static int info_ioctl(struct tty_struct *tty, struct file * file, | |||
2709 | int brd = arg & 0xff000000 >> 16 ; | 2239 | int brd = arg & 0xff000000 >> 16 ; |
2710 | unsigned char state = arg & 0xff ; | 2240 | unsigned char state = arg & 0xff ; |
2711 | 2241 | ||
2712 | if ((brd < 0) || (brd >= num_cards)) | 2242 | if (brd < 0 || brd >= num_cards) { |
2713 | { | 2243 | printk(KERN_ERR "epca: DIGI POLLER : brd not valid!\n"); |
2714 | printk(KERN_ERR "<Error> - DIGI POLLER : brd not valid!\n"); | ||
2715 | return (-ENODEV); | 2244 | return (-ENODEV); |
2716 | } | 2245 | } |
2717 | |||
2718 | digi_poller_inhibited = state ; | 2246 | digi_poller_inhibited = state ; |
2719 | break ; | 2247 | break ; |
2720 | |||
2721 | } /* End case DIGI_POLLER */ | 2248 | } /* End case DIGI_POLLER */ |
2722 | 2249 | ||
2723 | case DIGI_INIT: | 2250 | case DIGI_INIT: |
2724 | { /* Begin case DIGI_INIT */ | 2251 | { /* Begin case DIGI_INIT */ |
2725 | |||
2726 | /* ------------------------------------------------------------ | 2252 | /* ------------------------------------------------------------ |
2727 | This call is made by the apps to complete the initilization | 2253 | This call is made by the apps to complete the initilization |
2728 | of the board(s). This routine is responsible for setting | 2254 | of the board(s). This routine is responsible for setting |
2729 | the card to its initial state and setting the drivers control | 2255 | the card to its initial state and setting the drivers control |
2730 | fields to the sutianle settings for the card in question. | 2256 | fields to the sutianle settings for the card in question. |
2731 | ---------------------------------------------------------------- */ | 2257 | ---------------------------------------------------------------- */ |
2732 | |||
2733 | int crd ; | 2258 | int crd ; |
2734 | for (crd = 0; crd < num_cards; crd++) | 2259 | for (crd = 0; crd < num_cards; crd++) |
2735 | post_fep_init (crd); | 2260 | post_fep_init (crd); |
2736 | |||
2737 | break ; | 2261 | break ; |
2738 | |||
2739 | } /* End case DIGI_INIT */ | 2262 | } /* End case DIGI_INIT */ |
2740 | |||
2741 | |||
2742 | default: | 2263 | default: |
2743 | return -ENOIOCTLCMD; | 2264 | return -ENOTTY; |
2744 | |||
2745 | } /* End switch cmd */ | 2265 | } /* End switch cmd */ |
2746 | return (0) ; | 2266 | return (0) ; |
2747 | } | 2267 | } |
@@ -2750,43 +2270,33 @@ static int info_ioctl(struct tty_struct *tty, struct file * file, | |||
2750 | static int pc_tiocmget(struct tty_struct *tty, struct file *file) | 2270 | static int pc_tiocmget(struct tty_struct *tty, struct file *file) |
2751 | { | 2271 | { |
2752 | struct channel *ch = (struct channel *) tty->driver_data; | 2272 | struct channel *ch = (struct channel *) tty->driver_data; |
2753 | volatile struct board_chan *bc; | 2273 | struct board_chan *bc; |
2754 | unsigned int mstat, mflag = 0; | 2274 | unsigned int mstat, mflag = 0; |
2755 | unsigned long flags; | 2275 | unsigned long flags; |
2756 | 2276 | ||
2757 | if (ch) | 2277 | if (ch) |
2758 | bc = ch->brdchan; | 2278 | bc = ch->brdchan; |
2759 | else | 2279 | else |
2760 | { | 2280 | return -EINVAL; |
2761 | printk(KERN_ERR "<Error> - ch is NULL in pc_tiocmget!\n"); | ||
2762 | return(-EINVAL); | ||
2763 | } | ||
2764 | 2281 | ||
2765 | save_flags(flags); | 2282 | spin_lock_irqsave(&epca_lock, flags); |
2766 | cli(); | ||
2767 | globalwinon(ch); | 2283 | globalwinon(ch); |
2768 | mstat = bc->mstat; | 2284 | mstat = readb(&bc->mstat); |
2769 | memoff(ch); | 2285 | memoff(ch); |
2770 | restore_flags(flags); | 2286 | spin_unlock_irqrestore(&epca_lock, flags); |
2771 | 2287 | ||
2772 | if (mstat & ch->m_dtr) | 2288 | if (mstat & ch->m_dtr) |
2773 | mflag |= TIOCM_DTR; | 2289 | mflag |= TIOCM_DTR; |
2774 | |||
2775 | if (mstat & ch->m_rts) | 2290 | if (mstat & ch->m_rts) |
2776 | mflag |= TIOCM_RTS; | 2291 | mflag |= TIOCM_RTS; |
2777 | |||
2778 | if (mstat & ch->m_cts) | 2292 | if (mstat & ch->m_cts) |
2779 | mflag |= TIOCM_CTS; | 2293 | mflag |= TIOCM_CTS; |
2780 | |||
2781 | if (mstat & ch->dsr) | 2294 | if (mstat & ch->dsr) |
2782 | mflag |= TIOCM_DSR; | 2295 | mflag |= TIOCM_DSR; |
2783 | |||
2784 | if (mstat & ch->m_ri) | 2296 | if (mstat & ch->m_ri) |
2785 | mflag |= TIOCM_RI; | 2297 | mflag |= TIOCM_RI; |
2786 | |||
2787 | if (mstat & ch->dcd) | 2298 | if (mstat & ch->dcd) |
2788 | mflag |= TIOCM_CD; | 2299 | mflag |= TIOCM_CD; |
2789 | |||
2790 | return mflag; | 2300 | return mflag; |
2791 | } | 2301 | } |
2792 | 2302 | ||
@@ -2796,13 +2306,10 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file, | |||
2796 | struct channel *ch = (struct channel *) tty->driver_data; | 2306 | struct channel *ch = (struct channel *) tty->driver_data; |
2797 | unsigned long flags; | 2307 | unsigned long flags; |
2798 | 2308 | ||
2799 | if (!ch) { | 2309 | if (!ch) |
2800 | printk(KERN_ERR "<Error> - ch is NULL in pc_tiocmset!\n"); | 2310 | return -EINVAL; |
2801 | return(-EINVAL); | ||
2802 | } | ||
2803 | 2311 | ||
2804 | save_flags(flags); | 2312 | spin_lock_irqsave(&epca_lock, flags); |
2805 | cli(); | ||
2806 | /* | 2313 | /* |
2807 | * I think this modemfake stuff is broken. It doesn't | 2314 | * I think this modemfake stuff is broken. It doesn't |
2808 | * correctly reflect the behaviour desired by the TIOCM* | 2315 | * correctly reflect the behaviour desired by the TIOCM* |
@@ -2824,17 +2331,14 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file, | |||
2824 | ch->modemfake |= ch->m_dtr; | 2331 | ch->modemfake |= ch->m_dtr; |
2825 | ch->modem &= ~ch->m_dtr; | 2332 | ch->modem &= ~ch->m_dtr; |
2826 | } | 2333 | } |
2827 | |||
2828 | globalwinon(ch); | 2334 | globalwinon(ch); |
2829 | |||
2830 | /* -------------------------------------------------------------- | 2335 | /* -------------------------------------------------------------- |
2831 | The below routine generally sets up parity, baud, flow control | 2336 | The below routine generally sets up parity, baud, flow control |
2832 | issues, etc.... It effect both control flags and input flags. | 2337 | issues, etc.... It effect both control flags and input flags. |
2833 | ------------------------------------------------------------------ */ | 2338 | ------------------------------------------------------------------ */ |
2834 | |||
2835 | epcaparam(tty,ch); | 2339 | epcaparam(tty,ch); |
2836 | memoff(ch); | 2340 | memoff(ch); |
2837 | restore_flags(flags); | 2341 | spin_unlock_irqrestore(&epca_lock, flags); |
2838 | return 0; | 2342 | return 0; |
2839 | } | 2343 | } |
2840 | 2344 | ||
@@ -2847,19 +2351,14 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, | |||
2847 | unsigned long flags; | 2351 | unsigned long flags; |
2848 | unsigned int mflag, mstat; | 2352 | unsigned int mflag, mstat; |
2849 | unsigned char startc, stopc; | 2353 | unsigned char startc, stopc; |
2850 | volatile struct board_chan *bc; | 2354 | struct board_chan *bc; |
2851 | struct channel *ch = (struct channel *) tty->driver_data; | 2355 | struct channel *ch = (struct channel *) tty->driver_data; |
2852 | void __user *argp = (void __user *)arg; | 2356 | void __user *argp = (void __user *)arg; |
2853 | 2357 | ||
2854 | if (ch) | 2358 | if (ch) |
2855 | bc = ch->brdchan; | 2359 | bc = ch->brdchan; |
2856 | else | 2360 | else |
2857 | { | 2361 | return -EINVAL; |
2858 | printk(KERN_ERR "<Error> - ch is NULL in pc_ioctl!\n"); | ||
2859 | return(-EINVAL); | ||
2860 | } | ||
2861 | |||
2862 | save_flags(flags); | ||
2863 | 2362 | ||
2864 | /* ------------------------------------------------------------------- | 2363 | /* ------------------------------------------------------------------- |
2865 | For POSIX compliance we need to add more ioctls. See tty_ioctl.c | 2364 | For POSIX compliance we need to add more ioctls. See tty_ioctl.c |
@@ -2871,46 +2370,39 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, | |||
2871 | { /* Begin switch cmd */ | 2370 | { /* Begin switch cmd */ |
2872 | 2371 | ||
2873 | case TCGETS: | 2372 | case TCGETS: |
2874 | if (copy_to_user(argp, | 2373 | if (copy_to_user(argp, tty->termios, sizeof(struct termios))) |
2875 | tty->termios, sizeof(struct termios))) | ||
2876 | return -EFAULT; | 2374 | return -EFAULT; |
2877 | return(0); | 2375 | return 0; |
2878 | |||
2879 | case TCGETA: | 2376 | case TCGETA: |
2880 | return get_termio(tty, argp); | 2377 | return get_termio(tty, argp); |
2881 | |||
2882 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | 2378 | case TCSBRK: /* SVID version: non-zero arg --> no break */ |
2883 | |||
2884 | retval = tty_check_change(tty); | 2379 | retval = tty_check_change(tty); |
2885 | if (retval) | 2380 | if (retval) |
2886 | return retval; | 2381 | return retval; |
2887 | |||
2888 | /* Setup an event to indicate when the transmit buffer empties */ | 2382 | /* Setup an event to indicate when the transmit buffer empties */ |
2889 | 2383 | spin_lock_irqsave(&epca_lock, flags); | |
2890 | setup_empty_event(tty,ch); | 2384 | setup_empty_event(tty,ch); |
2385 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2891 | tty_wait_until_sent(tty, 0); | 2386 | tty_wait_until_sent(tty, 0); |
2892 | if (!arg) | 2387 | if (!arg) |
2893 | digi_send_break(ch, HZ/4); /* 1/4 second */ | 2388 | digi_send_break(ch, HZ/4); /* 1/4 second */ |
2894 | return 0; | 2389 | return 0; |
2895 | |||
2896 | case TCSBRKP: /* support for POSIX tcsendbreak() */ | 2390 | case TCSBRKP: /* support for POSIX tcsendbreak() */ |
2897 | |||
2898 | retval = tty_check_change(tty); | 2391 | retval = tty_check_change(tty); |
2899 | if (retval) | 2392 | if (retval) |
2900 | return retval; | 2393 | return retval; |
2901 | 2394 | ||
2902 | /* Setup an event to indicate when the transmit buffer empties */ | 2395 | /* Setup an event to indicate when the transmit buffer empties */ |
2903 | 2396 | spin_lock_irqsave(&epca_lock, flags); | |
2904 | setup_empty_event(tty,ch); | 2397 | setup_empty_event(tty,ch); |
2398 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2905 | tty_wait_until_sent(tty, 0); | 2399 | tty_wait_until_sent(tty, 0); |
2906 | digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4); | 2400 | digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4); |
2907 | return 0; | 2401 | return 0; |
2908 | |||
2909 | case TIOCGSOFTCAR: | 2402 | case TIOCGSOFTCAR: |
2910 | if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)arg)) | 2403 | if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)arg)) |
2911 | return -EFAULT; | 2404 | return -EFAULT; |
2912 | return 0; | 2405 | return 0; |
2913 | |||
2914 | case TIOCSSOFTCAR: | 2406 | case TIOCSSOFTCAR: |
2915 | { | 2407 | { |
2916 | unsigned int value; | 2408 | unsigned int value; |
@@ -2922,75 +2414,63 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, | |||
2922 | (value ? CLOCAL : 0)); | 2414 | (value ? CLOCAL : 0)); |
2923 | return 0; | 2415 | return 0; |
2924 | } | 2416 | } |
2925 | |||
2926 | case TIOCMODG: | 2417 | case TIOCMODG: |
2927 | mflag = pc_tiocmget(tty, file); | 2418 | mflag = pc_tiocmget(tty, file); |
2928 | if (put_user(mflag, (unsigned long __user *)argp)) | 2419 | if (put_user(mflag, (unsigned long __user *)argp)) |
2929 | return -EFAULT; | 2420 | return -EFAULT; |
2930 | break; | 2421 | break; |
2931 | |||
2932 | case TIOCMODS: | 2422 | case TIOCMODS: |
2933 | if (get_user(mstat, (unsigned __user *)argp)) | 2423 | if (get_user(mstat, (unsigned __user *)argp)) |
2934 | return -EFAULT; | 2424 | return -EFAULT; |
2935 | return pc_tiocmset(tty, file, mstat, ~mstat); | 2425 | return pc_tiocmset(tty, file, mstat, ~mstat); |
2936 | |||
2937 | case TIOCSDTR: | 2426 | case TIOCSDTR: |
2427 | spin_lock_irqsave(&epca_lock, flags); | ||
2938 | ch->omodem |= ch->m_dtr; | 2428 | ch->omodem |= ch->m_dtr; |
2939 | cli(); | ||
2940 | globalwinon(ch); | 2429 | globalwinon(ch); |
2941 | fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1); | 2430 | fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1); |
2942 | memoff(ch); | 2431 | memoff(ch); |
2943 | restore_flags(flags); | 2432 | spin_unlock_irqrestore(&epca_lock, flags); |
2944 | break; | 2433 | break; |
2945 | 2434 | ||
2946 | case TIOCCDTR: | 2435 | case TIOCCDTR: |
2436 | spin_lock_irqsave(&epca_lock, flags); | ||
2947 | ch->omodem &= ~ch->m_dtr; | 2437 | ch->omodem &= ~ch->m_dtr; |
2948 | cli(); | ||
2949 | globalwinon(ch); | 2438 | globalwinon(ch); |
2950 | fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1); | 2439 | fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1); |
2951 | memoff(ch); | 2440 | memoff(ch); |
2952 | restore_flags(flags); | 2441 | spin_unlock_irqrestore(&epca_lock, flags); |
2953 | break; | 2442 | break; |
2954 | |||
2955 | case DIGI_GETA: | 2443 | case DIGI_GETA: |
2956 | if (copy_to_user(argp, &ch->digiext, sizeof(digi_t))) | 2444 | if (copy_to_user(argp, &ch->digiext, sizeof(digi_t))) |
2957 | return -EFAULT; | 2445 | return -EFAULT; |
2958 | break; | 2446 | break; |
2959 | |||
2960 | case DIGI_SETAW: | 2447 | case DIGI_SETAW: |
2961 | case DIGI_SETAF: | 2448 | case DIGI_SETAF: |
2962 | if ((cmd) == (DIGI_SETAW)) | 2449 | if (cmd == DIGI_SETAW) { |
2963 | { | ||
2964 | /* Setup an event to indicate when the transmit buffer empties */ | 2450 | /* Setup an event to indicate when the transmit buffer empties */ |
2965 | 2451 | spin_lock_irqsave(&epca_lock, flags); | |
2966 | setup_empty_event(tty,ch); | 2452 | setup_empty_event(tty,ch); |
2453 | spin_unlock_irqrestore(&epca_lock, flags); | ||
2967 | tty_wait_until_sent(tty, 0); | 2454 | tty_wait_until_sent(tty, 0); |
2968 | } | 2455 | } else { |
2969 | else | ||
2970 | { | ||
2971 | /* ldisc lock already held in ioctl */ | 2456 | /* ldisc lock already held in ioctl */ |
2972 | if (tty->ldisc.flush_buffer) | 2457 | if (tty->ldisc.flush_buffer) |
2973 | tty->ldisc.flush_buffer(tty); | 2458 | tty->ldisc.flush_buffer(tty); |
2974 | } | 2459 | } |
2975 | |||
2976 | /* Fall Thru */ | 2460 | /* Fall Thru */ |
2977 | |||
2978 | case DIGI_SETA: | 2461 | case DIGI_SETA: |
2979 | if (copy_from_user(&ch->digiext, argp, sizeof(digi_t))) | 2462 | if (copy_from_user(&ch->digiext, argp, sizeof(digi_t))) |
2980 | return -EFAULT; | 2463 | return -EFAULT; |
2981 | 2464 | ||
2982 | if (ch->digiext.digi_flags & DIGI_ALTPIN) | 2465 | if (ch->digiext.digi_flags & DIGI_ALTPIN) { |
2983 | { | ||
2984 | ch->dcd = ch->m_dsr; | 2466 | ch->dcd = ch->m_dsr; |
2985 | ch->dsr = ch->m_dcd; | 2467 | ch->dsr = ch->m_dcd; |
2986 | } | 2468 | } else { |
2987 | else | ||
2988 | { | ||
2989 | ch->dcd = ch->m_dcd; | 2469 | ch->dcd = ch->m_dcd; |
2990 | ch->dsr = ch->m_dsr; | 2470 | ch->dsr = ch->m_dsr; |
2991 | } | 2471 | } |
2992 | 2472 | ||
2993 | cli(); | 2473 | spin_lock_irqsave(&epca_lock, flags); |
2994 | globalwinon(ch); | 2474 | globalwinon(ch); |
2995 | 2475 | ||
2996 | /* ----------------------------------------------------------------- | 2476 | /* ----------------------------------------------------------------- |
@@ -3000,25 +2480,22 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, | |||
3000 | 2480 | ||
3001 | epcaparam(tty,ch); | 2481 | epcaparam(tty,ch); |
3002 | memoff(ch); | 2482 | memoff(ch); |
3003 | restore_flags(flags); | 2483 | spin_unlock_irqrestore(&epca_lock, flags); |
3004 | break; | 2484 | break; |
3005 | 2485 | ||
3006 | case DIGI_GETFLOW: | 2486 | case DIGI_GETFLOW: |
3007 | case DIGI_GETAFLOW: | 2487 | case DIGI_GETAFLOW: |
3008 | cli(); | 2488 | spin_lock_irqsave(&epca_lock, flags); |
3009 | globalwinon(ch); | 2489 | globalwinon(ch); |
3010 | if ((cmd) == (DIGI_GETFLOW)) | 2490 | if (cmd == DIGI_GETFLOW) { |
3011 | { | 2491 | dflow.startc = readb(&bc->startc); |
3012 | dflow.startc = bc->startc; | 2492 | dflow.stopc = readb(&bc->stopc); |
3013 | dflow.stopc = bc->stopc; | 2493 | } else { |
3014 | } | 2494 | dflow.startc = readb(&bc->startca); |
3015 | else | 2495 | dflow.stopc = readb(&bc->stopca); |
3016 | { | ||
3017 | dflow.startc = bc->startca; | ||
3018 | dflow.stopc = bc->stopca; | ||
3019 | } | 2496 | } |
3020 | memoff(ch); | 2497 | memoff(ch); |
3021 | restore_flags(flags); | 2498 | spin_unlock_irqrestore(&epca_lock, flags); |
3022 | 2499 | ||
3023 | if (copy_to_user(argp, &dflow, sizeof(dflow))) | 2500 | if (copy_to_user(argp, &dflow, sizeof(dflow))) |
3024 | return -EFAULT; | 2501 | return -EFAULT; |
@@ -3026,13 +2503,10 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, | |||
3026 | 2503 | ||
3027 | case DIGI_SETAFLOW: | 2504 | case DIGI_SETAFLOW: |
3028 | case DIGI_SETFLOW: | 2505 | case DIGI_SETFLOW: |
3029 | if ((cmd) == (DIGI_SETFLOW)) | 2506 | if (cmd == DIGI_SETFLOW) { |
3030 | { | ||
3031 | startc = ch->startc; | 2507 | startc = ch->startc; |
3032 | stopc = ch->stopc; | 2508 | stopc = ch->stopc; |
3033 | } | 2509 | } else { |
3034 | else | ||
3035 | { | ||
3036 | startc = ch->startca; | 2510 | startc = ch->startca; |
3037 | stopc = ch->stopca; | 2511 | stopc = ch->stopca; |
3038 | } | 2512 | } |
@@ -3040,40 +2514,31 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, | |||
3040 | if (copy_from_user(&dflow, argp, sizeof(dflow))) | 2514 | if (copy_from_user(&dflow, argp, sizeof(dflow))) |
3041 | return -EFAULT; | 2515 | return -EFAULT; |
3042 | 2516 | ||
3043 | if (dflow.startc != startc || dflow.stopc != stopc) | 2517 | if (dflow.startc != startc || dflow.stopc != stopc) { /* Begin if setflow toggled */ |
3044 | { /* Begin if setflow toggled */ | 2518 | spin_lock_irqsave(&epca_lock, flags); |
3045 | cli(); | ||
3046 | globalwinon(ch); | 2519 | globalwinon(ch); |
3047 | 2520 | ||
3048 | if ((cmd) == (DIGI_SETFLOW)) | 2521 | if (cmd == DIGI_SETFLOW) { |
3049 | { | ||
3050 | ch->fepstartc = ch->startc = dflow.startc; | 2522 | ch->fepstartc = ch->startc = dflow.startc; |
3051 | ch->fepstopc = ch->stopc = dflow.stopc; | 2523 | ch->fepstopc = ch->stopc = dflow.stopc; |
3052 | fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1); | 2524 | fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1); |
3053 | } | 2525 | } else { |
3054 | else | ||
3055 | { | ||
3056 | ch->fepstartca = ch->startca = dflow.startc; | 2526 | ch->fepstartca = ch->startca = dflow.startc; |
3057 | ch->fepstopca = ch->stopca = dflow.stopc; | 2527 | ch->fepstopca = ch->stopca = dflow.stopc; |
3058 | fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1); | 2528 | fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1); |
3059 | } | 2529 | } |
3060 | 2530 | ||
3061 | if (ch->statusflags & TXSTOPPED) | 2531 | if (ch->statusflags & TXSTOPPED) |
3062 | pc_start(tty); | 2532 | pc_start(tty); |
3063 | 2533 | ||
3064 | memoff(ch); | 2534 | memoff(ch); |
3065 | restore_flags(flags); | 2535 | spin_unlock_irqrestore(&epca_lock, flags); |
3066 | |||
3067 | } /* End if setflow toggled */ | 2536 | } /* End if setflow toggled */ |
3068 | break; | 2537 | break; |
3069 | |||
3070 | default: | 2538 | default: |
3071 | return -ENOIOCTLCMD; | 2539 | return -ENOIOCTLCMD; |
3072 | |||
3073 | } /* End switch cmd */ | 2540 | } /* End switch cmd */ |
3074 | |||
3075 | return 0; | 2541 | return 0; |
3076 | |||
3077 | } /* End pc_ioctl */ | 2542 | } /* End pc_ioctl */ |
3078 | 2543 | ||
3079 | /* --------------------- Begin pc_set_termios ----------------------- */ | 2544 | /* --------------------- Begin pc_set_termios ----------------------- */ |
@@ -3083,20 +2548,16 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios) | |||
3083 | 2548 | ||
3084 | struct channel *ch; | 2549 | struct channel *ch; |
3085 | unsigned long flags; | 2550 | unsigned long flags; |
3086 | |||
3087 | /* --------------------------------------------------------- | 2551 | /* --------------------------------------------------------- |
3088 | verifyChannel returns the channel from the tty struct | 2552 | verifyChannel returns the channel from the tty struct |
3089 | if it is valid. This serves as a sanity check. | 2553 | if it is valid. This serves as a sanity check. |
3090 | ------------------------------------------------------------- */ | 2554 | ------------------------------------------------------------- */ |
3091 | 2555 | if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */ | |
3092 | if ((ch = verifyChannel(tty)) != NULL) | 2556 | spin_lock_irqsave(&epca_lock, flags); |
3093 | { /* Begin if channel valid */ | ||
3094 | |||
3095 | save_flags(flags); | ||
3096 | cli(); | ||
3097 | globalwinon(ch); | 2557 | globalwinon(ch); |
3098 | epcaparam(tty, ch); | 2558 | epcaparam(tty, ch); |
3099 | memoff(ch); | 2559 | memoff(ch); |
2560 | spin_unlock_irqrestore(&epca_lock, flags); | ||
3100 | 2561 | ||
3101 | if ((old_termios->c_cflag & CRTSCTS) && | 2562 | if ((old_termios->c_cflag & CRTSCTS) && |
3102 | ((tty->termios->c_cflag & CRTSCTS) == 0)) | 2563 | ((tty->termios->c_cflag & CRTSCTS) == 0)) |
@@ -3106,8 +2567,6 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios) | |||
3106 | (tty->termios->c_cflag & CLOCAL)) | 2567 | (tty->termios->c_cflag & CLOCAL)) |
3107 | wake_up_interruptible(&ch->open_wait); | 2568 | wake_up_interruptible(&ch->open_wait); |
3108 | 2569 | ||
3109 | restore_flags(flags); | ||
3110 | |||
3111 | } /* End if channel valid */ | 2570 | } /* End if channel valid */ |
3112 | 2571 | ||
3113 | } /* End pc_set_termios */ | 2572 | } /* End pc_set_termios */ |
@@ -3116,29 +2575,18 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios) | |||
3116 | 2575 | ||
3117 | static void do_softint(void *private_) | 2576 | static void do_softint(void *private_) |
3118 | { /* Begin do_softint */ | 2577 | { /* Begin do_softint */ |
3119 | |||
3120 | struct channel *ch = (struct channel *) private_; | 2578 | struct channel *ch = (struct channel *) private_; |
3121 | |||
3122 | |||
3123 | /* Called in response to a modem change event */ | 2579 | /* Called in response to a modem change event */ |
3124 | 2580 | if (ch && ch->magic == EPCA_MAGIC) { /* Begin EPCA_MAGIC */ | |
3125 | if (ch && ch->magic == EPCA_MAGIC) | ||
3126 | { /* Begin EPCA_MAGIC */ | ||
3127 | |||
3128 | struct tty_struct *tty = ch->tty; | 2581 | struct tty_struct *tty = ch->tty; |
3129 | 2582 | ||
3130 | if (tty && tty->driver_data) | 2583 | if (tty && tty->driver_data) { |
3131 | { | 2584 | if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { /* Begin if clear_bit */ |
3132 | if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) | ||
3133 | { /* Begin if clear_bit */ | ||
3134 | |||
3135 | tty_hangup(tty); /* FIXME: module removal race here - AKPM */ | 2585 | tty_hangup(tty); /* FIXME: module removal race here - AKPM */ |
3136 | wake_up_interruptible(&ch->open_wait); | 2586 | wake_up_interruptible(&ch->open_wait); |
3137 | ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE; | 2587 | ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE; |
3138 | |||
3139 | } /* End if clear_bit */ | 2588 | } /* End if clear_bit */ |
3140 | } | 2589 | } |
3141 | |||
3142 | } /* End EPCA_MAGIC */ | 2590 | } /* End EPCA_MAGIC */ |
3143 | } /* End do_softint */ | 2591 | } /* End do_softint */ |
3144 | 2592 | ||
@@ -3154,82 +2602,49 @@ static void pc_stop(struct tty_struct *tty) | |||
3154 | 2602 | ||
3155 | struct channel *ch; | 2603 | struct channel *ch; |
3156 | unsigned long flags; | 2604 | unsigned long flags; |
3157 | |||
3158 | /* --------------------------------------------------------- | 2605 | /* --------------------------------------------------------- |
3159 | verifyChannel returns the channel from the tty struct | 2606 | verifyChannel returns the channel from the tty struct |
3160 | if it is valid. This serves as a sanity check. | 2607 | if it is valid. This serves as a sanity check. |
3161 | ------------------------------------------------------------- */ | 2608 | ------------------------------------------------------------- */ |
3162 | 2609 | if ((ch = verifyChannel(tty)) != NULL) { /* Begin if valid channel */ | |
3163 | if ((ch = verifyChannel(tty)) != NULL) | 2610 | spin_lock_irqsave(&epca_lock, flags); |
3164 | { /* Begin if valid channel */ | 2611 | if ((ch->statusflags & TXSTOPPED) == 0) { /* Begin if transmit stop requested */ |
3165 | |||
3166 | save_flags(flags); | ||
3167 | cli(); | ||
3168 | |||
3169 | if ((ch->statusflags & TXSTOPPED) == 0) | ||
3170 | { /* Begin if transmit stop requested */ | ||
3171 | |||
3172 | globalwinon(ch); | 2612 | globalwinon(ch); |
3173 | |||
3174 | /* STOP transmitting now !! */ | 2613 | /* STOP transmitting now !! */ |
3175 | |||
3176 | fepcmd(ch, PAUSETX, 0, 0, 0, 0); | 2614 | fepcmd(ch, PAUSETX, 0, 0, 0, 0); |
3177 | |||
3178 | ch->statusflags |= TXSTOPPED; | 2615 | ch->statusflags |= TXSTOPPED; |
3179 | memoff(ch); | 2616 | memoff(ch); |
3180 | |||
3181 | } /* End if transmit stop requested */ | 2617 | } /* End if transmit stop requested */ |
3182 | 2618 | spin_unlock_irqrestore(&epca_lock, flags); | |
3183 | restore_flags(flags); | ||
3184 | |||
3185 | } /* End if valid channel */ | 2619 | } /* End if valid channel */ |
3186 | |||
3187 | } /* End pc_stop */ | 2620 | } /* End pc_stop */ |
3188 | 2621 | ||
3189 | /* --------------------- Begin pc_start ----------------------- */ | 2622 | /* --------------------- Begin pc_start ----------------------- */ |
3190 | 2623 | ||
3191 | static void pc_start(struct tty_struct *tty) | 2624 | static void pc_start(struct tty_struct *tty) |
3192 | { /* Begin pc_start */ | 2625 | { /* Begin pc_start */ |
3193 | |||
3194 | struct channel *ch; | 2626 | struct channel *ch; |
3195 | |||
3196 | /* --------------------------------------------------------- | 2627 | /* --------------------------------------------------------- |
3197 | verifyChannel returns the channel from the tty struct | 2628 | verifyChannel returns the channel from the tty struct |
3198 | if it is valid. This serves as a sanity check. | 2629 | if it is valid. This serves as a sanity check. |
3199 | ------------------------------------------------------------- */ | 2630 | ------------------------------------------------------------- */ |
3200 | 2631 | if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */ | |
3201 | if ((ch = verifyChannel(tty)) != NULL) | ||
3202 | { /* Begin if channel valid */ | ||
3203 | |||
3204 | unsigned long flags; | 2632 | unsigned long flags; |
3205 | 2633 | spin_lock_irqsave(&epca_lock, flags); | |
3206 | save_flags(flags); | ||
3207 | cli(); | ||
3208 | |||
3209 | /* Just in case output was resumed because of a change in Digi-flow */ | 2634 | /* Just in case output was resumed because of a change in Digi-flow */ |
3210 | if (ch->statusflags & TXSTOPPED) | 2635 | if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */ |
3211 | { /* Begin transmit resume requested */ | 2636 | struct board_chan *bc; |
3212 | |||
3213 | volatile struct board_chan *bc; | ||
3214 | |||
3215 | globalwinon(ch); | 2637 | globalwinon(ch); |
3216 | bc = ch->brdchan; | 2638 | bc = ch->brdchan; |
3217 | if (ch->statusflags & LOWWAIT) | 2639 | if (ch->statusflags & LOWWAIT) |
3218 | bc->ilow = 1; | 2640 | writeb(1, &bc->ilow); |
3219 | |||
3220 | /* Okay, you can start transmitting again... */ | 2641 | /* Okay, you can start transmitting again... */ |
3221 | |||
3222 | fepcmd(ch, RESUMETX, 0, 0, 0, 0); | 2642 | fepcmd(ch, RESUMETX, 0, 0, 0, 0); |
3223 | |||
3224 | ch->statusflags &= ~TXSTOPPED; | 2643 | ch->statusflags &= ~TXSTOPPED; |
3225 | memoff(ch); | 2644 | memoff(ch); |
3226 | |||
3227 | } /* End transmit resume requested */ | 2645 | } /* End transmit resume requested */ |
3228 | 2646 | spin_unlock_irqrestore(&epca_lock, flags); | |
3229 | restore_flags(flags); | ||
3230 | |||
3231 | } /* End if channel valid */ | 2647 | } /* End if channel valid */ |
3232 | |||
3233 | } /* End pc_start */ | 2648 | } /* End pc_start */ |
3234 | 2649 | ||
3235 | /* ------------------------------------------------------------------ | 2650 | /* ------------------------------------------------------------------ |
@@ -3244,86 +2659,55 @@ ______________________________________________________________________ */ | |||
3244 | 2659 | ||
3245 | static void pc_throttle(struct tty_struct * tty) | 2660 | static void pc_throttle(struct tty_struct * tty) |
3246 | { /* Begin pc_throttle */ | 2661 | { /* Begin pc_throttle */ |
3247 | |||
3248 | struct channel *ch; | 2662 | struct channel *ch; |
3249 | unsigned long flags; | 2663 | unsigned long flags; |
3250 | |||
3251 | /* --------------------------------------------------------- | 2664 | /* --------------------------------------------------------- |
3252 | verifyChannel returns the channel from the tty struct | 2665 | verifyChannel returns the channel from the tty struct |
3253 | if it is valid. This serves as a sanity check. | 2666 | if it is valid. This serves as a sanity check. |
3254 | ------------------------------------------------------------- */ | 2667 | ------------------------------------------------------------- */ |
3255 | 2668 | if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */ | |
3256 | if ((ch = verifyChannel(tty)) != NULL) | 2669 | spin_lock_irqsave(&epca_lock, flags); |
3257 | { /* Begin if channel valid */ | 2670 | if ((ch->statusflags & RXSTOPPED) == 0) { |
3258 | |||
3259 | |||
3260 | save_flags(flags); | ||
3261 | cli(); | ||
3262 | |||
3263 | if ((ch->statusflags & RXSTOPPED) == 0) | ||
3264 | { | ||
3265 | globalwinon(ch); | 2671 | globalwinon(ch); |
3266 | fepcmd(ch, PAUSERX, 0, 0, 0, 0); | 2672 | fepcmd(ch, PAUSERX, 0, 0, 0, 0); |
3267 | |||
3268 | ch->statusflags |= RXSTOPPED; | 2673 | ch->statusflags |= RXSTOPPED; |
3269 | memoff(ch); | 2674 | memoff(ch); |
3270 | } | 2675 | } |
3271 | restore_flags(flags); | 2676 | spin_unlock_irqrestore(&epca_lock, flags); |
3272 | |||
3273 | } /* End if channel valid */ | 2677 | } /* End if channel valid */ |
3274 | |||
3275 | } /* End pc_throttle */ | 2678 | } /* End pc_throttle */ |
3276 | 2679 | ||
3277 | /* --------------------- Begin unthrottle ----------------------- */ | 2680 | /* --------------------- Begin unthrottle ----------------------- */ |
3278 | 2681 | ||
3279 | static void pc_unthrottle(struct tty_struct *tty) | 2682 | static void pc_unthrottle(struct tty_struct *tty) |
3280 | { /* Begin pc_unthrottle */ | 2683 | { /* Begin pc_unthrottle */ |
3281 | |||
3282 | struct channel *ch; | 2684 | struct channel *ch; |
3283 | unsigned long flags; | 2685 | unsigned long flags; |
3284 | volatile struct board_chan *bc; | ||
3285 | |||
3286 | |||
3287 | /* --------------------------------------------------------- | 2686 | /* --------------------------------------------------------- |
3288 | verifyChannel returns the channel from the tty struct | 2687 | verifyChannel returns the channel from the tty struct |
3289 | if it is valid. This serves as a sanity check. | 2688 | if it is valid. This serves as a sanity check. |
3290 | ------------------------------------------------------------- */ | 2689 | ------------------------------------------------------------- */ |
3291 | 2690 | if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */ | |
3292 | if ((ch = verifyChannel(tty)) != NULL) | ||
3293 | { /* Begin if channel valid */ | ||
3294 | |||
3295 | |||
3296 | /* Just in case output was resumed because of a change in Digi-flow */ | 2691 | /* Just in case output was resumed because of a change in Digi-flow */ |
3297 | save_flags(flags); | 2692 | spin_lock_irqsave(&epca_lock, flags); |
3298 | cli(); | 2693 | if (ch->statusflags & RXSTOPPED) { |
3299 | |||
3300 | if (ch->statusflags & RXSTOPPED) | ||
3301 | { | ||
3302 | |||
3303 | globalwinon(ch); | 2694 | globalwinon(ch); |
3304 | bc = ch->brdchan; | ||
3305 | fepcmd(ch, RESUMERX, 0, 0, 0, 0); | 2695 | fepcmd(ch, RESUMERX, 0, 0, 0, 0); |
3306 | |||
3307 | ch->statusflags &= ~RXSTOPPED; | 2696 | ch->statusflags &= ~RXSTOPPED; |
3308 | memoff(ch); | 2697 | memoff(ch); |
3309 | } | 2698 | } |
3310 | restore_flags(flags); | 2699 | spin_unlock_irqrestore(&epca_lock, flags); |
3311 | |||
3312 | } /* End if channel valid */ | 2700 | } /* End if channel valid */ |
3313 | |||
3314 | } /* End pc_unthrottle */ | 2701 | } /* End pc_unthrottle */ |
3315 | 2702 | ||
3316 | /* --------------------- Begin digi_send_break ----------------------- */ | 2703 | /* --------------------- Begin digi_send_break ----------------------- */ |
3317 | 2704 | ||
3318 | void digi_send_break(struct channel *ch, int msec) | 2705 | void digi_send_break(struct channel *ch, int msec) |
3319 | { /* Begin digi_send_break */ | 2706 | { /* Begin digi_send_break */ |
3320 | |||
3321 | unsigned long flags; | 2707 | unsigned long flags; |
3322 | 2708 | ||
3323 | save_flags(flags); | 2709 | spin_lock_irqsave(&epca_lock, flags); |
3324 | cli(); | ||
3325 | globalwinon(ch); | 2710 | globalwinon(ch); |
3326 | |||
3327 | /* -------------------------------------------------------------------- | 2711 | /* -------------------------------------------------------------------- |
3328 | Maybe I should send an infinite break here, schedule() for | 2712 | Maybe I should send an infinite break here, schedule() for |
3329 | msec amount of time, and then stop the break. This way, | 2713 | msec amount of time, and then stop the break. This way, |
@@ -3331,36 +2715,28 @@ void digi_send_break(struct channel *ch, int msec) | |||
3331 | to be called (i.e. via an ioctl()) more than once in msec amount | 2715 | to be called (i.e. via an ioctl()) more than once in msec amount |
3332 | of time. Try this for now... | 2716 | of time. Try this for now... |
3333 | ------------------------------------------------------------------------ */ | 2717 | ------------------------------------------------------------------------ */ |
3334 | |||
3335 | fepcmd(ch, SENDBREAK, msec, 0, 10, 0); | 2718 | fepcmd(ch, SENDBREAK, msec, 0, 10, 0); |
3336 | memoff(ch); | 2719 | memoff(ch); |
3337 | 2720 | spin_unlock_irqrestore(&epca_lock, flags); | |
3338 | restore_flags(flags); | ||
3339 | |||
3340 | } /* End digi_send_break */ | 2721 | } /* End digi_send_break */ |
3341 | 2722 | ||
3342 | /* --------------------- Begin setup_empty_event ----------------------- */ | 2723 | /* --------------------- Begin setup_empty_event ----------------------- */ |
3343 | 2724 | ||
2725 | /* Caller MUST hold the lock */ | ||
2726 | |||
3344 | static void setup_empty_event(struct tty_struct *tty, struct channel *ch) | 2727 | static void setup_empty_event(struct tty_struct *tty, struct channel *ch) |
3345 | { /* Begin setup_empty_event */ | 2728 | { /* Begin setup_empty_event */ |
3346 | 2729 | ||
3347 | volatile struct board_chan *bc = ch->brdchan; | 2730 | struct board_chan *bc = ch->brdchan; |
3348 | unsigned long int flags; | ||
3349 | 2731 | ||
3350 | save_flags(flags); | ||
3351 | cli(); | ||
3352 | globalwinon(ch); | 2732 | globalwinon(ch); |
3353 | ch->statusflags |= EMPTYWAIT; | 2733 | ch->statusflags |= EMPTYWAIT; |
3354 | |||
3355 | /* ------------------------------------------------------------------ | 2734 | /* ------------------------------------------------------------------ |
3356 | When set the iempty flag request a event to be generated when the | 2735 | When set the iempty flag request a event to be generated when the |
3357 | transmit buffer is empty (If there is no BREAK in progress). | 2736 | transmit buffer is empty (If there is no BREAK in progress). |
3358 | --------------------------------------------------------------------- */ | 2737 | --------------------------------------------------------------------- */ |
3359 | 2738 | writeb(1, &bc->iempty); | |
3360 | bc->iempty = 1; | ||
3361 | memoff(ch); | 2739 | memoff(ch); |
3362 | restore_flags(flags); | ||
3363 | |||
3364 | } /* End setup_empty_event */ | 2740 | } /* End setup_empty_event */ |
3365 | 2741 | ||
3366 | /* --------------------- Begin get_termio ----------------------- */ | 2742 | /* --------------------- Begin get_termio ----------------------- */ |
@@ -3369,10 +2745,10 @@ static int get_termio(struct tty_struct * tty, struct termio __user * termio) | |||
3369 | { /* Begin get_termio */ | 2745 | { /* Begin get_termio */ |
3370 | return kernel_termios_to_user_termio(termio, tty->termios); | 2746 | return kernel_termios_to_user_termio(termio, tty->termios); |
3371 | } /* End get_termio */ | 2747 | } /* End get_termio */ |
2748 | |||
3372 | /* ---------------------- Begin epca_setup -------------------------- */ | 2749 | /* ---------------------- Begin epca_setup -------------------------- */ |
3373 | void epca_setup(char *str, int *ints) | 2750 | void epca_setup(char *str, int *ints) |
3374 | { /* Begin epca_setup */ | 2751 | { /* Begin epca_setup */ |
3375 | |||
3376 | struct board_info board; | 2752 | struct board_info board; |
3377 | int index, loop, last; | 2753 | int index, loop, last; |
3378 | char *temp, *t2; | 2754 | char *temp, *t2; |
@@ -3394,49 +2770,41 @@ void epca_setup(char *str, int *ints) | |||
3394 | for (last = 0, index = 1; index <= ints[0]; index++) | 2770 | for (last = 0, index = 1; index <= ints[0]; index++) |
3395 | switch(index) | 2771 | switch(index) |
3396 | { /* Begin parse switch */ | 2772 | { /* Begin parse switch */ |
3397 | |||
3398 | case 1: | 2773 | case 1: |
3399 | board.status = ints[index]; | 2774 | board.status = ints[index]; |
3400 | |||
3401 | /* --------------------------------------------------------- | 2775 | /* --------------------------------------------------------- |
3402 | We check for 2 (As opposed to 1; because 2 is a flag | 2776 | We check for 2 (As opposed to 1; because 2 is a flag |
3403 | instructing the driver to ignore epcaconfig.) For this | 2777 | instructing the driver to ignore epcaconfig.) For this |
3404 | reason we check for 2. | 2778 | reason we check for 2. |
3405 | ------------------------------------------------------------ */ | 2779 | ------------------------------------------------------------ */ |
3406 | if (board.status == 2) | 2780 | if (board.status == 2) { /* Begin ignore epcaconfig as well as lilo cmd line */ |
3407 | { /* Begin ignore epcaconfig as well as lilo cmd line */ | ||
3408 | nbdevs = 0; | 2781 | nbdevs = 0; |
3409 | num_cards = 0; | 2782 | num_cards = 0; |
3410 | return; | 2783 | return; |
3411 | } /* End ignore epcaconfig as well as lilo cmd line */ | 2784 | } /* End ignore epcaconfig as well as lilo cmd line */ |
3412 | 2785 | ||
3413 | if (board.status > 2) | 2786 | if (board.status > 2) { |
3414 | { | 2787 | printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", board.status); |
3415 | printk(KERN_ERR "<Error> - epca_setup: Invalid board status 0x%x\n", board.status); | ||
3416 | invalid_lilo_config = 1; | 2788 | invalid_lilo_config = 1; |
3417 | setup_error_code |= INVALID_BOARD_STATUS; | 2789 | setup_error_code |= INVALID_BOARD_STATUS; |
3418 | return; | 2790 | return; |
3419 | } | 2791 | } |
3420 | last = index; | 2792 | last = index; |
3421 | break; | 2793 | break; |
3422 | |||
3423 | case 2: | 2794 | case 2: |
3424 | board.type = ints[index]; | 2795 | board.type = ints[index]; |
3425 | if (board.type >= PCIXEM) | 2796 | if (board.type >= PCIXEM) { |
3426 | { | 2797 | printk(KERN_ERR "epca_setup: Invalid board type 0x%x\n", board.type); |
3427 | printk(KERN_ERR "<Error> - epca_setup: Invalid board type 0x%x\n", board.type); | ||
3428 | invalid_lilo_config = 1; | 2798 | invalid_lilo_config = 1; |
3429 | setup_error_code |= INVALID_BOARD_TYPE; | 2799 | setup_error_code |= INVALID_BOARD_TYPE; |
3430 | return; | 2800 | return; |
3431 | } | 2801 | } |
3432 | last = index; | 2802 | last = index; |
3433 | break; | 2803 | break; |
3434 | |||
3435 | case 3: | 2804 | case 3: |
3436 | board.altpin = ints[index]; | 2805 | board.altpin = ints[index]; |
3437 | if (board.altpin > 1) | 2806 | if (board.altpin > 1) { |
3438 | { | 2807 | printk(KERN_ERR "epca_setup: Invalid board altpin 0x%x\n", board.altpin); |
3439 | printk(KERN_ERR "<Error> - epca_setup: Invalid board altpin 0x%x\n", board.altpin); | ||
3440 | invalid_lilo_config = 1; | 2808 | invalid_lilo_config = 1; |
3441 | setup_error_code |= INVALID_ALTPIN; | 2809 | setup_error_code |= INVALID_ALTPIN; |
3442 | return; | 2810 | return; |
@@ -3446,9 +2814,8 @@ void epca_setup(char *str, int *ints) | |||
3446 | 2814 | ||
3447 | case 4: | 2815 | case 4: |
3448 | board.numports = ints[index]; | 2816 | board.numports = ints[index]; |
3449 | if ((board.numports < 2) || (board.numports > 256)) | 2817 | if (board.numports < 2 || board.numports > 256) { |
3450 | { | 2818 | printk(KERN_ERR "epca_setup: Invalid board numports 0x%x\n", board.numports); |
3451 | printk(KERN_ERR "<Error> - epca_setup: Invalid board numports 0x%x\n", board.numports); | ||
3452 | invalid_lilo_config = 1; | 2819 | invalid_lilo_config = 1; |
3453 | setup_error_code |= INVALID_NUM_PORTS; | 2820 | setup_error_code |= INVALID_NUM_PORTS; |
3454 | return; | 2821 | return; |
@@ -3458,10 +2825,9 @@ void epca_setup(char *str, int *ints) | |||
3458 | break; | 2825 | break; |
3459 | 2826 | ||
3460 | case 5: | 2827 | case 5: |
3461 | board.port = (unsigned char *)ints[index]; | 2828 | board.port = ints[index]; |
3462 | if (ints[index] <= 0) | 2829 | if (ints[index] <= 0) { |
3463 | { | 2830 | printk(KERN_ERR "epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port); |
3464 | printk(KERN_ERR "<Error> - epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port); | ||
3465 | invalid_lilo_config = 1; | 2831 | invalid_lilo_config = 1; |
3466 | setup_error_code |= INVALID_PORT_BASE; | 2832 | setup_error_code |= INVALID_PORT_BASE; |
3467 | return; | 2833 | return; |
@@ -3470,10 +2836,9 @@ void epca_setup(char *str, int *ints) | |||
3470 | break; | 2836 | break; |
3471 | 2837 | ||
3472 | case 6: | 2838 | case 6: |
3473 | board.membase = (unsigned char *)ints[index]; | 2839 | board.membase = ints[index]; |
3474 | if (ints[index] <= 0) | 2840 | if (ints[index] <= 0) { |
3475 | { | 2841 | printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase); |
3476 | printk(KERN_ERR "<Error> - epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase); | ||
3477 | invalid_lilo_config = 1; | 2842 | invalid_lilo_config = 1; |
3478 | setup_error_code |= INVALID_MEM_BASE; | 2843 | setup_error_code |= INVALID_MEM_BASE; |
3479 | return; | 2844 | return; |
@@ -3487,21 +2852,16 @@ void epca_setup(char *str, int *ints) | |||
3487 | 2852 | ||
3488 | } /* End parse switch */ | 2853 | } /* End parse switch */ |
3489 | 2854 | ||
3490 | while (str && *str) | 2855 | while (str && *str) { /* Begin while there is a string arg */ |
3491 | { /* Begin while there is a string arg */ | ||
3492 | |||
3493 | /* find the next comma or terminator */ | 2856 | /* find the next comma or terminator */ |
3494 | temp = str; | 2857 | temp = str; |
3495 | |||
3496 | /* While string is not null, and a comma hasn't been found */ | 2858 | /* While string is not null, and a comma hasn't been found */ |
3497 | while (*temp && (*temp != ',')) | 2859 | while (*temp && (*temp != ',')) |
3498 | temp++; | 2860 | temp++; |
3499 | |||
3500 | if (!*temp) | 2861 | if (!*temp) |
3501 | temp = NULL; | 2862 | temp = NULL; |
3502 | else | 2863 | else |
3503 | *temp++ = 0; | 2864 | *temp++ = 0; |
3504 | |||
3505 | /* Set index to the number of args + 1 */ | 2865 | /* Set index to the number of args + 1 */ |
3506 | index = last + 1; | 2866 | index = last + 1; |
3507 | 2867 | ||
@@ -3511,12 +2871,10 @@ void epca_setup(char *str, int *ints) | |||
3511 | len = strlen(str); | 2871 | len = strlen(str); |
3512 | if (strncmp("Disable", str, len) == 0) | 2872 | if (strncmp("Disable", str, len) == 0) |
3513 | board.status = 0; | 2873 | board.status = 0; |
3514 | else | 2874 | else if (strncmp("Enable", str, len) == 0) |
3515 | if (strncmp("Enable", str, len) == 0) | ||
3516 | board.status = 1; | 2875 | board.status = 1; |
3517 | else | 2876 | else { |
3518 | { | 2877 | printk(KERN_ERR "epca_setup: Invalid status %s\n", str); |
3519 | printk(KERN_ERR "<Error> - epca_setup: Invalid status %s\n", str); | ||
3520 | invalid_lilo_config = 1; | 2878 | invalid_lilo_config = 1; |
3521 | setup_error_code |= INVALID_BOARD_STATUS; | 2879 | setup_error_code |= INVALID_BOARD_STATUS; |
3522 | return; | 2880 | return; |
@@ -3525,22 +2883,17 @@ void epca_setup(char *str, int *ints) | |||
3525 | break; | 2883 | break; |
3526 | 2884 | ||
3527 | case 2: | 2885 | case 2: |
3528 | |||
3529 | for(loop = 0; loop < EPCA_NUM_TYPES; loop++) | 2886 | for(loop = 0; loop < EPCA_NUM_TYPES; loop++) |
3530 | if (strcmp(board_desc[loop], str) == 0) | 2887 | if (strcmp(board_desc[loop], str) == 0) |
3531 | break; | 2888 | break; |
3532 | |||
3533 | |||
3534 | /* --------------------------------------------------------------- | 2889 | /* --------------------------------------------------------------- |
3535 | If the index incremented above refers to a legitamate board | 2890 | If the index incremented above refers to a legitamate board |
3536 | type set it here. | 2891 | type set it here. |
3537 | ------------------------------------------------------------------*/ | 2892 | ------------------------------------------------------------------*/ |
3538 | |||
3539 | if (index < EPCA_NUM_TYPES) | 2893 | if (index < EPCA_NUM_TYPES) |
3540 | board.type = loop; | 2894 | board.type = loop; |
3541 | else | 2895 | else { |
3542 | { | 2896 | printk(KERN_ERR "epca_setup: Invalid board type: %s\n", str); |
3543 | printk(KERN_ERR "<Error> - epca_setup: Invalid board type: %s\n", str); | ||
3544 | invalid_lilo_config = 1; | 2897 | invalid_lilo_config = 1; |
3545 | setup_error_code |= INVALID_BOARD_TYPE; | 2898 | setup_error_code |= INVALID_BOARD_TYPE; |
3546 | return; | 2899 | return; |
@@ -3552,12 +2905,10 @@ void epca_setup(char *str, int *ints) | |||
3552 | len = strlen(str); | 2905 | len = strlen(str); |
3553 | if (strncmp("Disable", str, len) == 0) | 2906 | if (strncmp("Disable", str, len) == 0) |
3554 | board.altpin = 0; | 2907 | board.altpin = 0; |
3555 | else | 2908 | else if (strncmp("Enable", str, len) == 0) |
3556 | if (strncmp("Enable", str, len) == 0) | ||
3557 | board.altpin = 1; | 2909 | board.altpin = 1; |
3558 | else | 2910 | else { |
3559 | { | 2911 | printk(KERN_ERR "epca_setup: Invalid altpin %s\n", str); |
3560 | printk(KERN_ERR "<Error> - epca_setup: Invalid altpin %s\n", str); | ||
3561 | invalid_lilo_config = 1; | 2912 | invalid_lilo_config = 1; |
3562 | setup_error_code |= INVALID_ALTPIN; | 2913 | setup_error_code |= INVALID_ALTPIN; |
3563 | return; | 2914 | return; |
@@ -3570,9 +2921,8 @@ void epca_setup(char *str, int *ints) | |||
3570 | while (isdigit(*t2)) | 2921 | while (isdigit(*t2)) |
3571 | t2++; | 2922 | t2++; |
3572 | 2923 | ||
3573 | if (*t2) | 2924 | if (*t2) { |
3574 | { | 2925 | printk(KERN_ERR "epca_setup: Invalid port count %s\n", str); |
3575 | printk(KERN_ERR "<Error> - epca_setup: Invalid port count %s\n", str); | ||
3576 | invalid_lilo_config = 1; | 2926 | invalid_lilo_config = 1; |
3577 | setup_error_code |= INVALID_NUM_PORTS; | 2927 | setup_error_code |= INVALID_NUM_PORTS; |
3578 | return; | 2928 | return; |
@@ -3601,15 +2951,14 @@ void epca_setup(char *str, int *ints) | |||
3601 | while (isxdigit(*t2)) | 2951 | while (isxdigit(*t2)) |
3602 | t2++; | 2952 | t2++; |
3603 | 2953 | ||
3604 | if (*t2) | 2954 | if (*t2) { |
3605 | { | 2955 | printk(KERN_ERR "epca_setup: Invalid i/o address %s\n", str); |
3606 | printk(KERN_ERR "<Error> - epca_setup: Invalid i/o address %s\n", str); | ||
3607 | invalid_lilo_config = 1; | 2956 | invalid_lilo_config = 1; |
3608 | setup_error_code |= INVALID_PORT_BASE; | 2957 | setup_error_code |= INVALID_PORT_BASE; |
3609 | return; | 2958 | return; |
3610 | } | 2959 | } |
3611 | 2960 | ||
3612 | board.port = (unsigned char *)simple_strtoul(str, NULL, 16); | 2961 | board.port = simple_strtoul(str, NULL, 16); |
3613 | last = index; | 2962 | last = index; |
3614 | break; | 2963 | break; |
3615 | 2964 | ||
@@ -3618,52 +2967,38 @@ void epca_setup(char *str, int *ints) | |||
3618 | while (isxdigit(*t2)) | 2967 | while (isxdigit(*t2)) |
3619 | t2++; | 2968 | t2++; |
3620 | 2969 | ||
3621 | if (*t2) | 2970 | if (*t2) { |
3622 | { | 2971 | printk(KERN_ERR "epca_setup: Invalid memory base %s\n",str); |
3623 | printk(KERN_ERR "<Error> - epca_setup: Invalid memory base %s\n",str); | ||
3624 | invalid_lilo_config = 1; | 2972 | invalid_lilo_config = 1; |
3625 | setup_error_code |= INVALID_MEM_BASE; | 2973 | setup_error_code |= INVALID_MEM_BASE; |
3626 | return; | 2974 | return; |
3627 | } | 2975 | } |
3628 | 2976 | board.membase = simple_strtoul(str, NULL, 16); | |
3629 | board.membase = (unsigned char *)simple_strtoul(str, NULL, 16); | ||
3630 | last = index; | 2977 | last = index; |
3631 | break; | 2978 | break; |
3632 | |||
3633 | default: | 2979 | default: |
3634 | printk(KERN_ERR "PC/Xx: Too many string parms\n"); | 2980 | printk(KERN_ERR "epca: Too many string parms\n"); |
3635 | return; | 2981 | return; |
3636 | } | 2982 | } |
3637 | str = temp; | 2983 | str = temp; |
3638 | |||
3639 | } /* End while there is a string arg */ | 2984 | } /* End while there is a string arg */ |
3640 | 2985 | ||
3641 | 2986 | if (last < 6) { | |
3642 | if (last < 6) | 2987 | printk(KERN_ERR "epca: Insufficient parms specified\n"); |
3643 | { | ||
3644 | printk(KERN_ERR "PC/Xx: Insufficient parms specified\n"); | ||
3645 | return; | 2988 | return; |
3646 | } | 2989 | } |
3647 | 2990 | ||
3648 | /* I should REALLY validate the stuff here */ | 2991 | /* I should REALLY validate the stuff here */ |
3649 | |||
3650 | /* Copies our local copy of board into boards */ | 2992 | /* Copies our local copy of board into boards */ |
3651 | memcpy((void *)&boards[num_cards],(void *)&board, sizeof(board)); | 2993 | memcpy((void *)&boards[num_cards],(void *)&board, sizeof(board)); |
3652 | |||
3653 | |||
3654 | /* Does this get called once per lilo arg are what ? */ | 2994 | /* Does this get called once per lilo arg are what ? */ |
3655 | |||
3656 | printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n", | 2995 | printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n", |
3657 | num_cards, board_desc[board.type], | 2996 | num_cards, board_desc[board.type], |
3658 | board.numports, (int)board.port, (unsigned int) board.membase); | 2997 | board.numports, (int)board.port, (unsigned int) board.membase); |
3659 | |||
3660 | num_cards++; | 2998 | num_cards++; |
3661 | |||
3662 | } /* End epca_setup */ | 2999 | } /* End epca_setup */ |
3663 | 3000 | ||
3664 | 3001 | ||
3665 | |||
3666 | #ifdef ENABLE_PCI | ||
3667 | /* ------------------------ Begin init_PCI --------------------------- */ | 3002 | /* ------------------------ Begin init_PCI --------------------------- */ |
3668 | 3003 | ||
3669 | enum epic_board_types { | 3004 | enum epic_board_types { |
@@ -3685,7 +3020,6 @@ static struct { | |||
3685 | { PCIXRJ, 2, }, | 3020 | { PCIXRJ, 2, }, |
3686 | }; | 3021 | }; |
3687 | 3022 | ||
3688 | |||
3689 | static int __devinit epca_init_one (struct pci_dev *pdev, | 3023 | static int __devinit epca_init_one (struct pci_dev *pdev, |
3690 | const struct pci_device_id *ent) | 3024 | const struct pci_device_id *ent) |
3691 | { | 3025 | { |
@@ -3711,10 +3045,8 @@ static int __devinit epca_init_one (struct pci_dev *pdev, | |||
3711 | boards[board_idx].status = ENABLED; | 3045 | boards[board_idx].status = ENABLED; |
3712 | boards[board_idx].type = epca_info_tbl[info_idx].board_type; | 3046 | boards[board_idx].type = epca_info_tbl[info_idx].board_type; |
3713 | boards[board_idx].numports = 0x0; | 3047 | boards[board_idx].numports = 0x0; |
3714 | boards[board_idx].port = | 3048 | boards[board_idx].port = addr + PCI_IO_OFFSET; |
3715 | (unsigned char *)((char *) addr + PCI_IO_OFFSET); | 3049 | boards[board_idx].membase = addr; |
3716 | boards[board_idx].membase = | ||
3717 | (unsigned char *)((char *) addr); | ||
3718 | 3050 | ||
3719 | if (!request_mem_region (addr + PCI_IO_OFFSET, 0x200000, "epca")) { | 3051 | if (!request_mem_region (addr + PCI_IO_OFFSET, 0x200000, "epca")) { |
3720 | printk (KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n", | 3052 | printk (KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n", |
@@ -3775,15 +3107,13 @@ static struct pci_device_id epca_pci_tbl[] = { | |||
3775 | MODULE_DEVICE_TABLE(pci, epca_pci_tbl); | 3107 | MODULE_DEVICE_TABLE(pci, epca_pci_tbl); |
3776 | 3108 | ||
3777 | int __init init_PCI (void) | 3109 | int __init init_PCI (void) |
3778 | { /* Begin init_PCI */ | 3110 | { /* Begin init_PCI */ |
3779 | memset (&epca_driver, 0, sizeof (epca_driver)); | 3111 | memset (&epca_driver, 0, sizeof (epca_driver)); |
3780 | epca_driver.name = "epca"; | 3112 | epca_driver.name = "epca"; |
3781 | epca_driver.id_table = epca_pci_tbl; | 3113 | epca_driver.id_table = epca_pci_tbl; |
3782 | epca_driver.probe = epca_init_one; | 3114 | epca_driver.probe = epca_init_one; |
3783 | 3115 | ||
3784 | return pci_register_driver(&epca_driver); | 3116 | return pci_register_driver(&epca_driver); |
3785 | } /* End init_PCI */ | 3117 | } |
3786 | |||
3787 | #endif /* ENABLE_PCI */ | ||
3788 | 3118 | ||
3789 | MODULE_LICENSE("GPL"); | 3119 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/epca.h b/drivers/char/epca.h index 52205ef71314..20eeb5a70e1a 100644 --- a/drivers/char/epca.h +++ b/drivers/char/epca.h | |||
@@ -85,73 +85,73 @@ static char *board_desc[] = | |||
85 | struct channel | 85 | struct channel |
86 | { | 86 | { |
87 | long magic; | 87 | long magic; |
88 | unchar boardnum; | 88 | unsigned char boardnum; |
89 | unchar channelnum; | 89 | unsigned char channelnum; |
90 | unchar omodem; /* FEP output modem status */ | 90 | unsigned char omodem; /* FEP output modem status */ |
91 | unchar imodem; /* FEP input modem status */ | 91 | unsigned char imodem; /* FEP input modem status */ |
92 | unchar modemfake; /* Modem values to be forced */ | 92 | unsigned char modemfake; /* Modem values to be forced */ |
93 | unchar modem; /* Force values */ | 93 | unsigned char modem; /* Force values */ |
94 | unchar hflow; | 94 | unsigned char hflow; |
95 | unchar dsr; | 95 | unsigned char dsr; |
96 | unchar dcd; | 96 | unsigned char dcd; |
97 | unchar m_rts ; /* The bits used in whatever FEP */ | 97 | unsigned char m_rts ; /* The bits used in whatever FEP */ |
98 | unchar m_dcd ; /* is indiginous to this board to */ | 98 | unsigned char m_dcd ; /* is indiginous to this board to */ |
99 | unchar m_dsr ; /* represent each of the physical */ | 99 | unsigned char m_dsr ; /* represent each of the physical */ |
100 | unchar m_cts ; /* handshake lines */ | 100 | unsigned char m_cts ; /* handshake lines */ |
101 | unchar m_ri ; | 101 | unsigned char m_ri ; |
102 | unchar m_dtr ; | 102 | unsigned char m_dtr ; |
103 | unchar stopc; | 103 | unsigned char stopc; |
104 | unchar startc; | 104 | unsigned char startc; |
105 | unchar stopca; | 105 | unsigned char stopca; |
106 | unchar startca; | 106 | unsigned char startca; |
107 | unchar fepstopc; | 107 | unsigned char fepstopc; |
108 | unchar fepstartc; | 108 | unsigned char fepstartc; |
109 | unchar fepstopca; | 109 | unsigned char fepstopca; |
110 | unchar fepstartca; | 110 | unsigned char fepstartca; |
111 | unchar txwin; | 111 | unsigned char txwin; |
112 | unchar rxwin; | 112 | unsigned char rxwin; |
113 | ushort fepiflag; | 113 | unsigned short fepiflag; |
114 | ushort fepcflag; | 114 | unsigned short fepcflag; |
115 | ushort fepoflag; | 115 | unsigned short fepoflag; |
116 | ushort txbufhead; | 116 | unsigned short txbufhead; |
117 | ushort txbufsize; | 117 | unsigned short txbufsize; |
118 | ushort rxbufhead; | 118 | unsigned short rxbufhead; |
119 | ushort rxbufsize; | 119 | unsigned short rxbufsize; |
120 | int close_delay; | 120 | int close_delay; |
121 | int count; | 121 | int count; |
122 | int blocked_open; | 122 | int blocked_open; |
123 | ulong event; | 123 | unsigned long event; |
124 | int asyncflags; | 124 | int asyncflags; |
125 | uint dev; | 125 | uint dev; |
126 | ulong statusflags; | 126 | unsigned long statusflags; |
127 | ulong c_iflag; | 127 | unsigned long c_iflag; |
128 | ulong c_cflag; | 128 | unsigned long c_cflag; |
129 | ulong c_lflag; | 129 | unsigned long c_lflag; |
130 | ulong c_oflag; | 130 | unsigned long c_oflag; |
131 | unchar *txptr; | 131 | unsigned char *txptr; |
132 | unchar *rxptr; | 132 | unsigned char *rxptr; |
133 | unchar *tmp_buf; | 133 | unsigned char *tmp_buf; |
134 | struct board_info *board; | 134 | struct board_info *board; |
135 | volatile struct board_chan *brdchan; | 135 | struct board_chan *brdchan; |
136 | struct digi_struct digiext; | 136 | struct digi_struct digiext; |
137 | struct tty_struct *tty; | 137 | struct tty_struct *tty; |
138 | wait_queue_head_t open_wait; | 138 | wait_queue_head_t open_wait; |
139 | wait_queue_head_t close_wait; | 139 | wait_queue_head_t close_wait; |
140 | struct work_struct tqueue; | 140 | struct work_struct tqueue; |
141 | volatile struct global_data *mailbox; | 141 | struct global_data *mailbox; |
142 | }; | 142 | }; |
143 | 143 | ||
144 | struct board_info | 144 | struct board_info |
145 | { | 145 | { |
146 | unchar status; | 146 | unsigned char status; |
147 | unchar type; | 147 | unsigned char type; |
148 | unchar altpin; | 148 | unsigned char altpin; |
149 | ushort numports; | 149 | unsigned short numports; |
150 | unchar *port; | 150 | unsigned long port; |
151 | unchar *membase; | 151 | unsigned long membase; |
152 | unchar __iomem *re_map_port; | 152 | unsigned char __iomem *re_map_port; |
153 | unchar *re_map_membase; | 153 | unsigned char *re_map_membase; |
154 | ulong memory_seg; | 154 | unsigned long memory_seg; |
155 | void ( * memwinon ) (struct board_info *, unsigned int) ; | 155 | void ( * memwinon ) (struct board_info *, unsigned int) ; |
156 | void ( * memwinoff ) (struct board_info *, unsigned int) ; | 156 | void ( * memwinoff ) (struct board_info *, unsigned int) ; |
157 | void ( * globalwinon ) (struct channel *) ; | 157 | void ( * globalwinon ) (struct channel *) ; |
@@ -160,6 +160,6 @@ struct board_info | |||
160 | void ( * memoff ) (struct channel *) ; | 160 | void ( * memoff ) (struct channel *) ; |
161 | void ( * assertgwinon ) (struct channel *) ; | 161 | void ( * assertgwinon ) (struct channel *) ; |
162 | void ( * assertmemoff ) (struct channel *) ; | 162 | void ( * assertmemoff ) (struct channel *) ; |
163 | unchar poller_inhibited ; | 163 | unsigned char poller_inhibited ; |
164 | }; | 164 | }; |
165 | 165 | ||
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 762fa430fb5b..a695f25e4497 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
@@ -44,7 +44,7 @@ | |||
44 | /* | 44 | /* |
45 | * The High Precision Event Timer driver. | 45 | * The High Precision Event Timer driver. |
46 | * This driver is closely modelled after the rtc.c driver. | 46 | * This driver is closely modelled after the rtc.c driver. |
47 | * http://www.intel.com/labs/platcomp/hpet/hpetspec.htm | 47 | * http://www.intel.com/hardwaredesign/hpetspec.htm |
48 | */ | 48 | */ |
49 | #define HPET_USER_FREQ (64) | 49 | #define HPET_USER_FREQ (64) |
50 | #define HPET_DRIFT (500) | 50 | #define HPET_DRIFT (500) |
@@ -712,7 +712,7 @@ static void hpet_register_interpolator(struct hpets *hpetp) | |||
712 | ti->shift = 10; | 712 | ti->shift = 10; |
713 | ti->addr = &hpetp->hp_hpet->hpet_mc; | 713 | ti->addr = &hpetp->hp_hpet->hpet_mc; |
714 | ti->frequency = hpet_time_div(hpets->hp_period); | 714 | ti->frequency = hpet_time_div(hpets->hp_period); |
715 | ti->drift = ti->frequency * HPET_DRIFT / 1000000; | 715 | ti->drift = HPET_DRIFT; |
716 | ti->mask = -1; | 716 | ti->mask = -1; |
717 | 717 | ||
718 | hpetp->hp_interpolator = ti; | 718 | hpetp->hp_interpolator = ti; |
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index 5ce9c6269033..33862670e285 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c | |||
@@ -31,8 +31,6 @@ | |||
31 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ | 31 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ |
32 | #include "ipmi_si_sm.h" | 32 | #include "ipmi_si_sm.h" |
33 | 33 | ||
34 | #define IPMI_BT_VERSION "v33" | ||
35 | |||
36 | static int bt_debug = 0x00; /* Production value 0, see following flags */ | 34 | static int bt_debug = 0x00; /* Production value 0, see following flags */ |
37 | 35 | ||
38 | #define BT_DEBUG_ENABLE 1 | 36 | #define BT_DEBUG_ENABLE 1 |
@@ -163,7 +161,8 @@ static int bt_start_transaction(struct si_sm_data *bt, | |||
163 | { | 161 | { |
164 | unsigned int i; | 162 | unsigned int i; |
165 | 163 | ||
166 | if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH)) return -1; | 164 | if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH)) |
165 | return -1; | ||
167 | 166 | ||
168 | if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED)) | 167 | if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED)) |
169 | return -2; | 168 | return -2; |
@@ -171,7 +170,8 @@ static int bt_start_transaction(struct si_sm_data *bt, | |||
171 | if (bt_debug & BT_DEBUG_MSG) { | 170 | if (bt_debug & BT_DEBUG_MSG) { |
172 | printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n"); | 171 | printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n"); |
173 | printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq); | 172 | printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq); |
174 | for (i = 0; i < size; i ++) printk (" %02x", data[i]); | 173 | for (i = 0; i < size; i ++) |
174 | printk (" %02x", data[i]); | ||
175 | printk("\n"); | 175 | printk("\n"); |
176 | } | 176 | } |
177 | bt->write_data[0] = size + 1; /* all data plus seq byte */ | 177 | bt->write_data[0] = size + 1; /* all data plus seq byte */ |
@@ -210,15 +210,18 @@ static int bt_get_result(struct si_sm_data *bt, | |||
210 | } else { | 210 | } else { |
211 | data[0] = bt->read_data[1]; | 211 | data[0] = bt->read_data[1]; |
212 | data[1] = bt->read_data[3]; | 212 | data[1] = bt->read_data[3]; |
213 | if (length < msg_len) bt->truncated = 1; | 213 | if (length < msg_len) |
214 | bt->truncated = 1; | ||
214 | if (bt->truncated) { /* can be set in read_all_bytes() */ | 215 | if (bt->truncated) { /* can be set in read_all_bytes() */ |
215 | data[2] = IPMI_ERR_MSG_TRUNCATED; | 216 | data[2] = IPMI_ERR_MSG_TRUNCATED; |
216 | msg_len = 3; | 217 | msg_len = 3; |
217 | } else memcpy(data + 2, bt->read_data + 4, msg_len - 2); | 218 | } else |
219 | memcpy(data + 2, bt->read_data + 4, msg_len - 2); | ||
218 | 220 | ||
219 | if (bt_debug & BT_DEBUG_MSG) { | 221 | if (bt_debug & BT_DEBUG_MSG) { |
220 | printk (KERN_WARNING "BT: res (raw)"); | 222 | printk (KERN_WARNING "BT: res (raw)"); |
221 | for (i = 0; i < msg_len; i++) printk(" %02x", data[i]); | 223 | for (i = 0; i < msg_len; i++) |
224 | printk(" %02x", data[i]); | ||
222 | printk ("\n"); | 225 | printk ("\n"); |
223 | } | 226 | } |
224 | } | 227 | } |
@@ -231,8 +234,10 @@ static int bt_get_result(struct si_sm_data *bt, | |||
231 | 234 | ||
232 | static void reset_flags(struct si_sm_data *bt) | 235 | static void reset_flags(struct si_sm_data *bt) |
233 | { | 236 | { |
234 | if (BT_STATUS & BT_H_BUSY) BT_CONTROL(BT_H_BUSY); | 237 | if (BT_STATUS & BT_H_BUSY) |
235 | if (BT_STATUS & BT_B_BUSY) BT_CONTROL(BT_B_BUSY); | 238 | BT_CONTROL(BT_H_BUSY); |
239 | if (BT_STATUS & BT_B_BUSY) | ||
240 | BT_CONTROL(BT_B_BUSY); | ||
236 | BT_CONTROL(BT_CLR_WR_PTR); | 241 | BT_CONTROL(BT_CLR_WR_PTR); |
237 | BT_CONTROL(BT_SMS_ATN); | 242 | BT_CONTROL(BT_SMS_ATN); |
238 | #ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION | 243 | #ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION |
@@ -241,7 +246,8 @@ static void reset_flags(struct si_sm_data *bt) | |||
241 | BT_CONTROL(BT_H_BUSY); | 246 | BT_CONTROL(BT_H_BUSY); |
242 | BT_CONTROL(BT_B2H_ATN); | 247 | BT_CONTROL(BT_B2H_ATN); |
243 | BT_CONTROL(BT_CLR_RD_PTR); | 248 | BT_CONTROL(BT_CLR_RD_PTR); |
244 | for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++) BMC2HOST; | 249 | for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++) |
250 | BMC2HOST; | ||
245 | BT_CONTROL(BT_H_BUSY); | 251 | BT_CONTROL(BT_H_BUSY); |
246 | } | 252 | } |
247 | #endif | 253 | #endif |
@@ -258,7 +264,8 @@ static inline void write_all_bytes(struct si_sm_data *bt) | |||
258 | printk (" %02x", bt->write_data[i]); | 264 | printk (" %02x", bt->write_data[i]); |
259 | printk ("\n"); | 265 | printk ("\n"); |
260 | } | 266 | } |
261 | for (i = 0; i < bt->write_count; i++) HOST2BMC(bt->write_data[i]); | 267 | for (i = 0; i < bt->write_count; i++) |
268 | HOST2BMC(bt->write_data[i]); | ||
262 | } | 269 | } |
263 | 270 | ||
264 | static inline int read_all_bytes(struct si_sm_data *bt) | 271 | static inline int read_all_bytes(struct si_sm_data *bt) |
@@ -278,7 +285,8 @@ static inline int read_all_bytes(struct si_sm_data *bt) | |||
278 | bt->truncated = 1; | 285 | bt->truncated = 1; |
279 | return 1; /* let next XACTION START clean it up */ | 286 | return 1; /* let next XACTION START clean it up */ |
280 | } | 287 | } |
281 | for (i = 1; i <= bt->read_count; i++) bt->read_data[i] = BMC2HOST; | 288 | for (i = 1; i <= bt->read_count; i++) |
289 | bt->read_data[i] = BMC2HOST; | ||
282 | bt->read_count++; /* account for the length byte */ | 290 | bt->read_count++; /* account for the length byte */ |
283 | 291 | ||
284 | if (bt_debug & BT_DEBUG_MSG) { | 292 | if (bt_debug & BT_DEBUG_MSG) { |
@@ -295,7 +303,8 @@ static inline int read_all_bytes(struct si_sm_data *bt) | |||
295 | ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8))) | 303 | ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8))) |
296 | return 1; | 304 | return 1; |
297 | 305 | ||
298 | if (bt_debug & BT_DEBUG_MSG) printk(KERN_WARNING "BT: bad packet: " | 306 | if (bt_debug & BT_DEBUG_MSG) |
307 | printk(KERN_WARNING "BT: bad packet: " | ||
299 | "want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n", | 308 | "want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n", |
300 | bt->write_data[1], bt->write_data[2], bt->write_data[3], | 309 | bt->write_data[1], bt->write_data[2], bt->write_data[3], |
301 | bt->read_data[1], bt->read_data[2], bt->read_data[3]); | 310 | bt->read_data[1], bt->read_data[2], bt->read_data[3]); |
@@ -359,7 +368,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
359 | time); | 368 | time); |
360 | bt->last_state = bt->state; | 369 | bt->last_state = bt->state; |
361 | 370 | ||
362 | if (bt->state == BT_STATE_HOSED) return SI_SM_HOSED; | 371 | if (bt->state == BT_STATE_HOSED) |
372 | return SI_SM_HOSED; | ||
363 | 373 | ||
364 | if (bt->state != BT_STATE_IDLE) { /* do timeout test */ | 374 | if (bt->state != BT_STATE_IDLE) { /* do timeout test */ |
365 | 375 | ||
@@ -371,7 +381,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
371 | /* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT | 381 | /* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT |
372 | (noticed in ipmi_smic_sm.c January 2004) */ | 382 | (noticed in ipmi_smic_sm.c January 2004) */ |
373 | 383 | ||
374 | if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) time = 100; | 384 | if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) |
385 | time = 100; | ||
375 | bt->timeout -= time; | 386 | bt->timeout -= time; |
376 | if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) { | 387 | if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) { |
377 | error_recovery(bt, "timed out"); | 388 | error_recovery(bt, "timed out"); |
@@ -393,12 +404,14 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
393 | BT_CONTROL(BT_H_BUSY); | 404 | BT_CONTROL(BT_H_BUSY); |
394 | break; | 405 | break; |
395 | } | 406 | } |
396 | if (status & BT_B2H_ATN) break; | 407 | if (status & BT_B2H_ATN) |
408 | break; | ||
397 | bt->state = BT_STATE_WRITE_BYTES; | 409 | bt->state = BT_STATE_WRITE_BYTES; |
398 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ | 410 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ |
399 | 411 | ||
400 | case BT_STATE_WRITE_BYTES: | 412 | case BT_STATE_WRITE_BYTES: |
401 | if (status & (BT_B_BUSY | BT_H2B_ATN)) break; | 413 | if (status & (BT_B_BUSY | BT_H2B_ATN)) |
414 | break; | ||
402 | BT_CONTROL(BT_CLR_WR_PTR); | 415 | BT_CONTROL(BT_CLR_WR_PTR); |
403 | write_all_bytes(bt); | 416 | write_all_bytes(bt); |
404 | BT_CONTROL(BT_H2B_ATN); /* clears too fast to catch? */ | 417 | BT_CONTROL(BT_H2B_ATN); /* clears too fast to catch? */ |
@@ -406,7 +419,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
406 | return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */ | 419 | return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */ |
407 | 420 | ||
408 | case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */ | 421 | case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */ |
409 | if (status & (BT_H2B_ATN | BT_B_BUSY)) break; | 422 | if (status & (BT_H2B_ATN | BT_B_BUSY)) |
423 | break; | ||
410 | bt->state = BT_STATE_B2H_WAIT; | 424 | bt->state = BT_STATE_B2H_WAIT; |
411 | /* fall through with status */ | 425 | /* fall through with status */ |
412 | 426 | ||
@@ -415,15 +429,18 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
415 | generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */ | 429 | generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */ |
416 | 430 | ||
417 | case BT_STATE_B2H_WAIT: | 431 | case BT_STATE_B2H_WAIT: |
418 | if (!(status & BT_B2H_ATN)) break; | 432 | if (!(status & BT_B2H_ATN)) |
433 | break; | ||
419 | 434 | ||
420 | /* Assume ordered, uncached writes: no need to wait */ | 435 | /* Assume ordered, uncached writes: no need to wait */ |
421 | if (!(status & BT_H_BUSY)) BT_CONTROL(BT_H_BUSY); /* set */ | 436 | if (!(status & BT_H_BUSY)) |
437 | BT_CONTROL(BT_H_BUSY); /* set */ | ||
422 | BT_CONTROL(BT_B2H_ATN); /* clear it, ACK to the BMC */ | 438 | BT_CONTROL(BT_B2H_ATN); /* clear it, ACK to the BMC */ |
423 | BT_CONTROL(BT_CLR_RD_PTR); /* reset the queue */ | 439 | BT_CONTROL(BT_CLR_RD_PTR); /* reset the queue */ |
424 | i = read_all_bytes(bt); | 440 | i = read_all_bytes(bt); |
425 | BT_CONTROL(BT_H_BUSY); /* clear */ | 441 | BT_CONTROL(BT_H_BUSY); /* clear */ |
426 | if (!i) break; /* Try this state again */ | 442 | if (!i) /* Try this state again */ |
443 | break; | ||
427 | bt->state = BT_STATE_READ_END; | 444 | bt->state = BT_STATE_READ_END; |
428 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ | 445 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ |
429 | 446 | ||
@@ -436,7 +453,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
436 | 453 | ||
437 | #ifdef MAKE_THIS_TRUE_IF_NECESSARY | 454 | #ifdef MAKE_THIS_TRUE_IF_NECESSARY |
438 | 455 | ||
439 | if (status & BT_H_BUSY) break; | 456 | if (status & BT_H_BUSY) |
457 | break; | ||
440 | #endif | 458 | #endif |
441 | bt->seq++; | 459 | bt->seq++; |
442 | bt->state = BT_STATE_IDLE; | 460 | bt->state = BT_STATE_IDLE; |
@@ -459,7 +477,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
459 | break; | 477 | break; |
460 | 478 | ||
461 | case BT_STATE_RESET3: | 479 | case BT_STATE_RESET3: |
462 | if (bt->timeout > 0) return SI_SM_CALL_WITH_DELAY; | 480 | if (bt->timeout > 0) |
481 | return SI_SM_CALL_WITH_DELAY; | ||
463 | bt->state = BT_STATE_RESTART; /* printk in debug modes */ | 482 | bt->state = BT_STATE_RESTART; /* printk in debug modes */ |
464 | break; | 483 | break; |
465 | 484 | ||
@@ -485,7 +504,8 @@ static int bt_detect(struct si_sm_data *bt) | |||
485 | but that's what you get from reading a bogus address, so we | 504 | but that's what you get from reading a bogus address, so we |
486 | test that first. The calling routine uses negative logic. */ | 505 | test that first. The calling routine uses negative logic. */ |
487 | 506 | ||
488 | if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) return 1; | 507 | if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) |
508 | return 1; | ||
489 | reset_flags(bt); | 509 | reset_flags(bt); |
490 | return 0; | 510 | return 0; |
491 | } | 511 | } |
@@ -501,7 +521,6 @@ static int bt_size(void) | |||
501 | 521 | ||
502 | struct si_sm_handlers bt_smi_handlers = | 522 | struct si_sm_handlers bt_smi_handlers = |
503 | { | 523 | { |
504 | .version = IPMI_BT_VERSION, | ||
505 | .init_data = bt_init_data, | 524 | .init_data = bt_init_data, |
506 | .start_transaction = bt_start_transaction, | 525 | .start_transaction = bt_start_transaction, |
507 | .get_result = bt_get_result, | 526 | .get_result = bt_get_result, |
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index e0a53570fea1..883ac4352be4 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c | |||
@@ -47,8 +47,6 @@ | |||
47 | #include <linux/device.h> | 47 | #include <linux/device.h> |
48 | #include <linux/compat.h> | 48 | #include <linux/compat.h> |
49 | 49 | ||
50 | #define IPMI_DEVINTF_VERSION "v33" | ||
51 | |||
52 | struct ipmi_file_private | 50 | struct ipmi_file_private |
53 | { | 51 | { |
54 | ipmi_user_t user; | 52 | ipmi_user_t user; |
@@ -411,6 +409,7 @@ static int ipmi_ioctl(struct inode *inode, | |||
411 | break; | 409 | break; |
412 | } | 410 | } |
413 | 411 | ||
412 | /* The next four are legacy, not per-channel. */ | ||
414 | case IPMICTL_SET_MY_ADDRESS_CMD: | 413 | case IPMICTL_SET_MY_ADDRESS_CMD: |
415 | { | 414 | { |
416 | unsigned int val; | 415 | unsigned int val; |
@@ -420,22 +419,25 @@ static int ipmi_ioctl(struct inode *inode, | |||
420 | break; | 419 | break; |
421 | } | 420 | } |
422 | 421 | ||
423 | ipmi_set_my_address(priv->user, val); | 422 | rv = ipmi_set_my_address(priv->user, 0, val); |
424 | rv = 0; | ||
425 | break; | 423 | break; |
426 | } | 424 | } |
427 | 425 | ||
428 | case IPMICTL_GET_MY_ADDRESS_CMD: | 426 | case IPMICTL_GET_MY_ADDRESS_CMD: |
429 | { | 427 | { |
430 | unsigned int val; | 428 | unsigned int val; |
429 | unsigned char rval; | ||
430 | |||
431 | rv = ipmi_get_my_address(priv->user, 0, &rval); | ||
432 | if (rv) | ||
433 | break; | ||
431 | 434 | ||
432 | val = ipmi_get_my_address(priv->user); | 435 | val = rval; |
433 | 436 | ||
434 | if (copy_to_user(arg, &val, sizeof(val))) { | 437 | if (copy_to_user(arg, &val, sizeof(val))) { |
435 | rv = -EFAULT; | 438 | rv = -EFAULT; |
436 | break; | 439 | break; |
437 | } | 440 | } |
438 | rv = 0; | ||
439 | break; | 441 | break; |
440 | } | 442 | } |
441 | 443 | ||
@@ -448,24 +450,94 @@ static int ipmi_ioctl(struct inode *inode, | |||
448 | break; | 450 | break; |
449 | } | 451 | } |
450 | 452 | ||
451 | ipmi_set_my_LUN(priv->user, val); | 453 | rv = ipmi_set_my_LUN(priv->user, 0, val); |
452 | rv = 0; | ||
453 | break; | 454 | break; |
454 | } | 455 | } |
455 | 456 | ||
456 | case IPMICTL_GET_MY_LUN_CMD: | 457 | case IPMICTL_GET_MY_LUN_CMD: |
457 | { | 458 | { |
458 | unsigned int val; | 459 | unsigned int val; |
460 | unsigned char rval; | ||
459 | 461 | ||
460 | val = ipmi_get_my_LUN(priv->user); | 462 | rv = ipmi_get_my_LUN(priv->user, 0, &rval); |
463 | if (rv) | ||
464 | break; | ||
465 | |||
466 | val = rval; | ||
467 | |||
468 | if (copy_to_user(arg, &val, sizeof(val))) { | ||
469 | rv = -EFAULT; | ||
470 | break; | ||
471 | } | ||
472 | break; | ||
473 | } | ||
474 | |||
475 | case IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD: | ||
476 | { | ||
477 | struct ipmi_channel_lun_address_set val; | ||
478 | |||
479 | if (copy_from_user(&val, arg, sizeof(val))) { | ||
480 | rv = -EFAULT; | ||
481 | break; | ||
482 | } | ||
483 | |||
484 | return ipmi_set_my_address(priv->user, val.channel, val.value); | ||
485 | break; | ||
486 | } | ||
487 | |||
488 | case IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD: | ||
489 | { | ||
490 | struct ipmi_channel_lun_address_set val; | ||
491 | |||
492 | if (copy_from_user(&val, arg, sizeof(val))) { | ||
493 | rv = -EFAULT; | ||
494 | break; | ||
495 | } | ||
496 | |||
497 | rv = ipmi_get_my_address(priv->user, val.channel, &val.value); | ||
498 | if (rv) | ||
499 | break; | ||
500 | |||
501 | if (copy_to_user(arg, &val, sizeof(val))) { | ||
502 | rv = -EFAULT; | ||
503 | break; | ||
504 | } | ||
505 | break; | ||
506 | } | ||
507 | |||
508 | case IPMICTL_SET_MY_CHANNEL_LUN_CMD: | ||
509 | { | ||
510 | struct ipmi_channel_lun_address_set val; | ||
511 | |||
512 | if (copy_from_user(&val, arg, sizeof(val))) { | ||
513 | rv = -EFAULT; | ||
514 | break; | ||
515 | } | ||
516 | |||
517 | rv = ipmi_set_my_LUN(priv->user, val.channel, val.value); | ||
518 | break; | ||
519 | } | ||
520 | |||
521 | case IPMICTL_GET_MY_CHANNEL_LUN_CMD: | ||
522 | { | ||
523 | struct ipmi_channel_lun_address_set val; | ||
524 | |||
525 | if (copy_from_user(&val, arg, sizeof(val))) { | ||
526 | rv = -EFAULT; | ||
527 | break; | ||
528 | } | ||
529 | |||
530 | rv = ipmi_get_my_LUN(priv->user, val.channel, &val.value); | ||
531 | if (rv) | ||
532 | break; | ||
461 | 533 | ||
462 | if (copy_to_user(arg, &val, sizeof(val))) { | 534 | if (copy_to_user(arg, &val, sizeof(val))) { |
463 | rv = -EFAULT; | 535 | rv = -EFAULT; |
464 | break; | 536 | break; |
465 | } | 537 | } |
466 | rv = 0; | ||
467 | break; | 538 | break; |
468 | } | 539 | } |
540 | |||
469 | case IPMICTL_SET_TIMING_PARMS_CMD: | 541 | case IPMICTL_SET_TIMING_PARMS_CMD: |
470 | { | 542 | { |
471 | struct ipmi_timing_parms parms; | 543 | struct ipmi_timing_parms parms; |
@@ -748,8 +820,7 @@ static __init int init_ipmi_devintf(void) | |||
748 | if (ipmi_major < 0) | 820 | if (ipmi_major < 0) |
749 | return -EINVAL; | 821 | return -EINVAL; |
750 | 822 | ||
751 | printk(KERN_INFO "ipmi device interface version " | 823 | printk(KERN_INFO "ipmi device interface\n"); |
752 | IPMI_DEVINTF_VERSION "\n"); | ||
753 | 824 | ||
754 | ipmi_class = class_create(THIS_MODULE, "ipmi"); | 825 | ipmi_class = class_create(THIS_MODULE, "ipmi"); |
755 | if (IS_ERR(ipmi_class)) { | 826 | if (IS_ERR(ipmi_class)) { |
@@ -792,3 +863,5 @@ static __exit void cleanup_ipmi(void) | |||
792 | module_exit(cleanup_ipmi); | 863 | module_exit(cleanup_ipmi); |
793 | 864 | ||
794 | MODULE_LICENSE("GPL"); | 865 | MODULE_LICENSE("GPL"); |
866 | MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); | ||
867 | MODULE_DESCRIPTION("Linux device interface for the IPMI message handler."); | ||
diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c index 48cce24329be..d21853a594a3 100644 --- a/drivers/char/ipmi/ipmi_kcs_sm.c +++ b/drivers/char/ipmi/ipmi_kcs_sm.c | |||
@@ -42,8 +42,6 @@ | |||
42 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ | 42 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ |
43 | #include "ipmi_si_sm.h" | 43 | #include "ipmi_si_sm.h" |
44 | 44 | ||
45 | #define IPMI_KCS_VERSION "v33" | ||
46 | |||
47 | /* Set this if you want a printout of why the state machine was hosed | 45 | /* Set this if you want a printout of why the state machine was hosed |
48 | when it gets hosed. */ | 46 | when it gets hosed. */ |
49 | #define DEBUG_HOSED_REASON | 47 | #define DEBUG_HOSED_REASON |
@@ -489,7 +487,6 @@ static void kcs_cleanup(struct si_sm_data *kcs) | |||
489 | 487 | ||
490 | struct si_sm_handlers kcs_smi_handlers = | 488 | struct si_sm_handlers kcs_smi_handlers = |
491 | { | 489 | { |
492 | .version = IPMI_KCS_VERSION, | ||
493 | .init_data = init_kcs_data, | 490 | .init_data = init_kcs_data, |
494 | .start_transaction = start_kcs_transaction, | 491 | .start_transaction = start_kcs_transaction, |
495 | .get_result = get_kcs_result, | 492 | .get_result = get_kcs_result, |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index e16c13fe698d..463351d4f942 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -47,7 +47,8 @@ | |||
47 | #include <linux/proc_fs.h> | 47 | #include <linux/proc_fs.h> |
48 | 48 | ||
49 | #define PFX "IPMI message handler: " | 49 | #define PFX "IPMI message handler: " |
50 | #define IPMI_MSGHANDLER_VERSION "v33" | 50 | |
51 | #define IPMI_DRIVER_VERSION "36.0" | ||
51 | 52 | ||
52 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); | 53 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); |
53 | static int ipmi_init_msghandler(void); | 54 | static int ipmi_init_msghandler(void); |
@@ -116,7 +117,7 @@ struct seq_table | |||
116 | do { \ | 117 | do { \ |
117 | seq = ((msgid >> 26) & 0x3f); \ | 118 | seq = ((msgid >> 26) & 0x3f); \ |
118 | seqid = (msgid & 0x3fffff); \ | 119 | seqid = (msgid & 0x3fffff); \ |
119 | } while(0) | 120 | } while (0) |
120 | 121 | ||
121 | #define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3fffff) | 122 | #define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3fffff) |
122 | 123 | ||
@@ -124,6 +125,14 @@ struct ipmi_channel | |||
124 | { | 125 | { |
125 | unsigned char medium; | 126 | unsigned char medium; |
126 | unsigned char protocol; | 127 | unsigned char protocol; |
128 | |||
129 | /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR, | ||
130 | but may be changed by the user. */ | ||
131 | unsigned char address; | ||
132 | |||
133 | /* My LUN. This should generally stay the SMS LUN, but just in | ||
134 | case... */ | ||
135 | unsigned char lun; | ||
127 | }; | 136 | }; |
128 | 137 | ||
129 | #ifdef CONFIG_PROC_FS | 138 | #ifdef CONFIG_PROC_FS |
@@ -135,7 +144,7 @@ struct ipmi_proc_entry | |||
135 | #endif | 144 | #endif |
136 | 145 | ||
137 | #define IPMI_IPMB_NUM_SEQ 64 | 146 | #define IPMI_IPMB_NUM_SEQ 64 |
138 | #define IPMI_MAX_CHANNELS 8 | 147 | #define IPMI_MAX_CHANNELS 16 |
139 | struct ipmi_smi | 148 | struct ipmi_smi |
140 | { | 149 | { |
141 | /* What interface number are we? */ | 150 | /* What interface number are we? */ |
@@ -193,20 +202,6 @@ struct ipmi_smi | |||
193 | struct list_head waiting_events; | 202 | struct list_head waiting_events; |
194 | unsigned int waiting_events_count; /* How many events in queue? */ | 203 | unsigned int waiting_events_count; /* How many events in queue? */ |
195 | 204 | ||
196 | /* This will be non-null if someone registers to receive all | ||
197 | IPMI commands (this is for interface emulation). There | ||
198 | may not be any things in the cmd_rcvrs list above when | ||
199 | this is registered. */ | ||
200 | ipmi_user_t all_cmd_rcvr; | ||
201 | |||
202 | /* My slave address. This is initialized to IPMI_BMC_SLAVE_ADDR, | ||
203 | but may be changed by the user. */ | ||
204 | unsigned char my_address; | ||
205 | |||
206 | /* My LUN. This should generally stay the SMS LUN, but just in | ||
207 | case... */ | ||
208 | unsigned char my_lun; | ||
209 | |||
210 | /* The event receiver for my BMC, only really used at panic | 205 | /* The event receiver for my BMC, only really used at panic |
211 | shutdown as a place to store this. */ | 206 | shutdown as a place to store this. */ |
212 | unsigned char event_receiver; | 207 | unsigned char event_receiver; |
@@ -218,7 +213,7 @@ struct ipmi_smi | |||
218 | interface comes in with a NULL user, call this routine with | 213 | interface comes in with a NULL user, call this routine with |
219 | it. Note that the message will still be freed by the | 214 | it. Note that the message will still be freed by the |
220 | caller. This only works on the system interface. */ | 215 | caller. This only works on the system interface. */ |
221 | void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_smi_msg *msg); | 216 | void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_recv_msg *msg); |
222 | 217 | ||
223 | /* When we are scanning the channels for an SMI, this will | 218 | /* When we are scanning the channels for an SMI, this will |
224 | tell which channel we are scanning. */ | 219 | tell which channel we are scanning. */ |
@@ -325,7 +320,7 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) | |||
325 | down_read(&interfaces_sem); | 320 | down_read(&interfaces_sem); |
326 | down_write(&smi_watchers_sem); | 321 | down_write(&smi_watchers_sem); |
327 | list_add(&(watcher->link), &smi_watchers); | 322 | list_add(&(watcher->link), &smi_watchers); |
328 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 323 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
329 | if (ipmi_interfaces[i] != NULL) { | 324 | if (ipmi_interfaces[i] != NULL) { |
330 | watcher->new_smi(i); | 325 | watcher->new_smi(i); |
331 | } | 326 | } |
@@ -458,7 +453,27 @@ unsigned int ipmi_addr_length(int addr_type) | |||
458 | 453 | ||
459 | static void deliver_response(struct ipmi_recv_msg *msg) | 454 | static void deliver_response(struct ipmi_recv_msg *msg) |
460 | { | 455 | { |
461 | msg->user->handler->ipmi_recv_hndl(msg, msg->user->handler_data); | 456 | if (! msg->user) { |
457 | ipmi_smi_t intf = msg->user_msg_data; | ||
458 | unsigned long flags; | ||
459 | |||
460 | /* Special handling for NULL users. */ | ||
461 | if (intf->null_user_handler) { | ||
462 | intf->null_user_handler(intf, msg); | ||
463 | spin_lock_irqsave(&intf->counter_lock, flags); | ||
464 | intf->handled_local_responses++; | ||
465 | spin_unlock_irqrestore(&intf->counter_lock, flags); | ||
466 | } else { | ||
467 | /* No handler, so give up. */ | ||
468 | spin_lock_irqsave(&intf->counter_lock, flags); | ||
469 | intf->unhandled_local_responses++; | ||
470 | spin_unlock_irqrestore(&intf->counter_lock, flags); | ||
471 | } | ||
472 | ipmi_free_recv_msg(msg); | ||
473 | } else { | ||
474 | msg->user->handler->ipmi_recv_hndl(msg, | ||
475 | msg->user->handler_data); | ||
476 | } | ||
462 | } | 477 | } |
463 | 478 | ||
464 | /* Find the next sequence number not being used and add the given | 479 | /* Find the next sequence number not being used and add the given |
@@ -475,9 +490,9 @@ static int intf_next_seq(ipmi_smi_t intf, | |||
475 | int rv = 0; | 490 | int rv = 0; |
476 | unsigned int i; | 491 | unsigned int i; |
477 | 492 | ||
478 | for (i=intf->curr_seq; | 493 | for (i = intf->curr_seq; |
479 | (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq; | 494 | (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq; |
480 | i=(i+1)%IPMI_IPMB_NUM_SEQ) | 495 | i = (i+1)%IPMI_IPMB_NUM_SEQ) |
481 | { | 496 | { |
482 | if (! intf->seq_table[i].inuse) | 497 | if (! intf->seq_table[i].inuse) |
483 | break; | 498 | break; |
@@ -712,7 +727,7 @@ static int ipmi_destroy_user_nolock(ipmi_user_t user) | |||
712 | 727 | ||
713 | /* Remove the user from the interfaces sequence table. */ | 728 | /* Remove the user from the interfaces sequence table. */ |
714 | spin_lock_irqsave(&(user->intf->seq_lock), flags); | 729 | spin_lock_irqsave(&(user->intf->seq_lock), flags); |
715 | for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) { | 730 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { |
716 | if (user->intf->seq_table[i].inuse | 731 | if (user->intf->seq_table[i].inuse |
717 | && (user->intf->seq_table[i].recv_msg->user == user)) | 732 | && (user->intf->seq_table[i].recv_msg->user == user)) |
718 | { | 733 | { |
@@ -766,26 +781,44 @@ void ipmi_get_version(ipmi_user_t user, | |||
766 | *minor = user->intf->version_minor; | 781 | *minor = user->intf->version_minor; |
767 | } | 782 | } |
768 | 783 | ||
769 | void ipmi_set_my_address(ipmi_user_t user, | 784 | int ipmi_set_my_address(ipmi_user_t user, |
770 | unsigned char address) | 785 | unsigned int channel, |
786 | unsigned char address) | ||
771 | { | 787 | { |
772 | user->intf->my_address = address; | 788 | if (channel >= IPMI_MAX_CHANNELS) |
789 | return -EINVAL; | ||
790 | user->intf->channels[channel].address = address; | ||
791 | return 0; | ||
773 | } | 792 | } |
774 | 793 | ||
775 | unsigned char ipmi_get_my_address(ipmi_user_t user) | 794 | int ipmi_get_my_address(ipmi_user_t user, |
795 | unsigned int channel, | ||
796 | unsigned char *address) | ||
776 | { | 797 | { |
777 | return user->intf->my_address; | 798 | if (channel >= IPMI_MAX_CHANNELS) |
799 | return -EINVAL; | ||
800 | *address = user->intf->channels[channel].address; | ||
801 | return 0; | ||
778 | } | 802 | } |
779 | 803 | ||
780 | void ipmi_set_my_LUN(ipmi_user_t user, | 804 | int ipmi_set_my_LUN(ipmi_user_t user, |
781 | unsigned char LUN) | 805 | unsigned int channel, |
806 | unsigned char LUN) | ||
782 | { | 807 | { |
783 | user->intf->my_lun = LUN & 0x3; | 808 | if (channel >= IPMI_MAX_CHANNELS) |
809 | return -EINVAL; | ||
810 | user->intf->channels[channel].lun = LUN & 0x3; | ||
811 | return 0; | ||
784 | } | 812 | } |
785 | 813 | ||
786 | unsigned char ipmi_get_my_LUN(ipmi_user_t user) | 814 | int ipmi_get_my_LUN(ipmi_user_t user, |
815 | unsigned int channel, | ||
816 | unsigned char *address) | ||
787 | { | 817 | { |
788 | return user->intf->my_lun; | 818 | if (channel >= IPMI_MAX_CHANNELS) |
819 | return -EINVAL; | ||
820 | *address = user->intf->channels[channel].lun; | ||
821 | return 0; | ||
789 | } | 822 | } |
790 | 823 | ||
791 | int ipmi_set_gets_events(ipmi_user_t user, int val) | 824 | int ipmi_set_gets_events(ipmi_user_t user, int val) |
@@ -828,11 +861,6 @@ int ipmi_register_for_cmd(ipmi_user_t user, | |||
828 | 861 | ||
829 | read_lock(&(user->intf->users_lock)); | 862 | read_lock(&(user->intf->users_lock)); |
830 | write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); | 863 | write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); |
831 | if (user->intf->all_cmd_rcvr != NULL) { | ||
832 | rv = -EBUSY; | ||
833 | goto out_unlock; | ||
834 | } | ||
835 | |||
836 | /* Make sure the command/netfn is not already registered. */ | 864 | /* Make sure the command/netfn is not already registered. */ |
837 | list_for_each_entry(cmp, &(user->intf->cmd_rcvrs), link) { | 865 | list_for_each_entry(cmp, &(user->intf->cmd_rcvrs), link) { |
838 | if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) { | 866 | if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) { |
@@ -847,7 +875,7 @@ int ipmi_register_for_cmd(ipmi_user_t user, | |||
847 | rcvr->user = user; | 875 | rcvr->user = user; |
848 | list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs)); | 876 | list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs)); |
849 | } | 877 | } |
850 | out_unlock: | 878 | |
851 | write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); | 879 | write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); |
852 | read_unlock(&(user->intf->users_lock)); | 880 | read_unlock(&(user->intf->users_lock)); |
853 | 881 | ||
@@ -1213,7 +1241,7 @@ static inline int i_ipmi_request(ipmi_user_t user, | |||
1213 | unsigned char ipmb_seq; | 1241 | unsigned char ipmb_seq; |
1214 | long seqid; | 1242 | long seqid; |
1215 | 1243 | ||
1216 | if (addr->channel > IPMI_NUM_CHANNELS) { | 1244 | if (addr->channel >= IPMI_NUM_CHANNELS) { |
1217 | spin_lock_irqsave(&intf->counter_lock, flags); | 1245 | spin_lock_irqsave(&intf->counter_lock, flags); |
1218 | intf->sent_invalid_commands++; | 1246 | intf->sent_invalid_commands++; |
1219 | spin_unlock_irqrestore(&intf->counter_lock, flags); | 1247 | spin_unlock_irqrestore(&intf->counter_lock, flags); |
@@ -1331,7 +1359,7 @@ static inline int i_ipmi_request(ipmi_user_t user, | |||
1331 | #ifdef DEBUG_MSGING | 1359 | #ifdef DEBUG_MSGING |
1332 | { | 1360 | { |
1333 | int m; | 1361 | int m; |
1334 | for (m=0; m<smi_msg->data_size; m++) | 1362 | for (m = 0; m < smi_msg->data_size; m++) |
1335 | printk(" %2.2x", smi_msg->data[m]); | 1363 | printk(" %2.2x", smi_msg->data[m]); |
1336 | printk("\n"); | 1364 | printk("\n"); |
1337 | } | 1365 | } |
@@ -1346,6 +1374,18 @@ static inline int i_ipmi_request(ipmi_user_t user, | |||
1346 | return rv; | 1374 | return rv; |
1347 | } | 1375 | } |
1348 | 1376 | ||
1377 | static int check_addr(ipmi_smi_t intf, | ||
1378 | struct ipmi_addr *addr, | ||
1379 | unsigned char *saddr, | ||
1380 | unsigned char *lun) | ||
1381 | { | ||
1382 | if (addr->channel >= IPMI_MAX_CHANNELS) | ||
1383 | return -EINVAL; | ||
1384 | *lun = intf->channels[addr->channel].lun; | ||
1385 | *saddr = intf->channels[addr->channel].address; | ||
1386 | return 0; | ||
1387 | } | ||
1388 | |||
1349 | int ipmi_request_settime(ipmi_user_t user, | 1389 | int ipmi_request_settime(ipmi_user_t user, |
1350 | struct ipmi_addr *addr, | 1390 | struct ipmi_addr *addr, |
1351 | long msgid, | 1391 | long msgid, |
@@ -1355,6 +1395,14 @@ int ipmi_request_settime(ipmi_user_t user, | |||
1355 | int retries, | 1395 | int retries, |
1356 | unsigned int retry_time_ms) | 1396 | unsigned int retry_time_ms) |
1357 | { | 1397 | { |
1398 | unsigned char saddr, lun; | ||
1399 | int rv; | ||
1400 | |||
1401 | if (! user) | ||
1402 | return -EINVAL; | ||
1403 | rv = check_addr(user->intf, addr, &saddr, &lun); | ||
1404 | if (rv) | ||
1405 | return rv; | ||
1358 | return i_ipmi_request(user, | 1406 | return i_ipmi_request(user, |
1359 | user->intf, | 1407 | user->intf, |
1360 | addr, | 1408 | addr, |
@@ -1363,8 +1411,8 @@ int ipmi_request_settime(ipmi_user_t user, | |||
1363 | user_msg_data, | 1411 | user_msg_data, |
1364 | NULL, NULL, | 1412 | NULL, NULL, |
1365 | priority, | 1413 | priority, |
1366 | user->intf->my_address, | 1414 | saddr, |
1367 | user->intf->my_lun, | 1415 | lun, |
1368 | retries, | 1416 | retries, |
1369 | retry_time_ms); | 1417 | retry_time_ms); |
1370 | } | 1418 | } |
@@ -1378,6 +1426,14 @@ int ipmi_request_supply_msgs(ipmi_user_t user, | |||
1378 | struct ipmi_recv_msg *supplied_recv, | 1426 | struct ipmi_recv_msg *supplied_recv, |
1379 | int priority) | 1427 | int priority) |
1380 | { | 1428 | { |
1429 | unsigned char saddr, lun; | ||
1430 | int rv; | ||
1431 | |||
1432 | if (! user) | ||
1433 | return -EINVAL; | ||
1434 | rv = check_addr(user->intf, addr, &saddr, &lun); | ||
1435 | if (rv) | ||
1436 | return rv; | ||
1381 | return i_ipmi_request(user, | 1437 | return i_ipmi_request(user, |
1382 | user->intf, | 1438 | user->intf, |
1383 | addr, | 1439 | addr, |
@@ -1387,8 +1443,8 @@ int ipmi_request_supply_msgs(ipmi_user_t user, | |||
1387 | supplied_smi, | 1443 | supplied_smi, |
1388 | supplied_recv, | 1444 | supplied_recv, |
1389 | priority, | 1445 | priority, |
1390 | user->intf->my_address, | 1446 | saddr, |
1391 | user->intf->my_lun, | 1447 | lun, |
1392 | -1, 0); | 1448 | -1, 0); |
1393 | } | 1449 | } |
1394 | 1450 | ||
@@ -1397,8 +1453,15 @@ static int ipmb_file_read_proc(char *page, char **start, off_t off, | |||
1397 | { | 1453 | { |
1398 | char *out = (char *) page; | 1454 | char *out = (char *) page; |
1399 | ipmi_smi_t intf = data; | 1455 | ipmi_smi_t intf = data; |
1456 | int i; | ||
1457 | int rv= 0; | ||
1400 | 1458 | ||
1401 | return sprintf(out, "%x\n", intf->my_address); | 1459 | for (i = 0; i < IPMI_MAX_CHANNELS; i++) |
1460 | rv += sprintf(out+rv, "%x ", intf->channels[i].address); | ||
1461 | out[rv-1] = '\n'; /* Replace the final space with a newline */ | ||
1462 | out[rv] = '\0'; | ||
1463 | rv++; | ||
1464 | return rv; | ||
1402 | } | 1465 | } |
1403 | 1466 | ||
1404 | static int version_file_read_proc(char *page, char **start, off_t off, | 1467 | static int version_file_read_proc(char *page, char **start, off_t off, |
@@ -1588,29 +1651,30 @@ send_channel_info_cmd(ipmi_smi_t intf, int chan) | |||
1588 | (struct ipmi_addr *) &si, | 1651 | (struct ipmi_addr *) &si, |
1589 | 0, | 1652 | 0, |
1590 | &msg, | 1653 | &msg, |
1591 | NULL, | 1654 | intf, |
1592 | NULL, | 1655 | NULL, |
1593 | NULL, | 1656 | NULL, |
1594 | 0, | 1657 | 0, |
1595 | intf->my_address, | 1658 | intf->channels[0].address, |
1596 | intf->my_lun, | 1659 | intf->channels[0].lun, |
1597 | -1, 0); | 1660 | -1, 0); |
1598 | } | 1661 | } |
1599 | 1662 | ||
1600 | static void | 1663 | static void |
1601 | channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg) | 1664 | channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) |
1602 | { | 1665 | { |
1603 | int rv = 0; | 1666 | int rv = 0; |
1604 | int chan; | 1667 | int chan; |
1605 | 1668 | ||
1606 | if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2)) | 1669 | if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) |
1607 | && (msg->rsp[1] == IPMI_GET_CHANNEL_INFO_CMD)) | 1670 | && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE) |
1671 | && (msg->msg.cmd == IPMI_GET_CHANNEL_INFO_CMD)) | ||
1608 | { | 1672 | { |
1609 | /* It's the one we want */ | 1673 | /* It's the one we want */ |
1610 | if (msg->rsp[2] != 0) { | 1674 | if (msg->msg.data[0] != 0) { |
1611 | /* Got an error from the channel, just go on. */ | 1675 | /* Got an error from the channel, just go on. */ |
1612 | 1676 | ||
1613 | if (msg->rsp[2] == IPMI_INVALID_COMMAND_ERR) { | 1677 | if (msg->msg.data[0] == IPMI_INVALID_COMMAND_ERR) { |
1614 | /* If the MC does not support this | 1678 | /* If the MC does not support this |
1615 | command, that is legal. We just | 1679 | command, that is legal. We just |
1616 | assume it has one IPMB at channel | 1680 | assume it has one IPMB at channel |
@@ -1627,13 +1691,13 @@ channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg) | |||
1627 | } | 1691 | } |
1628 | goto next_channel; | 1692 | goto next_channel; |
1629 | } | 1693 | } |
1630 | if (msg->rsp_size < 6) { | 1694 | if (msg->msg.data_len < 4) { |
1631 | /* Message not big enough, just go on. */ | 1695 | /* Message not big enough, just go on. */ |
1632 | goto next_channel; | 1696 | goto next_channel; |
1633 | } | 1697 | } |
1634 | chan = intf->curr_channel; | 1698 | chan = intf->curr_channel; |
1635 | intf->channels[chan].medium = msg->rsp[4] & 0x7f; | 1699 | intf->channels[chan].medium = msg->msg.data[2] & 0x7f; |
1636 | intf->channels[chan].protocol = msg->rsp[5] & 0x1f; | 1700 | intf->channels[chan].protocol = msg->msg.data[3] & 0x1f; |
1637 | 1701 | ||
1638 | next_channel: | 1702 | next_channel: |
1639 | intf->curr_channel++; | 1703 | intf->curr_channel++; |
@@ -1691,22 +1755,24 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
1691 | rv = -ENOMEM; | 1755 | rv = -ENOMEM; |
1692 | 1756 | ||
1693 | down_write(&interfaces_sem); | 1757 | down_write(&interfaces_sem); |
1694 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 1758 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
1695 | if (ipmi_interfaces[i] == NULL) { | 1759 | if (ipmi_interfaces[i] == NULL) { |
1696 | new_intf->intf_num = i; | 1760 | new_intf->intf_num = i; |
1697 | new_intf->version_major = version_major; | 1761 | new_intf->version_major = version_major; |
1698 | new_intf->version_minor = version_minor; | 1762 | new_intf->version_minor = version_minor; |
1699 | if (slave_addr == 0) | 1763 | for (j = 0; j < IPMI_MAX_CHANNELS; j++) { |
1700 | new_intf->my_address = IPMI_BMC_SLAVE_ADDR; | 1764 | new_intf->channels[j].address |
1701 | else | 1765 | = IPMI_BMC_SLAVE_ADDR; |
1702 | new_intf->my_address = slave_addr; | 1766 | new_intf->channels[j].lun = 2; |
1703 | new_intf->my_lun = 2; /* the SMS LUN. */ | 1767 | } |
1768 | if (slave_addr != 0) | ||
1769 | new_intf->channels[0].address = slave_addr; | ||
1704 | rwlock_init(&(new_intf->users_lock)); | 1770 | rwlock_init(&(new_intf->users_lock)); |
1705 | INIT_LIST_HEAD(&(new_intf->users)); | 1771 | INIT_LIST_HEAD(&(new_intf->users)); |
1706 | new_intf->handlers = handlers; | 1772 | new_intf->handlers = handlers; |
1707 | new_intf->send_info = send_info; | 1773 | new_intf->send_info = send_info; |
1708 | spin_lock_init(&(new_intf->seq_lock)); | 1774 | spin_lock_init(&(new_intf->seq_lock)); |
1709 | for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) { | 1775 | for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { |
1710 | new_intf->seq_table[j].inuse = 0; | 1776 | new_intf->seq_table[j].inuse = 0; |
1711 | new_intf->seq_table[j].seqid = 0; | 1777 | new_intf->seq_table[j].seqid = 0; |
1712 | } | 1778 | } |
@@ -1722,7 +1788,6 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
1722 | rwlock_init(&(new_intf->cmd_rcvr_lock)); | 1788 | rwlock_init(&(new_intf->cmd_rcvr_lock)); |
1723 | init_waitqueue_head(&new_intf->waitq); | 1789 | init_waitqueue_head(&new_intf->waitq); |
1724 | INIT_LIST_HEAD(&(new_intf->cmd_rcvrs)); | 1790 | INIT_LIST_HEAD(&(new_intf->cmd_rcvrs)); |
1725 | new_intf->all_cmd_rcvr = NULL; | ||
1726 | 1791 | ||
1727 | spin_lock_init(&(new_intf->counter_lock)); | 1792 | spin_lock_init(&(new_intf->counter_lock)); |
1728 | 1793 | ||
@@ -1814,7 +1879,7 @@ static void clean_up_interface_data(ipmi_smi_t intf) | |||
1814 | free_recv_msg_list(&(intf->waiting_events)); | 1879 | free_recv_msg_list(&(intf->waiting_events)); |
1815 | free_cmd_rcvr_list(&(intf->cmd_rcvrs)); | 1880 | free_cmd_rcvr_list(&(intf->cmd_rcvrs)); |
1816 | 1881 | ||
1817 | for (i=0; i<IPMI_IPMB_NUM_SEQ; i++) { | 1882 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { |
1818 | if ((intf->seq_table[i].inuse) | 1883 | if ((intf->seq_table[i].inuse) |
1819 | && (intf->seq_table[i].recv_msg)) | 1884 | && (intf->seq_table[i].recv_msg)) |
1820 | { | 1885 | { |
@@ -1833,7 +1898,7 @@ int ipmi_unregister_smi(ipmi_smi_t intf) | |||
1833 | down_write(&interfaces_sem); | 1898 | down_write(&interfaces_sem); |
1834 | if (list_empty(&(intf->users))) | 1899 | if (list_empty(&(intf->users))) |
1835 | { | 1900 | { |
1836 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 1901 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
1837 | if (ipmi_interfaces[i] == intf) { | 1902 | if (ipmi_interfaces[i] == intf) { |
1838 | remove_proc_entries(intf); | 1903 | remove_proc_entries(intf); |
1839 | spin_lock_irqsave(&interfaces_lock, flags); | 1904 | spin_lock_irqsave(&interfaces_lock, flags); |
@@ -1960,15 +2025,11 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, | |||
1960 | 2025 | ||
1961 | read_lock(&(intf->cmd_rcvr_lock)); | 2026 | read_lock(&(intf->cmd_rcvr_lock)); |
1962 | 2027 | ||
1963 | if (intf->all_cmd_rcvr) { | 2028 | /* Find the command/netfn. */ |
1964 | user = intf->all_cmd_rcvr; | 2029 | list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { |
1965 | } else { | 2030 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { |
1966 | /* Find the command/netfn. */ | 2031 | user = rcvr->user; |
1967 | list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { | 2032 | break; |
1968 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { | ||
1969 | user = rcvr->user; | ||
1970 | break; | ||
1971 | } | ||
1972 | } | 2033 | } |
1973 | } | 2034 | } |
1974 | read_unlock(&(intf->cmd_rcvr_lock)); | 2035 | read_unlock(&(intf->cmd_rcvr_lock)); |
@@ -1985,7 +2046,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, | |||
1985 | msg->data[3] = msg->rsp[6]; | 2046 | msg->data[3] = msg->rsp[6]; |
1986 | msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3); | 2047 | msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3); |
1987 | msg->data[5] = ipmb_checksum(&(msg->data[3]), 2); | 2048 | msg->data[5] = ipmb_checksum(&(msg->data[3]), 2); |
1988 | msg->data[6] = intf->my_address; | 2049 | msg->data[6] = intf->channels[msg->rsp[3] & 0xf].address; |
1989 | /* rqseq/lun */ | 2050 | /* rqseq/lun */ |
1990 | msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3); | 2051 | msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3); |
1991 | msg->data[8] = msg->rsp[8]; /* cmd */ | 2052 | msg->data[8] = msg->rsp[8]; /* cmd */ |
@@ -1997,7 +2058,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, | |||
1997 | { | 2058 | { |
1998 | int m; | 2059 | int m; |
1999 | printk("Invalid command:"); | 2060 | printk("Invalid command:"); |
2000 | for (m=0; m<msg->data_size; m++) | 2061 | for (m = 0; m < msg->data_size; m++) |
2001 | printk(" %2.2x", msg->data[m]); | 2062 | printk(" %2.2x", msg->data[m]); |
2002 | printk("\n"); | 2063 | printk("\n"); |
2003 | } | 2064 | } |
@@ -2145,15 +2206,11 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, | |||
2145 | 2206 | ||
2146 | read_lock(&(intf->cmd_rcvr_lock)); | 2207 | read_lock(&(intf->cmd_rcvr_lock)); |
2147 | 2208 | ||
2148 | if (intf->all_cmd_rcvr) { | 2209 | /* Find the command/netfn. */ |
2149 | user = intf->all_cmd_rcvr; | 2210 | list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { |
2150 | } else { | 2211 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { |
2151 | /* Find the command/netfn. */ | 2212 | user = rcvr->user; |
2152 | list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { | 2213 | break; |
2153 | if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { | ||
2154 | user = rcvr->user; | ||
2155 | break; | ||
2156 | } | ||
2157 | } | 2214 | } |
2158 | } | 2215 | } |
2159 | read_unlock(&(intf->cmd_rcvr_lock)); | 2216 | read_unlock(&(intf->cmd_rcvr_lock)); |
@@ -2330,6 +2387,14 @@ static int handle_bmc_rsp(ipmi_smi_t intf, | |||
2330 | unsigned long flags; | 2387 | unsigned long flags; |
2331 | 2388 | ||
2332 | recv_msg = (struct ipmi_recv_msg *) msg->user_data; | 2389 | recv_msg = (struct ipmi_recv_msg *) msg->user_data; |
2390 | if (recv_msg == NULL) | ||
2391 | { | ||
2392 | printk(KERN_WARNING"IPMI message received with no owner. This\n" | ||
2393 | "could be because of a malformed message, or\n" | ||
2394 | "because of a hardware error. Contact your\n" | ||
2395 | "hardware vender for assistance\n"); | ||
2396 | return 0; | ||
2397 | } | ||
2333 | 2398 | ||
2334 | /* Make sure the user still exists. */ | 2399 | /* Make sure the user still exists. */ |
2335 | list_for_each_entry(user, &(intf->users), link) { | 2400 | list_for_each_entry(user, &(intf->users), link) { |
@@ -2340,19 +2405,11 @@ static int handle_bmc_rsp(ipmi_smi_t intf, | |||
2340 | } | 2405 | } |
2341 | } | 2406 | } |
2342 | 2407 | ||
2343 | if (!found) { | 2408 | if ((! found) && recv_msg->user) { |
2344 | /* Special handling for NULL users. */ | 2409 | /* The user for the message went away, so give up. */ |
2345 | if (!recv_msg->user && intf->null_user_handler){ | 2410 | spin_lock_irqsave(&intf->counter_lock, flags); |
2346 | intf->null_user_handler(intf, msg); | 2411 | intf->unhandled_local_responses++; |
2347 | spin_lock_irqsave(&intf->counter_lock, flags); | 2412 | spin_unlock_irqrestore(&intf->counter_lock, flags); |
2348 | intf->handled_local_responses++; | ||
2349 | spin_unlock_irqrestore(&intf->counter_lock, flags); | ||
2350 | }else{ | ||
2351 | /* The user for the message went away, so give up. */ | ||
2352 | spin_lock_irqsave(&intf->counter_lock, flags); | ||
2353 | intf->unhandled_local_responses++; | ||
2354 | spin_unlock_irqrestore(&intf->counter_lock, flags); | ||
2355 | } | ||
2356 | ipmi_free_recv_msg(recv_msg); | 2413 | ipmi_free_recv_msg(recv_msg); |
2357 | } else { | 2414 | } else { |
2358 | struct ipmi_system_interface_addr *smi_addr; | 2415 | struct ipmi_system_interface_addr *smi_addr; |
@@ -2392,7 +2449,7 @@ static int handle_new_recv_msg(ipmi_smi_t intf, | |||
2392 | #ifdef DEBUG_MSGING | 2449 | #ifdef DEBUG_MSGING |
2393 | int m; | 2450 | int m; |
2394 | printk("Recv:"); | 2451 | printk("Recv:"); |
2395 | for (m=0; m<msg->rsp_size; m++) | 2452 | for (m = 0; m < msg->rsp_size; m++) |
2396 | printk(" %2.2x", msg->rsp[m]); | 2453 | printk(" %2.2x", msg->rsp[m]); |
2397 | printk("\n"); | 2454 | printk("\n"); |
2398 | #endif | 2455 | #endif |
@@ -2626,7 +2683,7 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, | |||
2626 | { | 2683 | { |
2627 | int m; | 2684 | int m; |
2628 | printk("Resend: "); | 2685 | printk("Resend: "); |
2629 | for (m=0; m<smi_msg->data_size; m++) | 2686 | for (m = 0; m < smi_msg->data_size; m++) |
2630 | printk(" %2.2x", smi_msg->data[m]); | 2687 | printk(" %2.2x", smi_msg->data[m]); |
2631 | printk("\n"); | 2688 | printk("\n"); |
2632 | } | 2689 | } |
@@ -2647,7 +2704,7 @@ ipmi_timeout_handler(long timeout_period) | |||
2647 | INIT_LIST_HEAD(&timeouts); | 2704 | INIT_LIST_HEAD(&timeouts); |
2648 | 2705 | ||
2649 | spin_lock(&interfaces_lock); | 2706 | spin_lock(&interfaces_lock); |
2650 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 2707 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
2651 | intf = ipmi_interfaces[i]; | 2708 | intf = ipmi_interfaces[i]; |
2652 | if (intf == NULL) | 2709 | if (intf == NULL) |
2653 | continue; | 2710 | continue; |
@@ -2672,7 +2729,7 @@ ipmi_timeout_handler(long timeout_period) | |||
2672 | have timed out, putting them in the timeouts | 2729 | have timed out, putting them in the timeouts |
2673 | list. */ | 2730 | list. */ |
2674 | spin_lock_irqsave(&(intf->seq_lock), flags); | 2731 | spin_lock_irqsave(&(intf->seq_lock), flags); |
2675 | for (j=0; j<IPMI_IPMB_NUM_SEQ; j++) { | 2732 | for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { |
2676 | struct seq_table *ent = &(intf->seq_table[j]); | 2733 | struct seq_table *ent = &(intf->seq_table[j]); |
2677 | if (!ent->inuse) | 2734 | if (!ent->inuse) |
2678 | continue; | 2735 | continue; |
@@ -2712,7 +2769,7 @@ ipmi_timeout_handler(long timeout_period) | |||
2712 | spin_unlock(&intf->counter_lock); | 2769 | spin_unlock(&intf->counter_lock); |
2713 | smi_msg = smi_from_recv_msg(intf, | 2770 | smi_msg = smi_from_recv_msg(intf, |
2714 | ent->recv_msg, j, ent->seqid); | 2771 | ent->recv_msg, j, ent->seqid); |
2715 | if(!smi_msg) | 2772 | if (! smi_msg) |
2716 | continue; | 2773 | continue; |
2717 | 2774 | ||
2718 | spin_unlock_irqrestore(&(intf->seq_lock),flags); | 2775 | spin_unlock_irqrestore(&(intf->seq_lock),flags); |
@@ -2743,7 +2800,7 @@ static void ipmi_request_event(void) | |||
2743 | int i; | 2800 | int i; |
2744 | 2801 | ||
2745 | spin_lock(&interfaces_lock); | 2802 | spin_lock(&interfaces_lock); |
2746 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 2803 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
2747 | intf = ipmi_interfaces[i]; | 2804 | intf = ipmi_interfaces[i]; |
2748 | if (intf == NULL) | 2805 | if (intf == NULL) |
2749 | continue; | 2806 | continue; |
@@ -2838,28 +2895,30 @@ static void dummy_recv_done_handler(struct ipmi_recv_msg *msg) | |||
2838 | } | 2895 | } |
2839 | 2896 | ||
2840 | #ifdef CONFIG_IPMI_PANIC_STRING | 2897 | #ifdef CONFIG_IPMI_PANIC_STRING |
2841 | static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg) | 2898 | static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg) |
2842 | { | 2899 | { |
2843 | if ((msg->rsp[0] == (IPMI_NETFN_SENSOR_EVENT_RESPONSE << 2)) | 2900 | if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) |
2844 | && (msg->rsp[1] == IPMI_GET_EVENT_RECEIVER_CMD) | 2901 | && (msg->msg.netfn == IPMI_NETFN_SENSOR_EVENT_RESPONSE) |
2845 | && (msg->rsp[2] == IPMI_CC_NO_ERROR)) | 2902 | && (msg->msg.cmd == IPMI_GET_EVENT_RECEIVER_CMD) |
2903 | && (msg->msg.data[0] == IPMI_CC_NO_ERROR)) | ||
2846 | { | 2904 | { |
2847 | /* A get event receiver command, save it. */ | 2905 | /* A get event receiver command, save it. */ |
2848 | intf->event_receiver = msg->rsp[3]; | 2906 | intf->event_receiver = msg->msg.data[1]; |
2849 | intf->event_receiver_lun = msg->rsp[4] & 0x3; | 2907 | intf->event_receiver_lun = msg->msg.data[2] & 0x3; |
2850 | } | 2908 | } |
2851 | } | 2909 | } |
2852 | 2910 | ||
2853 | static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg) | 2911 | static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg) |
2854 | { | 2912 | { |
2855 | if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2)) | 2913 | if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) |
2856 | && (msg->rsp[1] == IPMI_GET_DEVICE_ID_CMD) | 2914 | && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE) |
2857 | && (msg->rsp[2] == IPMI_CC_NO_ERROR)) | 2915 | && (msg->msg.cmd == IPMI_GET_DEVICE_ID_CMD) |
2916 | && (msg->msg.data[0] == IPMI_CC_NO_ERROR)) | ||
2858 | { | 2917 | { |
2859 | /* A get device id command, save if we are an event | 2918 | /* A get device id command, save if we are an event |
2860 | receiver or generator. */ | 2919 | receiver or generator. */ |
2861 | intf->local_sel_device = (msg->rsp[8] >> 2) & 1; | 2920 | intf->local_sel_device = (msg->msg.data[6] >> 2) & 1; |
2862 | intf->local_event_generator = (msg->rsp[8] >> 5) & 1; | 2921 | intf->local_event_generator = (msg->msg.data[6] >> 5) & 1; |
2863 | } | 2922 | } |
2864 | } | 2923 | } |
2865 | #endif | 2924 | #endif |
@@ -2903,7 +2962,7 @@ static void send_panic_events(char *str) | |||
2903 | recv_msg.done = dummy_recv_done_handler; | 2962 | recv_msg.done = dummy_recv_done_handler; |
2904 | 2963 | ||
2905 | /* For every registered interface, send the event. */ | 2964 | /* For every registered interface, send the event. */ |
2906 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 2965 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
2907 | intf = ipmi_interfaces[i]; | 2966 | intf = ipmi_interfaces[i]; |
2908 | if (intf == NULL) | 2967 | if (intf == NULL) |
2909 | continue; | 2968 | continue; |
@@ -2915,12 +2974,12 @@ static void send_panic_events(char *str) | |||
2915 | &addr, | 2974 | &addr, |
2916 | 0, | 2975 | 0, |
2917 | &msg, | 2976 | &msg, |
2918 | NULL, | 2977 | intf, |
2919 | &smi_msg, | 2978 | &smi_msg, |
2920 | &recv_msg, | 2979 | &recv_msg, |
2921 | 0, | 2980 | 0, |
2922 | intf->my_address, | 2981 | intf->channels[0].address, |
2923 | intf->my_lun, | 2982 | intf->channels[0].lun, |
2924 | 0, 1); /* Don't retry, and don't wait. */ | 2983 | 0, 1); /* Don't retry, and don't wait. */ |
2925 | } | 2984 | } |
2926 | 2985 | ||
@@ -2930,7 +2989,7 @@ static void send_panic_events(char *str) | |||
2930 | if (!str) | 2989 | if (!str) |
2931 | return; | 2990 | return; |
2932 | 2991 | ||
2933 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 2992 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
2934 | char *p = str; | 2993 | char *p = str; |
2935 | struct ipmi_ipmb_addr *ipmb; | 2994 | struct ipmi_ipmb_addr *ipmb; |
2936 | int j; | 2995 | int j; |
@@ -2961,12 +3020,12 @@ static void send_panic_events(char *str) | |||
2961 | &addr, | 3020 | &addr, |
2962 | 0, | 3021 | 0, |
2963 | &msg, | 3022 | &msg, |
2964 | NULL, | 3023 | intf, |
2965 | &smi_msg, | 3024 | &smi_msg, |
2966 | &recv_msg, | 3025 | &recv_msg, |
2967 | 0, | 3026 | 0, |
2968 | intf->my_address, | 3027 | intf->channels[0].address, |
2969 | intf->my_lun, | 3028 | intf->channels[0].lun, |
2970 | 0, 1); /* Don't retry, and don't wait. */ | 3029 | 0, 1); /* Don't retry, and don't wait. */ |
2971 | 3030 | ||
2972 | if (intf->local_event_generator) { | 3031 | if (intf->local_event_generator) { |
@@ -2981,12 +3040,12 @@ static void send_panic_events(char *str) | |||
2981 | &addr, | 3040 | &addr, |
2982 | 0, | 3041 | 0, |
2983 | &msg, | 3042 | &msg, |
2984 | NULL, | 3043 | intf, |
2985 | &smi_msg, | 3044 | &smi_msg, |
2986 | &recv_msg, | 3045 | &recv_msg, |
2987 | 0, | 3046 | 0, |
2988 | intf->my_address, | 3047 | intf->channels[0].address, |
2989 | intf->my_lun, | 3048 | intf->channels[0].lun, |
2990 | 0, 1); /* no retry, and no wait. */ | 3049 | 0, 1); /* no retry, and no wait. */ |
2991 | } | 3050 | } |
2992 | intf->null_user_handler = NULL; | 3051 | intf->null_user_handler = NULL; |
@@ -2996,7 +3055,7 @@ static void send_panic_events(char *str) | |||
2996 | be zero, and it must not be my address. */ | 3055 | be zero, and it must not be my address. */ |
2997 | if (((intf->event_receiver & 1) == 0) | 3056 | if (((intf->event_receiver & 1) == 0) |
2998 | && (intf->event_receiver != 0) | 3057 | && (intf->event_receiver != 0) |
2999 | && (intf->event_receiver != intf->my_address)) | 3058 | && (intf->event_receiver != intf->channels[0].address)) |
3000 | { | 3059 | { |
3001 | /* The event receiver is valid, send an IPMB | 3060 | /* The event receiver is valid, send an IPMB |
3002 | message. */ | 3061 | message. */ |
@@ -3031,7 +3090,7 @@ static void send_panic_events(char *str) | |||
3031 | data[0] = 0; | 3090 | data[0] = 0; |
3032 | data[1] = 0; | 3091 | data[1] = 0; |
3033 | data[2] = 0xf0; /* OEM event without timestamp. */ | 3092 | data[2] = 0xf0; /* OEM event without timestamp. */ |
3034 | data[3] = intf->my_address; | 3093 | data[3] = intf->channels[0].address; |
3035 | data[4] = j++; /* sequence # */ | 3094 | data[4] = j++; /* sequence # */ |
3036 | /* Always give 11 bytes, so strncpy will fill | 3095 | /* Always give 11 bytes, so strncpy will fill |
3037 | it with zeroes for me. */ | 3096 | it with zeroes for me. */ |
@@ -3043,12 +3102,12 @@ static void send_panic_events(char *str) | |||
3043 | &addr, | 3102 | &addr, |
3044 | 0, | 3103 | 0, |
3045 | &msg, | 3104 | &msg, |
3046 | NULL, | 3105 | intf, |
3047 | &smi_msg, | 3106 | &smi_msg, |
3048 | &recv_msg, | 3107 | &recv_msg, |
3049 | 0, | 3108 | 0, |
3050 | intf->my_address, | 3109 | intf->channels[0].address, |
3051 | intf->my_lun, | 3110 | intf->channels[0].lun, |
3052 | 0, 1); /* no retry, and no wait. */ | 3111 | 0, 1); /* no retry, and no wait. */ |
3053 | } | 3112 | } |
3054 | } | 3113 | } |
@@ -3070,7 +3129,7 @@ static int panic_event(struct notifier_block *this, | |||
3070 | has_paniced = 1; | 3129 | has_paniced = 1; |
3071 | 3130 | ||
3072 | /* For every registered interface, set it to run to completion. */ | 3131 | /* For every registered interface, set it to run to completion. */ |
3073 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 3132 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
3074 | intf = ipmi_interfaces[i]; | 3133 | intf = ipmi_interfaces[i]; |
3075 | if (intf == NULL) | 3134 | if (intf == NULL) |
3076 | continue; | 3135 | continue; |
@@ -3099,9 +3158,9 @@ static int ipmi_init_msghandler(void) | |||
3099 | return 0; | 3158 | return 0; |
3100 | 3159 | ||
3101 | printk(KERN_INFO "ipmi message handler version " | 3160 | printk(KERN_INFO "ipmi message handler version " |
3102 | IPMI_MSGHANDLER_VERSION "\n"); | 3161 | IPMI_DRIVER_VERSION "\n"); |
3103 | 3162 | ||
3104 | for (i=0; i<MAX_IPMI_INTERFACES; i++) { | 3163 | for (i = 0; i < MAX_IPMI_INTERFACES; i++) { |
3105 | ipmi_interfaces[i] = NULL; | 3164 | ipmi_interfaces[i] = NULL; |
3106 | } | 3165 | } |
3107 | 3166 | ||
@@ -3171,6 +3230,9 @@ module_exit(cleanup_ipmi); | |||
3171 | 3230 | ||
3172 | module_init(ipmi_init_msghandler_mod); | 3231 | module_init(ipmi_init_msghandler_mod); |
3173 | MODULE_LICENSE("GPL"); | 3232 | MODULE_LICENSE("GPL"); |
3233 | MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); | ||
3234 | MODULE_DESCRIPTION("Incoming and outgoing message routing for an IPMI interface."); | ||
3235 | MODULE_VERSION(IPMI_DRIVER_VERSION); | ||
3174 | 3236 | ||
3175 | EXPORT_SYMBOL(ipmi_create_user); | 3237 | EXPORT_SYMBOL(ipmi_create_user); |
3176 | EXPORT_SYMBOL(ipmi_destroy_user); | 3238 | EXPORT_SYMBOL(ipmi_destroy_user); |
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index f951c30236c9..e82a96ba396b 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/ipmi_smi.h> | 42 | #include <linux/ipmi_smi.h> |
43 | 43 | ||
44 | #define PFX "IPMI poweroff: " | 44 | #define PFX "IPMI poweroff: " |
45 | #define IPMI_POWEROFF_VERSION "v33" | ||
46 | 45 | ||
47 | /* Where to we insert our poweroff function? */ | 46 | /* Where to we insert our poweroff function? */ |
48 | extern void (*pm_power_off)(void); | 47 | extern void (*pm_power_off)(void); |
@@ -53,16 +52,17 @@ extern void (*pm_power_off)(void); | |||
53 | #define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */ | 52 | #define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */ |
54 | 53 | ||
55 | /* the IPMI data command */ | 54 | /* the IPMI data command */ |
56 | static int poweroff_control = IPMI_CHASSIS_POWER_DOWN; | 55 | static int poweroff_powercycle; |
57 | 56 | ||
58 | /* parameter definition to allow user to flag power cycle */ | 57 | /* parameter definition to allow user to flag power cycle */ |
59 | module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN); | 58 | module_param(poweroff_powercycle, int, 0); |
60 | MODULE_PARM_DESC(poweroff_control, " Set to 2 to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down."); | 59 | MODULE_PARM_DESC(poweroff_powercycles, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down."); |
61 | 60 | ||
62 | /* Stuff from the get device id command. */ | 61 | /* Stuff from the get device id command. */ |
63 | static unsigned int mfg_id; | 62 | static unsigned int mfg_id; |
64 | static unsigned int prod_id; | 63 | static unsigned int prod_id; |
65 | static unsigned char capabilities; | 64 | static unsigned char capabilities; |
65 | static unsigned char ipmi_version; | ||
66 | 66 | ||
67 | /* We use our own messages for this operation, we don't let the system | 67 | /* We use our own messages for this operation, we don't let the system |
68 | allocate them, since we may be in a panic situation. The whole | 68 | allocate them, since we may be in a panic situation. The whole |
@@ -338,6 +338,25 @@ static void ipmi_poweroff_cpi1 (ipmi_user_t user) | |||
338 | } | 338 | } |
339 | 339 | ||
340 | /* | 340 | /* |
341 | * ipmi_dell_chassis_detect() | ||
342 | * Dell systems with IPMI < 1.5 don't set the chassis capability bit | ||
343 | * but they can handle a chassis poweroff or powercycle command. | ||
344 | */ | ||
345 | |||
346 | #define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00} | ||
347 | static int ipmi_dell_chassis_detect (ipmi_user_t user) | ||
348 | { | ||
349 | const char ipmi_version_major = ipmi_version & 0xF; | ||
350 | const char ipmi_version_minor = (ipmi_version >> 4) & 0xF; | ||
351 | const char mfr[3]=DELL_IANA_MFR_ID; | ||
352 | if (!memcmp(mfr, &mfg_id, sizeof(mfr)) && | ||
353 | ipmi_version_major <= 1 && | ||
354 | ipmi_version_minor < 5) | ||
355 | return 1; | ||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | /* | ||
341 | * Standard chassis support | 360 | * Standard chassis support |
342 | */ | 361 | */ |
343 | 362 | ||
@@ -366,37 +385,34 @@ static void ipmi_poweroff_chassis (ipmi_user_t user) | |||
366 | 385 | ||
367 | powercyclefailed: | 386 | powercyclefailed: |
368 | printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n", | 387 | printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n", |
369 | ((poweroff_control != IPMI_CHASSIS_POWER_CYCLE) ? "down" : "cycle")); | 388 | (poweroff_powercycle ? "cycle" : "down")); |
370 | 389 | ||
371 | /* | 390 | /* |
372 | * Power down | 391 | * Power down |
373 | */ | 392 | */ |
374 | send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST; | 393 | send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST; |
375 | send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD; | 394 | send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD; |
376 | data[0] = poweroff_control; | 395 | if (poweroff_powercycle) |
396 | data[0] = IPMI_CHASSIS_POWER_CYCLE; | ||
397 | else | ||
398 | data[0] = IPMI_CHASSIS_POWER_DOWN; | ||
377 | send_msg.data = data; | 399 | send_msg.data = data; |
378 | send_msg.data_len = sizeof(data); | 400 | send_msg.data_len = sizeof(data); |
379 | rv = ipmi_request_in_rc_mode(user, | 401 | rv = ipmi_request_in_rc_mode(user, |
380 | (struct ipmi_addr *) &smi_addr, | 402 | (struct ipmi_addr *) &smi_addr, |
381 | &send_msg); | 403 | &send_msg); |
382 | if (rv) { | 404 | if (rv) { |
383 | switch (poweroff_control) { | 405 | if (poweroff_powercycle) { |
384 | case IPMI_CHASSIS_POWER_CYCLE: | 406 | /* power cycle failed, default to power down */ |
385 | /* power cycle failed, default to power down */ | 407 | printk(KERN_ERR PFX "Unable to send chassis power " \ |
386 | printk(KERN_ERR PFX "Unable to send chassis power " \ | 408 | "cycle message, IPMI error 0x%x\n", rv); |
387 | "cycle message, IPMI error 0x%x\n", rv); | 409 | poweroff_powercycle = 0; |
388 | poweroff_control = IPMI_CHASSIS_POWER_DOWN; | 410 | goto powercyclefailed; |
389 | goto powercyclefailed; | ||
390 | |||
391 | case IPMI_CHASSIS_POWER_DOWN: | ||
392 | default: | ||
393 | printk(KERN_ERR PFX "Unable to send chassis power " \ | ||
394 | "down message, IPMI error 0x%x\n", rv); | ||
395 | break; | ||
396 | } | 411 | } |
397 | } | ||
398 | 412 | ||
399 | return; | 413 | printk(KERN_ERR PFX "Unable to send chassis power " \ |
414 | "down message, IPMI error 0x%x\n", rv); | ||
415 | } | ||
400 | } | 416 | } |
401 | 417 | ||
402 | 418 | ||
@@ -414,6 +430,9 @@ static struct poweroff_function poweroff_functions[] = { | |||
414 | { .platform_type = "CPI1", | 430 | { .platform_type = "CPI1", |
415 | .detect = ipmi_cpi1_detect, | 431 | .detect = ipmi_cpi1_detect, |
416 | .poweroff_func = ipmi_poweroff_cpi1 }, | 432 | .poweroff_func = ipmi_poweroff_cpi1 }, |
433 | { .platform_type = "chassis", | ||
434 | .detect = ipmi_dell_chassis_detect, | ||
435 | .poweroff_func = ipmi_poweroff_chassis }, | ||
417 | /* Chassis should generally be last, other things should override | 436 | /* Chassis should generally be last, other things should override |
418 | it. */ | 437 | it. */ |
419 | { .platform_type = "chassis", | 438 | { .platform_type = "chassis", |
@@ -499,10 +518,11 @@ static void ipmi_po_new_smi(int if_num) | |||
499 | prod_id = (halt_recv_msg.msg.data[10] | 518 | prod_id = (halt_recv_msg.msg.data[10] |
500 | | (halt_recv_msg.msg.data[11] << 8)); | 519 | | (halt_recv_msg.msg.data[11] << 8)); |
501 | capabilities = halt_recv_msg.msg.data[6]; | 520 | capabilities = halt_recv_msg.msg.data[6]; |
521 | ipmi_version = halt_recv_msg.msg.data[5]; | ||
502 | 522 | ||
503 | 523 | ||
504 | /* Scan for a poweroff method */ | 524 | /* Scan for a poweroff method */ |
505 | for (i=0; i<NUM_PO_FUNCS; i++) { | 525 | for (i = 0; i < NUM_PO_FUNCS; i++) { |
506 | if (poweroff_functions[i].detect(ipmi_user)) | 526 | if (poweroff_functions[i].detect(ipmi_user)) |
507 | goto found; | 527 | goto found; |
508 | } | 528 | } |
@@ -538,39 +558,35 @@ static struct ipmi_smi_watcher smi_watcher = | |||
538 | 558 | ||
539 | 559 | ||
540 | #ifdef CONFIG_PROC_FS | 560 | #ifdef CONFIG_PROC_FS |
541 | /* displays properties to proc */ | 561 | #include <linux/sysctl.h> |
542 | static int proc_read_chassctrl(char *page, char **start, off_t off, int count, | 562 | |
543 | int *eof, void *data) | 563 | static ctl_table ipmi_table[] = { |
544 | { | 564 | { .ctl_name = DEV_IPMI_POWEROFF_POWERCYCLE, |
545 | return sprintf(page, "%d\t[ 0=powerdown 2=powercycle ]\n", | 565 | .procname = "poweroff_powercycle", |
546 | poweroff_control); | 566 | .data = &poweroff_powercycle, |
547 | } | 567 | .maxlen = sizeof(poweroff_powercycle), |
568 | .mode = 0644, | ||
569 | .proc_handler = &proc_dointvec }, | ||
570 | { } | ||
571 | }; | ||
548 | 572 | ||
549 | /* process property writes from proc */ | 573 | static ctl_table ipmi_dir_table[] = { |
550 | static int proc_write_chassctrl(struct file *file, const char *buffer, | 574 | { .ctl_name = DEV_IPMI, |
551 | unsigned long count, void *data) | 575 | .procname = "ipmi", |
552 | { | 576 | .mode = 0555, |
553 | int rv = count; | 577 | .child = ipmi_table }, |
554 | unsigned int newval = 0; | 578 | { } |
555 | 579 | }; | |
556 | sscanf(buffer, "%d", &newval); | ||
557 | switch (newval) { | ||
558 | case IPMI_CHASSIS_POWER_CYCLE: | ||
559 | printk(KERN_INFO PFX "power cycle is now enabled\n"); | ||
560 | poweroff_control = newval; | ||
561 | break; | ||
562 | |||
563 | case IPMI_CHASSIS_POWER_DOWN: | ||
564 | poweroff_control = IPMI_CHASSIS_POWER_DOWN; | ||
565 | break; | ||
566 | |||
567 | default: | ||
568 | rv = -EINVAL; | ||
569 | break; | ||
570 | } | ||
571 | 580 | ||
572 | return rv; | 581 | static ctl_table ipmi_root_table[] = { |
573 | } | 582 | { .ctl_name = CTL_DEV, |
583 | .procname = "dev", | ||
584 | .mode = 0555, | ||
585 | .child = ipmi_dir_table }, | ||
586 | { } | ||
587 | }; | ||
588 | |||
589 | static struct ctl_table_header *ipmi_table_header; | ||
574 | #endif /* CONFIG_PROC_FS */ | 590 | #endif /* CONFIG_PROC_FS */ |
575 | 591 | ||
576 | /* | 592 | /* |
@@ -578,42 +594,32 @@ static int proc_write_chassctrl(struct file *file, const char *buffer, | |||
578 | */ | 594 | */ |
579 | static int ipmi_poweroff_init (void) | 595 | static int ipmi_poweroff_init (void) |
580 | { | 596 | { |
581 | int rv; | 597 | int rv; |
582 | struct proc_dir_entry *file; | ||
583 | 598 | ||
584 | printk ("Copyright (C) 2004 MontaVista Software -" | 599 | printk ("Copyright (C) 2004 MontaVista Software -" |
585 | " IPMI Powerdown via sys_reboot version " | 600 | " IPMI Powerdown via sys_reboot.\n"); |
586 | IPMI_POWEROFF_VERSION ".\n"); | 601 | |
587 | 602 | if (poweroff_powercycle) | |
588 | switch (poweroff_control) { | 603 | printk(KERN_INFO PFX "Power cycle is enabled.\n"); |
589 | case IPMI_CHASSIS_POWER_CYCLE: | 604 | |
590 | printk(KERN_INFO PFX "Power cycle is enabled.\n"); | 605 | #ifdef CONFIG_PROC_FS |
591 | break; | 606 | ipmi_table_header = register_sysctl_table(ipmi_root_table, 1); |
592 | 607 | if (!ipmi_table_header) { | |
593 | case IPMI_CHASSIS_POWER_DOWN: | 608 | printk(KERN_ERR PFX "Unable to register powercycle sysctl\n"); |
594 | default: | 609 | rv = -ENOMEM; |
595 | poweroff_control = IPMI_CHASSIS_POWER_DOWN; | 610 | goto out_err; |
596 | break; | ||
597 | } | 611 | } |
612 | #endif | ||
598 | 613 | ||
614 | #ifdef CONFIG_PROC_FS | ||
599 | rv = ipmi_smi_watcher_register(&smi_watcher); | 615 | rv = ipmi_smi_watcher_register(&smi_watcher); |
616 | #endif | ||
600 | if (rv) { | 617 | if (rv) { |
618 | unregister_sysctl_table(ipmi_table_header); | ||
601 | printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv); | 619 | printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv); |
602 | goto out_err; | 620 | goto out_err; |
603 | } | 621 | } |
604 | 622 | ||
605 | #ifdef CONFIG_PROC_FS | ||
606 | file = create_proc_entry("poweroff_control", 0, proc_ipmi_root); | ||
607 | if (!file) { | ||
608 | printk(KERN_ERR PFX "Unable to create proc power control\n"); | ||
609 | } else { | ||
610 | file->nlink = 1; | ||
611 | file->read_proc = proc_read_chassctrl; | ||
612 | file->write_proc = proc_write_chassctrl; | ||
613 | file->owner = THIS_MODULE; | ||
614 | } | ||
615 | #endif | ||
616 | |||
617 | out_err: | 623 | out_err: |
618 | return rv; | 624 | return rv; |
619 | } | 625 | } |
@@ -624,7 +630,7 @@ static __exit void ipmi_poweroff_cleanup(void) | |||
624 | int rv; | 630 | int rv; |
625 | 631 | ||
626 | #ifdef CONFIG_PROC_FS | 632 | #ifdef CONFIG_PROC_FS |
627 | remove_proc_entry("poweroff_control", proc_ipmi_root); | 633 | unregister_sysctl_table(ipmi_table_header); |
628 | #endif | 634 | #endif |
629 | 635 | ||
630 | ipmi_smi_watcher_unregister(&smi_watcher); | 636 | ipmi_smi_watcher_unregister(&smi_watcher); |
@@ -642,3 +648,5 @@ module_exit(ipmi_poweroff_cleanup); | |||
642 | 648 | ||
643 | module_init(ipmi_poweroff_init); | 649 | module_init(ipmi_poweroff_init); |
644 | MODULE_LICENSE("GPL"); | 650 | MODULE_LICENSE("GPL"); |
651 | MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); | ||
652 | MODULE_DESCRIPTION("IPMI Poweroff extension to sys_reboot"); | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index a44b97304e95..1abec687865c 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -61,11 +61,11 @@ | |||
61 | # endif | 61 | # endif |
62 | static inline void add_usec_to_timer(struct timer_list *t, long v) | 62 | static inline void add_usec_to_timer(struct timer_list *t, long v) |
63 | { | 63 | { |
64 | t->sub_expires += nsec_to_arch_cycle(v * 1000); | 64 | t->arch_cycle_expires += nsec_to_arch_cycle(v * 1000); |
65 | while (t->sub_expires >= arch_cycles_per_jiffy) | 65 | while (t->arch_cycle_expires >= arch_cycles_per_jiffy) |
66 | { | 66 | { |
67 | t->expires++; | 67 | t->expires++; |
68 | t->sub_expires -= arch_cycles_per_jiffy; | 68 | t->arch_cycle_expires -= arch_cycles_per_jiffy; |
69 | } | 69 | } |
70 | } | 70 | } |
71 | #endif | 71 | #endif |
@@ -75,8 +75,7 @@ static inline void add_usec_to_timer(struct timer_list *t, long v) | |||
75 | #include <asm/io.h> | 75 | #include <asm/io.h> |
76 | #include "ipmi_si_sm.h" | 76 | #include "ipmi_si_sm.h" |
77 | #include <linux/init.h> | 77 | #include <linux/init.h> |
78 | 78 | #include <linux/dmi.h> | |
79 | #define IPMI_SI_VERSION "v33" | ||
80 | 79 | ||
81 | /* Measure times between events in the driver. */ | 80 | /* Measure times between events in the driver. */ |
82 | #undef DEBUG_TIMING | 81 | #undef DEBUG_TIMING |
@@ -109,6 +108,21 @@ enum si_type { | |||
109 | SI_KCS, SI_SMIC, SI_BT | 108 | SI_KCS, SI_SMIC, SI_BT |
110 | }; | 109 | }; |
111 | 110 | ||
111 | struct ipmi_device_id { | ||
112 | unsigned char device_id; | ||
113 | unsigned char device_revision; | ||
114 | unsigned char firmware_revision_1; | ||
115 | unsigned char firmware_revision_2; | ||
116 | unsigned char ipmi_version; | ||
117 | unsigned char additional_device_support; | ||
118 | unsigned char manufacturer_id[3]; | ||
119 | unsigned char product_id[2]; | ||
120 | unsigned char aux_firmware_revision[4]; | ||
121 | } __attribute__((packed)); | ||
122 | |||
123 | #define ipmi_version_major(v) ((v)->ipmi_version & 0xf) | ||
124 | #define ipmi_version_minor(v) ((v)->ipmi_version >> 4) | ||
125 | |||
112 | struct smi_info | 126 | struct smi_info |
113 | { | 127 | { |
114 | ipmi_smi_t intf; | 128 | ipmi_smi_t intf; |
@@ -131,12 +145,24 @@ struct smi_info | |||
131 | void (*irq_cleanup)(struct smi_info *info); | 145 | void (*irq_cleanup)(struct smi_info *info); |
132 | unsigned int io_size; | 146 | unsigned int io_size; |
133 | 147 | ||
148 | /* Per-OEM handler, called from handle_flags(). | ||
149 | Returns 1 when handle_flags() needs to be re-run | ||
150 | or 0 indicating it set si_state itself. | ||
151 | */ | ||
152 | int (*oem_data_avail_handler)(struct smi_info *smi_info); | ||
153 | |||
134 | /* Flags from the last GET_MSG_FLAGS command, used when an ATTN | 154 | /* Flags from the last GET_MSG_FLAGS command, used when an ATTN |
135 | is set to hold the flags until we are done handling everything | 155 | is set to hold the flags until we are done handling everything |
136 | from the flags. */ | 156 | from the flags. */ |
137 | #define RECEIVE_MSG_AVAIL 0x01 | 157 | #define RECEIVE_MSG_AVAIL 0x01 |
138 | #define EVENT_MSG_BUFFER_FULL 0x02 | 158 | #define EVENT_MSG_BUFFER_FULL 0x02 |
139 | #define WDT_PRE_TIMEOUT_INT 0x08 | 159 | #define WDT_PRE_TIMEOUT_INT 0x08 |
160 | #define OEM0_DATA_AVAIL 0x20 | ||
161 | #define OEM1_DATA_AVAIL 0x40 | ||
162 | #define OEM2_DATA_AVAIL 0x80 | ||
163 | #define OEM_DATA_AVAIL (OEM0_DATA_AVAIL | \ | ||
164 | OEM1_DATA_AVAIL | \ | ||
165 | OEM2_DATA_AVAIL) | ||
140 | unsigned char msg_flags; | 166 | unsigned char msg_flags; |
141 | 167 | ||
142 | /* If set to true, this will request events the next time the | 168 | /* If set to true, this will request events the next time the |
@@ -175,11 +201,7 @@ struct smi_info | |||
175 | interrupts. */ | 201 | interrupts. */ |
176 | int interrupt_disabled; | 202 | int interrupt_disabled; |
177 | 203 | ||
178 | unsigned char ipmi_si_dev_rev; | 204 | struct ipmi_device_id device_id; |
179 | unsigned char ipmi_si_fw_rev_major; | ||
180 | unsigned char ipmi_si_fw_rev_minor; | ||
181 | unsigned char ipmi_version_major; | ||
182 | unsigned char ipmi_version_minor; | ||
183 | 205 | ||
184 | /* Slave address, could be reported from DMI. */ | 206 | /* Slave address, could be reported from DMI. */ |
185 | unsigned char slave_addr; | 207 | unsigned char slave_addr; |
@@ -245,7 +267,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) | |||
245 | entry = smi_info->xmit_msgs.next; | 267 | entry = smi_info->xmit_msgs.next; |
246 | } | 268 | } |
247 | 269 | ||
248 | if (!entry) { | 270 | if (! entry) { |
249 | smi_info->curr_msg = NULL; | 271 | smi_info->curr_msg = NULL; |
250 | rv = SI_SM_IDLE; | 272 | rv = SI_SM_IDLE; |
251 | } else { | 273 | } else { |
@@ -306,7 +328,7 @@ static void start_clear_flags(struct smi_info *smi_info) | |||
306 | memory, we will re-enable the interrupt. */ | 328 | memory, we will re-enable the interrupt. */ |
307 | static inline void disable_si_irq(struct smi_info *smi_info) | 329 | static inline void disable_si_irq(struct smi_info *smi_info) |
308 | { | 330 | { |
309 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { | 331 | if ((smi_info->irq) && (! smi_info->interrupt_disabled)) { |
310 | disable_irq_nosync(smi_info->irq); | 332 | disable_irq_nosync(smi_info->irq); |
311 | smi_info->interrupt_disabled = 1; | 333 | smi_info->interrupt_disabled = 1; |
312 | } | 334 | } |
@@ -322,6 +344,7 @@ static inline void enable_si_irq(struct smi_info *smi_info) | |||
322 | 344 | ||
323 | static void handle_flags(struct smi_info *smi_info) | 345 | static void handle_flags(struct smi_info *smi_info) |
324 | { | 346 | { |
347 | retry: | ||
325 | if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) { | 348 | if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) { |
326 | /* Watchdog pre-timeout */ | 349 | /* Watchdog pre-timeout */ |
327 | spin_lock(&smi_info->count_lock); | 350 | spin_lock(&smi_info->count_lock); |
@@ -336,7 +359,7 @@ static void handle_flags(struct smi_info *smi_info) | |||
336 | } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { | 359 | } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { |
337 | /* Messages available. */ | 360 | /* Messages available. */ |
338 | smi_info->curr_msg = ipmi_alloc_smi_msg(); | 361 | smi_info->curr_msg = ipmi_alloc_smi_msg(); |
339 | if (!smi_info->curr_msg) { | 362 | if (! smi_info->curr_msg) { |
340 | disable_si_irq(smi_info); | 363 | disable_si_irq(smi_info); |
341 | smi_info->si_state = SI_NORMAL; | 364 | smi_info->si_state = SI_NORMAL; |
342 | return; | 365 | return; |
@@ -355,7 +378,7 @@ static void handle_flags(struct smi_info *smi_info) | |||
355 | } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) { | 378 | } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) { |
356 | /* Events available. */ | 379 | /* Events available. */ |
357 | smi_info->curr_msg = ipmi_alloc_smi_msg(); | 380 | smi_info->curr_msg = ipmi_alloc_smi_msg(); |
358 | if (!smi_info->curr_msg) { | 381 | if (! smi_info->curr_msg) { |
359 | disable_si_irq(smi_info); | 382 | disable_si_irq(smi_info); |
360 | smi_info->si_state = SI_NORMAL; | 383 | smi_info->si_state = SI_NORMAL; |
361 | return; | 384 | return; |
@@ -371,6 +394,10 @@ static void handle_flags(struct smi_info *smi_info) | |||
371 | smi_info->curr_msg->data, | 394 | smi_info->curr_msg->data, |
372 | smi_info->curr_msg->data_size); | 395 | smi_info->curr_msg->data_size); |
373 | smi_info->si_state = SI_GETTING_EVENTS; | 396 | smi_info->si_state = SI_GETTING_EVENTS; |
397 | } else if (smi_info->msg_flags & OEM_DATA_AVAIL) { | ||
398 | if (smi_info->oem_data_avail_handler) | ||
399 | if (smi_info->oem_data_avail_handler(smi_info)) | ||
400 | goto retry; | ||
374 | } else { | 401 | } else { |
375 | smi_info->si_state = SI_NORMAL; | 402 | smi_info->si_state = SI_NORMAL; |
376 | } | 403 | } |
@@ -387,7 +414,7 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
387 | #endif | 414 | #endif |
388 | switch (smi_info->si_state) { | 415 | switch (smi_info->si_state) { |
389 | case SI_NORMAL: | 416 | case SI_NORMAL: |
390 | if (!smi_info->curr_msg) | 417 | if (! smi_info->curr_msg) |
391 | break; | 418 | break; |
392 | 419 | ||
393 | smi_info->curr_msg->rsp_size | 420 | smi_info->curr_msg->rsp_size |
@@ -761,18 +788,20 @@ static void si_restart_short_timer(struct smi_info *smi_info) | |||
761 | #if defined(CONFIG_HIGH_RES_TIMERS) | 788 | #if defined(CONFIG_HIGH_RES_TIMERS) |
762 | unsigned long flags; | 789 | unsigned long flags; |
763 | unsigned long jiffies_now; | 790 | unsigned long jiffies_now; |
791 | unsigned long seq; | ||
764 | 792 | ||
765 | if (del_timer(&(smi_info->si_timer))) { | 793 | if (del_timer(&(smi_info->si_timer))) { |
766 | /* If we don't delete the timer, then it will go off | 794 | /* If we don't delete the timer, then it will go off |
767 | immediately, anyway. So we only process if we | 795 | immediately, anyway. So we only process if we |
768 | actually delete the timer. */ | 796 | actually delete the timer. */ |
769 | 797 | ||
770 | /* We already have irqsave on, so no need for it | 798 | do { |
771 | here. */ | 799 | seq = read_seqbegin_irqsave(&xtime_lock, flags); |
772 | read_lock(&xtime_lock); | 800 | jiffies_now = jiffies; |
773 | jiffies_now = jiffies; | 801 | smi_info->si_timer.expires = jiffies_now; |
774 | smi_info->si_timer.expires = jiffies_now; | 802 | smi_info->si_timer.arch_cycle_expires |
775 | smi_info->si_timer.sub_expires = get_arch_cycles(jiffies_now); | 803 | = get_arch_cycles(jiffies_now); |
804 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | ||
776 | 805 | ||
777 | add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); | 806 | add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); |
778 | 807 | ||
@@ -826,15 +855,19 @@ static void smi_timeout(unsigned long data) | |||
826 | /* If the state machine asks for a short delay, then shorten | 855 | /* If the state machine asks for a short delay, then shorten |
827 | the timer timeout. */ | 856 | the timer timeout. */ |
828 | if (smi_result == SI_SM_CALL_WITH_DELAY) { | 857 | if (smi_result == SI_SM_CALL_WITH_DELAY) { |
858 | #if defined(CONFIG_HIGH_RES_TIMERS) | ||
859 | unsigned long seq; | ||
860 | #endif | ||
829 | spin_lock_irqsave(&smi_info->count_lock, flags); | 861 | spin_lock_irqsave(&smi_info->count_lock, flags); |
830 | smi_info->short_timeouts++; | 862 | smi_info->short_timeouts++; |
831 | spin_unlock_irqrestore(&smi_info->count_lock, flags); | 863 | spin_unlock_irqrestore(&smi_info->count_lock, flags); |
832 | #if defined(CONFIG_HIGH_RES_TIMERS) | 864 | #if defined(CONFIG_HIGH_RES_TIMERS) |
833 | read_lock(&xtime_lock); | 865 | do { |
834 | smi_info->si_timer.expires = jiffies; | 866 | seq = read_seqbegin_irqsave(&xtime_lock, flags); |
835 | smi_info->si_timer.sub_expires | 867 | smi_info->si_timer.expires = jiffies; |
836 | = get_arch_cycles(smi_info->si_timer.expires); | 868 | smi_info->si_timer.arch_cycle_expires |
837 | read_unlock(&xtime_lock); | 869 | = get_arch_cycles(smi_info->si_timer.expires); |
870 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | ||
838 | add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); | 871 | add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC); |
839 | #else | 872 | #else |
840 | smi_info->si_timer.expires = jiffies + 1; | 873 | smi_info->si_timer.expires = jiffies + 1; |
@@ -845,7 +878,7 @@ static void smi_timeout(unsigned long data) | |||
845 | spin_unlock_irqrestore(&smi_info->count_lock, flags); | 878 | spin_unlock_irqrestore(&smi_info->count_lock, flags); |
846 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; | 879 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; |
847 | #if defined(CONFIG_HIGH_RES_TIMERS) | 880 | #if defined(CONFIG_HIGH_RES_TIMERS) |
848 | smi_info->si_timer.sub_expires = 0; | 881 | smi_info->si_timer.arch_cycle_expires = 0; |
849 | #endif | 882 | #endif |
850 | } | 883 | } |
851 | 884 | ||
@@ -1014,7 +1047,7 @@ static int std_irq_setup(struct smi_info *info) | |||
1014 | { | 1047 | { |
1015 | int rv; | 1048 | int rv; |
1016 | 1049 | ||
1017 | if (!info->irq) | 1050 | if (! info->irq) |
1018 | return 0; | 1051 | return 0; |
1019 | 1052 | ||
1020 | if (info->si_type == SI_BT) { | 1053 | if (info->si_type == SI_BT) { |
@@ -1023,7 +1056,7 @@ static int std_irq_setup(struct smi_info *info) | |||
1023 | SA_INTERRUPT, | 1056 | SA_INTERRUPT, |
1024 | DEVICE_NAME, | 1057 | DEVICE_NAME, |
1025 | info); | 1058 | info); |
1026 | if (!rv) | 1059 | if (! rv) |
1027 | /* Enable the interrupt in the BT interface. */ | 1060 | /* Enable the interrupt in the BT interface. */ |
1028 | info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, | 1061 | info->io.outputb(&info->io, IPMI_BT_INTMASK_REG, |
1029 | IPMI_BT_INTMASK_ENABLE_IRQ_BIT); | 1062 | IPMI_BT_INTMASK_ENABLE_IRQ_BIT); |
@@ -1048,7 +1081,7 @@ static int std_irq_setup(struct smi_info *info) | |||
1048 | 1081 | ||
1049 | static void std_irq_cleanup(struct smi_info *info) | 1082 | static void std_irq_cleanup(struct smi_info *info) |
1050 | { | 1083 | { |
1051 | if (!info->irq) | 1084 | if (! info->irq) |
1052 | return; | 1085 | return; |
1053 | 1086 | ||
1054 | if (info->si_type == SI_BT) | 1087 | if (info->si_type == SI_BT) |
@@ -1121,7 +1154,7 @@ static int port_setup(struct smi_info *info) | |||
1121 | unsigned int *addr = info->io.info; | 1154 | unsigned int *addr = info->io.info; |
1122 | int mapsize; | 1155 | int mapsize; |
1123 | 1156 | ||
1124 | if (!addr || (!*addr)) | 1157 | if (! addr || (! *addr)) |
1125 | return -ENODEV; | 1158 | return -ENODEV; |
1126 | 1159 | ||
1127 | info->io_cleanup = port_cleanup; | 1160 | info->io_cleanup = port_cleanup; |
@@ -1164,15 +1197,15 @@ static int try_init_port(int intf_num, struct smi_info **new_info) | |||
1164 | { | 1197 | { |
1165 | struct smi_info *info; | 1198 | struct smi_info *info; |
1166 | 1199 | ||
1167 | if (!ports[intf_num]) | 1200 | if (! ports[intf_num]) |
1168 | return -ENODEV; | 1201 | return -ENODEV; |
1169 | 1202 | ||
1170 | if (!is_new_interface(intf_num, IPMI_IO_ADDR_SPACE, | 1203 | if (! is_new_interface(intf_num, IPMI_IO_ADDR_SPACE, |
1171 | ports[intf_num])) | 1204 | ports[intf_num])) |
1172 | return -ENODEV; | 1205 | return -ENODEV; |
1173 | 1206 | ||
1174 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1207 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1175 | if (!info) { | 1208 | if (! info) { |
1176 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (1)\n"); | 1209 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (1)\n"); |
1177 | return -ENOMEM; | 1210 | return -ENOMEM; |
1178 | } | 1211 | } |
@@ -1182,10 +1215,10 @@ static int try_init_port(int intf_num, struct smi_info **new_info) | |||
1182 | info->io.info = &(ports[intf_num]); | 1215 | info->io.info = &(ports[intf_num]); |
1183 | info->io.addr = NULL; | 1216 | info->io.addr = NULL; |
1184 | info->io.regspacing = regspacings[intf_num]; | 1217 | info->io.regspacing = regspacings[intf_num]; |
1185 | if (!info->io.regspacing) | 1218 | if (! info->io.regspacing) |
1186 | info->io.regspacing = DEFAULT_REGSPACING; | 1219 | info->io.regspacing = DEFAULT_REGSPACING; |
1187 | info->io.regsize = regsizes[intf_num]; | 1220 | info->io.regsize = regsizes[intf_num]; |
1188 | if (!info->io.regsize) | 1221 | if (! info->io.regsize) |
1189 | info->io.regsize = DEFAULT_REGSPACING; | 1222 | info->io.regsize = DEFAULT_REGSPACING; |
1190 | info->io.regshift = regshifts[intf_num]; | 1223 | info->io.regshift = regshifts[intf_num]; |
1191 | info->irq = 0; | 1224 | info->irq = 0; |
@@ -1270,7 +1303,7 @@ static int mem_setup(struct smi_info *info) | |||
1270 | unsigned long *addr = info->io.info; | 1303 | unsigned long *addr = info->io.info; |
1271 | int mapsize; | 1304 | int mapsize; |
1272 | 1305 | ||
1273 | if (!addr || (!*addr)) | 1306 | if (! addr || (! *addr)) |
1274 | return -ENODEV; | 1307 | return -ENODEV; |
1275 | 1308 | ||
1276 | info->io_cleanup = mem_cleanup; | 1309 | info->io_cleanup = mem_cleanup; |
@@ -1325,15 +1358,15 @@ static int try_init_mem(int intf_num, struct smi_info **new_info) | |||
1325 | { | 1358 | { |
1326 | struct smi_info *info; | 1359 | struct smi_info *info; |
1327 | 1360 | ||
1328 | if (!addrs[intf_num]) | 1361 | if (! addrs[intf_num]) |
1329 | return -ENODEV; | 1362 | return -ENODEV; |
1330 | 1363 | ||
1331 | if (!is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE, | 1364 | if (! is_new_interface(intf_num, IPMI_MEM_ADDR_SPACE, |
1332 | addrs[intf_num])) | 1365 | addrs[intf_num])) |
1333 | return -ENODEV; | 1366 | return -ENODEV; |
1334 | 1367 | ||
1335 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1368 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1336 | if (!info) { | 1369 | if (! info) { |
1337 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (2)\n"); | 1370 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (2)\n"); |
1338 | return -ENOMEM; | 1371 | return -ENOMEM; |
1339 | } | 1372 | } |
@@ -1343,10 +1376,10 @@ static int try_init_mem(int intf_num, struct smi_info **new_info) | |||
1343 | info->io.info = &addrs[intf_num]; | 1376 | info->io.info = &addrs[intf_num]; |
1344 | info->io.addr = NULL; | 1377 | info->io.addr = NULL; |
1345 | info->io.regspacing = regspacings[intf_num]; | 1378 | info->io.regspacing = regspacings[intf_num]; |
1346 | if (!info->io.regspacing) | 1379 | if (! info->io.regspacing) |
1347 | info->io.regspacing = DEFAULT_REGSPACING; | 1380 | info->io.regspacing = DEFAULT_REGSPACING; |
1348 | info->io.regsize = regsizes[intf_num]; | 1381 | info->io.regsize = regsizes[intf_num]; |
1349 | if (!info->io.regsize) | 1382 | if (! info->io.regsize) |
1350 | info->io.regsize = DEFAULT_REGSPACING; | 1383 | info->io.regsize = DEFAULT_REGSPACING; |
1351 | info->io.regshift = regshifts[intf_num]; | 1384 | info->io.regshift = regshifts[intf_num]; |
1352 | info->irq = 0; | 1385 | info->irq = 0; |
@@ -1404,7 +1437,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info) | |||
1404 | { | 1437 | { |
1405 | acpi_status status; | 1438 | acpi_status status; |
1406 | 1439 | ||
1407 | if (!info->irq) | 1440 | if (! info->irq) |
1408 | return 0; | 1441 | return 0; |
1409 | 1442 | ||
1410 | /* FIXME - is level triggered right? */ | 1443 | /* FIXME - is level triggered right? */ |
@@ -1428,7 +1461,7 @@ static int acpi_gpe_irq_setup(struct smi_info *info) | |||
1428 | 1461 | ||
1429 | static void acpi_gpe_irq_cleanup(struct smi_info *info) | 1462 | static void acpi_gpe_irq_cleanup(struct smi_info *info) |
1430 | { | 1463 | { |
1431 | if (!info->irq) | 1464 | if (! info->irq) |
1432 | return; | 1465 | return; |
1433 | 1466 | ||
1434 | acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe); | 1467 | acpi_remove_gpe_handler(NULL, info->irq, &ipmi_acpi_gpe); |
@@ -1504,10 +1537,10 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) | |||
1504 | addr_space = IPMI_MEM_ADDR_SPACE; | 1537 | addr_space = IPMI_MEM_ADDR_SPACE; |
1505 | else | 1538 | else |
1506 | addr_space = IPMI_IO_ADDR_SPACE; | 1539 | addr_space = IPMI_IO_ADDR_SPACE; |
1507 | if (!is_new_interface(-1, addr_space, spmi->addr.address)) | 1540 | if (! is_new_interface(-1, addr_space, spmi->addr.address)) |
1508 | return -ENODEV; | 1541 | return -ENODEV; |
1509 | 1542 | ||
1510 | if (!spmi->addr.register_bit_width) { | 1543 | if (! spmi->addr.register_bit_width) { |
1511 | acpi_failure = 1; | 1544 | acpi_failure = 1; |
1512 | return -ENODEV; | 1545 | return -ENODEV; |
1513 | } | 1546 | } |
@@ -1534,7 +1567,7 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info) | |||
1534 | } | 1567 | } |
1535 | 1568 | ||
1536 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1569 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1537 | if (!info) { | 1570 | if (! info) { |
1538 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n"); | 1571 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n"); |
1539 | return -ENOMEM; | 1572 | return -ENOMEM; |
1540 | } | 1573 | } |
@@ -1610,22 +1643,15 @@ typedef struct dmi_ipmi_data | |||
1610 | static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS]; | 1643 | static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS]; |
1611 | static int dmi_data_entries; | 1644 | static int dmi_data_entries; |
1612 | 1645 | ||
1613 | typedef struct dmi_header | 1646 | static int __init decode_dmi(struct dmi_header *dm, int intf_num) |
1614 | { | ||
1615 | u8 type; | ||
1616 | u8 length; | ||
1617 | u16 handle; | ||
1618 | } dmi_header_t; | ||
1619 | |||
1620 | static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) | ||
1621 | { | 1647 | { |
1622 | u8 __iomem *data = (u8 __iomem *)dm; | 1648 | u8 *data = (u8 *)dm; |
1623 | unsigned long base_addr; | 1649 | unsigned long base_addr; |
1624 | u8 reg_spacing; | 1650 | u8 reg_spacing; |
1625 | u8 len = readb(&dm->length); | 1651 | u8 len = dm->length; |
1626 | dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; | 1652 | dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; |
1627 | 1653 | ||
1628 | ipmi_data->type = readb(&data[4]); | 1654 | ipmi_data->type = data[4]; |
1629 | 1655 | ||
1630 | memcpy(&base_addr, data+8, sizeof(unsigned long)); | 1656 | memcpy(&base_addr, data+8, sizeof(unsigned long)); |
1631 | if (len >= 0x11) { | 1657 | if (len >= 0x11) { |
@@ -1640,12 +1666,12 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) | |||
1640 | } | 1666 | } |
1641 | /* If bit 4 of byte 0x10 is set, then the lsb for the address | 1667 | /* If bit 4 of byte 0x10 is set, then the lsb for the address |
1642 | is odd. */ | 1668 | is odd. */ |
1643 | ipmi_data->base_addr = base_addr | ((readb(&data[0x10]) & 0x10) >> 4); | 1669 | ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4); |
1644 | 1670 | ||
1645 | ipmi_data->irq = readb(&data[0x11]); | 1671 | ipmi_data->irq = data[0x11]; |
1646 | 1672 | ||
1647 | /* The top two bits of byte 0x10 hold the register spacing. */ | 1673 | /* The top two bits of byte 0x10 hold the register spacing. */ |
1648 | reg_spacing = (readb(&data[0x10]) & 0xC0) >> 6; | 1674 | reg_spacing = (data[0x10] & 0xC0) >> 6; |
1649 | switch(reg_spacing){ | 1675 | switch(reg_spacing){ |
1650 | case 0x00: /* Byte boundaries */ | 1676 | case 0x00: /* Byte boundaries */ |
1651 | ipmi_data->offset = 1; | 1677 | ipmi_data->offset = 1; |
@@ -1673,7 +1699,7 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) | |||
1673 | ipmi_data->offset = 1; | 1699 | ipmi_data->offset = 1; |
1674 | } | 1700 | } |
1675 | 1701 | ||
1676 | ipmi_data->slave_addr = readb(&data[6]); | 1702 | ipmi_data->slave_addr = data[6]; |
1677 | 1703 | ||
1678 | if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) { | 1704 | if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) { |
1679 | dmi_data_entries++; | 1705 | dmi_data_entries++; |
@@ -1685,94 +1711,29 @@ static int decode_dmi(dmi_header_t __iomem *dm, int intf_num) | |||
1685 | return -1; | 1711 | return -1; |
1686 | } | 1712 | } |
1687 | 1713 | ||
1688 | static int dmi_table(u32 base, int len, int num) | 1714 | static void __init dmi_find_bmc(void) |
1689 | { | 1715 | { |
1690 | u8 __iomem *buf; | 1716 | struct dmi_device *dev = NULL; |
1691 | struct dmi_header __iomem *dm; | ||
1692 | u8 __iomem *data; | ||
1693 | int i=1; | ||
1694 | int status=-1; | ||
1695 | int intf_num = 0; | 1717 | int intf_num = 0; |
1696 | 1718 | ||
1697 | buf = ioremap(base, len); | 1719 | while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) { |
1698 | if(buf==NULL) | 1720 | if (intf_num >= SI_MAX_DRIVERS) |
1699 | return -1; | 1721 | break; |
1700 | |||
1701 | data = buf; | ||
1702 | |||
1703 | while(i<num && (data - buf) < len) | ||
1704 | { | ||
1705 | dm=(dmi_header_t __iomem *)data; | ||
1706 | |||
1707 | if((data-buf+readb(&dm->length)) >= len) | ||
1708 | break; | ||
1709 | |||
1710 | if (readb(&dm->type) == 38) { | ||
1711 | if (decode_dmi(dm, intf_num) == 0) { | ||
1712 | intf_num++; | ||
1713 | if (intf_num >= SI_MAX_DRIVERS) | ||
1714 | break; | ||
1715 | } | ||
1716 | } | ||
1717 | |||
1718 | data+=readb(&dm->length); | ||
1719 | while((data-buf) < len && (readb(data)||readb(data+1))) | ||
1720 | data++; | ||
1721 | data+=2; | ||
1722 | i++; | ||
1723 | } | ||
1724 | iounmap(buf); | ||
1725 | |||
1726 | return status; | ||
1727 | } | ||
1728 | |||
1729 | static inline int dmi_checksum(u8 *buf) | ||
1730 | { | ||
1731 | u8 sum=0; | ||
1732 | int a; | ||
1733 | |||
1734 | for(a=0; a<15; a++) | ||
1735 | sum+=buf[a]; | ||
1736 | return (sum==0); | ||
1737 | } | ||
1738 | |||
1739 | static int dmi_decode(void) | ||
1740 | { | ||
1741 | u8 buf[15]; | ||
1742 | u32 fp=0xF0000; | ||
1743 | |||
1744 | #ifdef CONFIG_SIMNOW | ||
1745 | return -1; | ||
1746 | #endif | ||
1747 | |||
1748 | while(fp < 0xFFFFF) | ||
1749 | { | ||
1750 | isa_memcpy_fromio(buf, fp, 15); | ||
1751 | if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf)) | ||
1752 | { | ||
1753 | u16 num=buf[13]<<8|buf[12]; | ||
1754 | u16 len=buf[7]<<8|buf[6]; | ||
1755 | u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]; | ||
1756 | 1722 | ||
1757 | if(dmi_table(base, len, num) == 0) | 1723 | decode_dmi((struct dmi_header *) dev->device_data, intf_num++); |
1758 | return 0; | ||
1759 | } | ||
1760 | fp+=16; | ||
1761 | } | 1724 | } |
1762 | |||
1763 | return -1; | ||
1764 | } | 1725 | } |
1765 | 1726 | ||
1766 | static int try_init_smbios(int intf_num, struct smi_info **new_info) | 1727 | static int try_init_smbios(int intf_num, struct smi_info **new_info) |
1767 | { | 1728 | { |
1768 | struct smi_info *info; | 1729 | struct smi_info *info; |
1769 | dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; | 1730 | dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num; |
1770 | char *io_type; | 1731 | char *io_type; |
1771 | 1732 | ||
1772 | if (intf_num >= dmi_data_entries) | 1733 | if (intf_num >= dmi_data_entries) |
1773 | return -ENODEV; | 1734 | return -ENODEV; |
1774 | 1735 | ||
1775 | switch(ipmi_data->type) { | 1736 | switch (ipmi_data->type) { |
1776 | case 0x01: /* KCS */ | 1737 | case 0x01: /* KCS */ |
1777 | si_type[intf_num] = "kcs"; | 1738 | si_type[intf_num] = "kcs"; |
1778 | break; | 1739 | break; |
@@ -1787,7 +1748,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info) | |||
1787 | } | 1748 | } |
1788 | 1749 | ||
1789 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1750 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1790 | if (!info) { | 1751 | if (! info) { |
1791 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (4)\n"); | 1752 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (4)\n"); |
1792 | return -ENOMEM; | 1753 | return -ENOMEM; |
1793 | } | 1754 | } |
@@ -1811,7 +1772,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info) | |||
1811 | 1772 | ||
1812 | regspacings[intf_num] = ipmi_data->offset; | 1773 | regspacings[intf_num] = ipmi_data->offset; |
1813 | info->io.regspacing = regspacings[intf_num]; | 1774 | info->io.regspacing = regspacings[intf_num]; |
1814 | if (!info->io.regspacing) | 1775 | if (! info->io.regspacing) |
1815 | info->io.regspacing = DEFAULT_REGSPACING; | 1776 | info->io.regspacing = DEFAULT_REGSPACING; |
1816 | info->io.regsize = DEFAULT_REGSPACING; | 1777 | info->io.regsize = DEFAULT_REGSPACING; |
1817 | info->io.regshift = regshifts[intf_num]; | 1778 | info->io.regshift = regshifts[intf_num]; |
@@ -1853,14 +1814,14 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) | |||
1853 | 1814 | ||
1854 | pci_smic_checked = 1; | 1815 | pci_smic_checked = 1; |
1855 | 1816 | ||
1856 | if ((pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, | 1817 | pci_dev = pci_get_device(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID, NULL); |
1857 | NULL))) | 1818 | if (! pci_dev) { |
1858 | ; | 1819 | pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL); |
1859 | else if ((pci_dev = pci_get_class(PCI_ERMC_CLASSCODE, NULL)) && | 1820 | if (pci_dev && (pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID)) |
1860 | pci_dev->subsystem_vendor == PCI_HP_VENDOR_ID) | 1821 | fe_rmc = 1; |
1861 | fe_rmc = 1; | 1822 | else |
1862 | else | 1823 | return -ENODEV; |
1863 | return -ENODEV; | 1824 | } |
1864 | 1825 | ||
1865 | error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr); | 1826 | error = pci_read_config_word(pci_dev, PCI_MMC_ADDR_CW, &base_addr); |
1866 | if (error) | 1827 | if (error) |
@@ -1873,7 +1834,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) | |||
1873 | } | 1834 | } |
1874 | 1835 | ||
1875 | /* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */ | 1836 | /* Bit 0: 1 specifies programmed I/O, 0 specifies memory mapped I/O */ |
1876 | if (!(base_addr & 0x0001)) | 1837 | if (! (base_addr & 0x0001)) |
1877 | { | 1838 | { |
1878 | pci_dev_put(pci_dev); | 1839 | pci_dev_put(pci_dev); |
1879 | printk(KERN_ERR | 1840 | printk(KERN_ERR |
@@ -1883,17 +1844,17 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) | |||
1883 | } | 1844 | } |
1884 | 1845 | ||
1885 | base_addr &= 0xFFFE; | 1846 | base_addr &= 0xFFFE; |
1886 | if (!fe_rmc) | 1847 | if (! fe_rmc) |
1887 | /* Data register starts at base address + 1 in eRMC */ | 1848 | /* Data register starts at base address + 1 in eRMC */ |
1888 | ++base_addr; | 1849 | ++base_addr; |
1889 | 1850 | ||
1890 | if (!is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) { | 1851 | if (! is_new_interface(-1, IPMI_IO_ADDR_SPACE, base_addr)) { |
1891 | pci_dev_put(pci_dev); | 1852 | pci_dev_put(pci_dev); |
1892 | return -ENODEV; | 1853 | return -ENODEV; |
1893 | } | 1854 | } |
1894 | 1855 | ||
1895 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1856 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1896 | if (!info) { | 1857 | if (! info) { |
1897 | pci_dev_put(pci_dev); | 1858 | pci_dev_put(pci_dev); |
1898 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n"); | 1859 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (5)\n"); |
1899 | return -ENOMEM; | 1860 | return -ENOMEM; |
@@ -1904,7 +1865,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) | |||
1904 | ports[intf_num] = base_addr; | 1865 | ports[intf_num] = base_addr; |
1905 | info->io.info = &(ports[intf_num]); | 1866 | info->io.info = &(ports[intf_num]); |
1906 | info->io.regspacing = regspacings[intf_num]; | 1867 | info->io.regspacing = regspacings[intf_num]; |
1907 | if (!info->io.regspacing) | 1868 | if (! info->io.regspacing) |
1908 | info->io.regspacing = DEFAULT_REGSPACING; | 1869 | info->io.regspacing = DEFAULT_REGSPACING; |
1909 | info->io.regsize = DEFAULT_REGSPACING; | 1870 | info->io.regsize = DEFAULT_REGSPACING; |
1910 | info->io.regshift = regshifts[intf_num]; | 1871 | info->io.regshift = regshifts[intf_num]; |
@@ -1925,7 +1886,7 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info) | |||
1925 | static int try_init_plug_and_play(int intf_num, struct smi_info **new_info) | 1886 | static int try_init_plug_and_play(int intf_num, struct smi_info **new_info) |
1926 | { | 1887 | { |
1927 | #ifdef CONFIG_PCI | 1888 | #ifdef CONFIG_PCI |
1928 | if (find_pci_smic(intf_num, new_info)==0) | 1889 | if (find_pci_smic(intf_num, new_info) == 0) |
1929 | return 0; | 1890 | return 0; |
1930 | #endif | 1891 | #endif |
1931 | /* Include other methods here. */ | 1892 | /* Include other methods here. */ |
@@ -1943,7 +1904,7 @@ static int try_get_dev_id(struct smi_info *smi_info) | |||
1943 | int rv = 0; | 1904 | int rv = 0; |
1944 | 1905 | ||
1945 | resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); | 1906 | resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); |
1946 | if (!resp) | 1907 | if (! resp) |
1947 | return -ENOMEM; | 1908 | return -ENOMEM; |
1948 | 1909 | ||
1949 | /* Do a Get Device ID command, since it comes back with some | 1910 | /* Do a Get Device ID command, since it comes back with some |
@@ -1992,11 +1953,8 @@ static int try_get_dev_id(struct smi_info *smi_info) | |||
1992 | } | 1953 | } |
1993 | 1954 | ||
1994 | /* Record info from the get device id, in case we need it. */ | 1955 | /* Record info from the get device id, in case we need it. */ |
1995 | smi_info->ipmi_si_dev_rev = resp[4] & 0xf; | 1956 | memcpy(&smi_info->device_id, &resp[3], |
1996 | smi_info->ipmi_si_fw_rev_major = resp[5] & 0x7f; | 1957 | min_t(unsigned long, resp_len-3, sizeof(smi_info->device_id))); |
1997 | smi_info->ipmi_si_fw_rev_minor = resp[6]; | ||
1998 | smi_info->ipmi_version_major = resp[7] & 0xf; | ||
1999 | smi_info->ipmi_version_minor = resp[7] >> 4; | ||
2000 | 1958 | ||
2001 | out: | 1959 | out: |
2002 | kfree(resp); | 1960 | kfree(resp); |
@@ -2028,7 +1986,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off, | |||
2028 | struct smi_info *smi = data; | 1986 | struct smi_info *smi = data; |
2029 | 1987 | ||
2030 | out += sprintf(out, "interrupts_enabled: %d\n", | 1988 | out += sprintf(out, "interrupts_enabled: %d\n", |
2031 | smi->irq && !smi->interrupt_disabled); | 1989 | smi->irq && ! smi->interrupt_disabled); |
2032 | out += sprintf(out, "short_timeouts: %ld\n", | 1990 | out += sprintf(out, "short_timeouts: %ld\n", |
2033 | smi->short_timeouts); | 1991 | smi->short_timeouts); |
2034 | out += sprintf(out, "long_timeouts: %ld\n", | 1992 | out += sprintf(out, "long_timeouts: %ld\n", |
@@ -2057,6 +2015,73 @@ static int stat_file_read_proc(char *page, char **start, off_t off, | |||
2057 | return (out - ((char *) page)); | 2015 | return (out - ((char *) page)); |
2058 | } | 2016 | } |
2059 | 2017 | ||
2018 | /* | ||
2019 | * oem_data_avail_to_receive_msg_avail | ||
2020 | * @info - smi_info structure with msg_flags set | ||
2021 | * | ||
2022 | * Converts flags from OEM_DATA_AVAIL to RECEIVE_MSG_AVAIL | ||
2023 | * Returns 1 indicating need to re-run handle_flags(). | ||
2024 | */ | ||
2025 | static int oem_data_avail_to_receive_msg_avail(struct smi_info *smi_info) | ||
2026 | { | ||
2027 | smi_info->msg_flags = ((smi_info->msg_flags & ~OEM_DATA_AVAIL) | | ||
2028 | RECEIVE_MSG_AVAIL); | ||
2029 | return 1; | ||
2030 | } | ||
2031 | |||
2032 | /* | ||
2033 | * setup_dell_poweredge_oem_data_handler | ||
2034 | * @info - smi_info.device_id must be populated | ||
2035 | * | ||
2036 | * Systems that match, but have firmware version < 1.40 may assert | ||
2037 | * OEM0_DATA_AVAIL on their own, without being told via Set Flags that | ||
2038 | * it's safe to do so. Such systems will de-assert OEM1_DATA_AVAIL | ||
2039 | * upon receipt of IPMI_GET_MSG_CMD, so we should treat these flags | ||
2040 | * as RECEIVE_MSG_AVAIL instead. | ||
2041 | * | ||
2042 | * As Dell has no plans to release IPMI 1.5 firmware that *ever* | ||
2043 | * assert the OEM[012] bits, and if it did, the driver would have to | ||
2044 | * change to handle that properly, we don't actually check for the | ||
2045 | * firmware version. | ||
2046 | * Device ID = 0x20 BMC on PowerEdge 8G servers | ||
2047 | * Device Revision = 0x80 | ||
2048 | * Firmware Revision1 = 0x01 BMC version 1.40 | ||
2049 | * Firmware Revision2 = 0x40 BCD encoded | ||
2050 | * IPMI Version = 0x51 IPMI 1.5 | ||
2051 | * Manufacturer ID = A2 02 00 Dell IANA | ||
2052 | * | ||
2053 | */ | ||
2054 | #define DELL_POWEREDGE_8G_BMC_DEVICE_ID 0x20 | ||
2055 | #define DELL_POWEREDGE_8G_BMC_DEVICE_REV 0x80 | ||
2056 | #define DELL_POWEREDGE_8G_BMC_IPMI_VERSION 0x51 | ||
2057 | #define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00} | ||
2058 | static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info) | ||
2059 | { | ||
2060 | struct ipmi_device_id *id = &smi_info->device_id; | ||
2061 | const char mfr[3]=DELL_IANA_MFR_ID; | ||
2062 | if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr)) | ||
2063 | && (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID) | ||
2064 | && (id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV) | ||
2065 | && (id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION)) | ||
2066 | { | ||
2067 | smi_info->oem_data_avail_handler = | ||
2068 | oem_data_avail_to_receive_msg_avail; | ||
2069 | } | ||
2070 | } | ||
2071 | |||
2072 | /* | ||
2073 | * setup_oem_data_handler | ||
2074 | * @info - smi_info.device_id must be filled in already | ||
2075 | * | ||
2076 | * Fills in smi_info.device_id.oem_data_available_handler | ||
2077 | * when we know what function to use there. | ||
2078 | */ | ||
2079 | |||
2080 | static void setup_oem_data_handler(struct smi_info *smi_info) | ||
2081 | { | ||
2082 | setup_dell_poweredge_oem_data_handler(smi_info); | ||
2083 | } | ||
2084 | |||
2060 | /* Returns 0 if initialized, or negative on an error. */ | 2085 | /* Returns 0 if initialized, or negative on an error. */ |
2061 | static int init_one_smi(int intf_num, struct smi_info **smi) | 2086 | static int init_one_smi(int intf_num, struct smi_info **smi) |
2062 | { | 2087 | { |
@@ -2068,19 +2093,15 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2068 | if (rv) | 2093 | if (rv) |
2069 | rv = try_init_port(intf_num, &new_smi); | 2094 | rv = try_init_port(intf_num, &new_smi); |
2070 | #ifdef CONFIG_ACPI_INTERPRETER | 2095 | #ifdef CONFIG_ACPI_INTERPRETER |
2071 | if ((rv) && (si_trydefaults)) { | 2096 | if (rv && si_trydefaults) |
2072 | rv = try_init_acpi(intf_num, &new_smi); | 2097 | rv = try_init_acpi(intf_num, &new_smi); |
2073 | } | ||
2074 | #endif | 2098 | #endif |
2075 | #ifdef CONFIG_X86 | 2099 | #ifdef CONFIG_X86 |
2076 | if ((rv) && (si_trydefaults)) { | 2100 | if (rv && si_trydefaults) |
2077 | rv = try_init_smbios(intf_num, &new_smi); | 2101 | rv = try_init_smbios(intf_num, &new_smi); |
2078 | } | ||
2079 | #endif | 2102 | #endif |
2080 | if ((rv) && (si_trydefaults)) { | 2103 | if (rv && si_trydefaults) |
2081 | rv = try_init_plug_and_play(intf_num, &new_smi); | 2104 | rv = try_init_plug_and_play(intf_num, &new_smi); |
2082 | } | ||
2083 | |||
2084 | 2105 | ||
2085 | if (rv) | 2106 | if (rv) |
2086 | return rv; | 2107 | return rv; |
@@ -2090,7 +2111,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2090 | new_smi->si_sm = NULL; | 2111 | new_smi->si_sm = NULL; |
2091 | new_smi->handlers = NULL; | 2112 | new_smi->handlers = NULL; |
2092 | 2113 | ||
2093 | if (!new_smi->irq_setup) { | 2114 | if (! new_smi->irq_setup) { |
2094 | new_smi->irq = irqs[intf_num]; | 2115 | new_smi->irq = irqs[intf_num]; |
2095 | new_smi->irq_setup = std_irq_setup; | 2116 | new_smi->irq_setup = std_irq_setup; |
2096 | new_smi->irq_cleanup = std_irq_cleanup; | 2117 | new_smi->irq_cleanup = std_irq_cleanup; |
@@ -2124,7 +2145,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2124 | 2145 | ||
2125 | /* Allocate the state machine's data and initialize it. */ | 2146 | /* Allocate the state machine's data and initialize it. */ |
2126 | new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); | 2147 | new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); |
2127 | if (!new_smi->si_sm) { | 2148 | if (! new_smi->si_sm) { |
2128 | printk(" Could not allocate state machine memory\n"); | 2149 | printk(" Could not allocate state machine memory\n"); |
2129 | rv = -ENOMEM; | 2150 | rv = -ENOMEM; |
2130 | goto out_err; | 2151 | goto out_err; |
@@ -2155,6 +2176,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2155 | if (rv) | 2176 | if (rv) |
2156 | goto out_err; | 2177 | goto out_err; |
2157 | 2178 | ||
2179 | setup_oem_data_handler(new_smi); | ||
2180 | |||
2158 | /* Try to claim any interrupts. */ | 2181 | /* Try to claim any interrupts. */ |
2159 | new_smi->irq_setup(new_smi); | 2182 | new_smi->irq_setup(new_smi); |
2160 | 2183 | ||
@@ -2188,8 +2211,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2188 | 2211 | ||
2189 | rv = ipmi_register_smi(&handlers, | 2212 | rv = ipmi_register_smi(&handlers, |
2190 | new_smi, | 2213 | new_smi, |
2191 | new_smi->ipmi_version_major, | 2214 | ipmi_version_major(&new_smi->device_id), |
2192 | new_smi->ipmi_version_minor, | 2215 | ipmi_version_minor(&new_smi->device_id), |
2193 | new_smi->slave_addr, | 2216 | new_smi->slave_addr, |
2194 | &(new_smi->intf)); | 2217 | &(new_smi->intf)); |
2195 | if (rv) { | 2218 | if (rv) { |
@@ -2230,7 +2253,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi) | |||
2230 | 2253 | ||
2231 | /* Wait for the timer to stop. This avoids problems with race | 2254 | /* Wait for the timer to stop. This avoids problems with race |
2232 | conditions removing the timer here. */ | 2255 | conditions removing the timer here. */ |
2233 | while (!new_smi->timer_stopped) { | 2256 | while (! new_smi->timer_stopped) { |
2234 | set_current_state(TASK_UNINTERRUPTIBLE); | 2257 | set_current_state(TASK_UNINTERRUPTIBLE); |
2235 | schedule_timeout(1); | 2258 | schedule_timeout(1); |
2236 | } | 2259 | } |
@@ -2270,7 +2293,7 @@ static __init int init_ipmi_si(void) | |||
2270 | /* Parse out the si_type string into its components. */ | 2293 | /* Parse out the si_type string into its components. */ |
2271 | str = si_type_str; | 2294 | str = si_type_str; |
2272 | if (*str != '\0') { | 2295 | if (*str != '\0') { |
2273 | for (i=0; (i<SI_MAX_PARMS) && (*str != '\0'); i++) { | 2296 | for (i = 0; (i < SI_MAX_PARMS) && (*str != '\0'); i++) { |
2274 | si_type[i] = str; | 2297 | si_type[i] = str; |
2275 | str = strchr(str, ','); | 2298 | str = strchr(str, ','); |
2276 | if (str) { | 2299 | if (str) { |
@@ -2282,22 +2305,14 @@ static __init int init_ipmi_si(void) | |||
2282 | } | 2305 | } |
2283 | } | 2306 | } |
2284 | 2307 | ||
2285 | printk(KERN_INFO "IPMI System Interface driver version " | 2308 | printk(KERN_INFO "IPMI System Interface driver.\n"); |
2286 | IPMI_SI_VERSION); | ||
2287 | if (kcs_smi_handlers.version) | ||
2288 | printk(", KCS version %s", kcs_smi_handlers.version); | ||
2289 | if (smic_smi_handlers.version) | ||
2290 | printk(", SMIC version %s", smic_smi_handlers.version); | ||
2291 | if (bt_smi_handlers.version) | ||
2292 | printk(", BT version %s", bt_smi_handlers.version); | ||
2293 | printk("\n"); | ||
2294 | 2309 | ||
2295 | #ifdef CONFIG_X86 | 2310 | #ifdef CONFIG_X86 |
2296 | dmi_decode(); | 2311 | dmi_find_bmc(); |
2297 | #endif | 2312 | #endif |
2298 | 2313 | ||
2299 | rv = init_one_smi(0, &(smi_infos[pos])); | 2314 | rv = init_one_smi(0, &(smi_infos[pos])); |
2300 | if (rv && !ports[0] && si_trydefaults) { | 2315 | if (rv && ! ports[0] && si_trydefaults) { |
2301 | /* If we are trying defaults and the initial port is | 2316 | /* If we are trying defaults and the initial port is |
2302 | not set, then set it. */ | 2317 | not set, then set it. */ |
2303 | si_type[0] = "kcs"; | 2318 | si_type[0] = "kcs"; |
@@ -2319,7 +2334,7 @@ static __init int init_ipmi_si(void) | |||
2319 | if (rv == 0) | 2334 | if (rv == 0) |
2320 | pos++; | 2335 | pos++; |
2321 | 2336 | ||
2322 | for (i=1; i < SI_MAX_PARMS; i++) { | 2337 | for (i = 1; i < SI_MAX_PARMS; i++) { |
2323 | rv = init_one_smi(i, &(smi_infos[pos])); | 2338 | rv = init_one_smi(i, &(smi_infos[pos])); |
2324 | if (rv == 0) | 2339 | if (rv == 0) |
2325 | pos++; | 2340 | pos++; |
@@ -2361,14 +2376,14 @@ static void __exit cleanup_one_si(struct smi_info *to_clean) | |||
2361 | 2376 | ||
2362 | /* Wait for the timer to stop. This avoids problems with race | 2377 | /* Wait for the timer to stop. This avoids problems with race |
2363 | conditions removing the timer here. */ | 2378 | conditions removing the timer here. */ |
2364 | while (!to_clean->timer_stopped) { | 2379 | while (! to_clean->timer_stopped) { |
2365 | set_current_state(TASK_UNINTERRUPTIBLE); | 2380 | set_current_state(TASK_UNINTERRUPTIBLE); |
2366 | schedule_timeout(1); | 2381 | schedule_timeout(1); |
2367 | } | 2382 | } |
2368 | 2383 | ||
2369 | /* Interrupts and timeouts are stopped, now make sure the | 2384 | /* Interrupts and timeouts are stopped, now make sure the |
2370 | interface is in a clean state. */ | 2385 | interface is in a clean state. */ |
2371 | while ((to_clean->curr_msg) || (to_clean->si_state != SI_NORMAL)) { | 2386 | while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { |
2372 | poll(to_clean); | 2387 | poll(to_clean); |
2373 | set_current_state(TASK_UNINTERRUPTIBLE); | 2388 | set_current_state(TASK_UNINTERRUPTIBLE); |
2374 | schedule_timeout(1); | 2389 | schedule_timeout(1); |
@@ -2392,13 +2407,15 @@ static __exit void cleanup_ipmi_si(void) | |||
2392 | { | 2407 | { |
2393 | int i; | 2408 | int i; |
2394 | 2409 | ||
2395 | if (!initialized) | 2410 | if (! initialized) |
2396 | return; | 2411 | return; |
2397 | 2412 | ||
2398 | for (i=0; i<SI_MAX_DRIVERS; i++) { | 2413 | for (i = 0; i < SI_MAX_DRIVERS; i++) { |
2399 | cleanup_one_si(smi_infos[i]); | 2414 | cleanup_one_si(smi_infos[i]); |
2400 | } | 2415 | } |
2401 | } | 2416 | } |
2402 | module_exit(cleanup_ipmi_si); | 2417 | module_exit(cleanup_ipmi_si); |
2403 | 2418 | ||
2404 | MODULE_LICENSE("GPL"); | 2419 | MODULE_LICENSE("GPL"); |
2420 | MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); | ||
2421 | MODULE_DESCRIPTION("Interface to the IPMI driver for the KCS, SMIC, and BT system interfaces."); | ||
diff --git a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c index ae18747e670b..add2aa2732f0 100644 --- a/drivers/char/ipmi/ipmi_smic_sm.c +++ b/drivers/char/ipmi/ipmi_smic_sm.c | |||
@@ -46,8 +46,6 @@ | |||
46 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ | 46 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ |
47 | #include "ipmi_si_sm.h" | 47 | #include "ipmi_si_sm.h" |
48 | 48 | ||
49 | #define IPMI_SMIC_VERSION "v33" | ||
50 | |||
51 | /* smic_debug is a bit-field | 49 | /* smic_debug is a bit-field |
52 | * SMIC_DEBUG_ENABLE - turned on for now | 50 | * SMIC_DEBUG_ENABLE - turned on for now |
53 | * SMIC_DEBUG_MSG - commands and their responses | 51 | * SMIC_DEBUG_MSG - commands and their responses |
@@ -588,7 +586,6 @@ static int smic_size(void) | |||
588 | 586 | ||
589 | struct si_sm_handlers smic_smi_handlers = | 587 | struct si_sm_handlers smic_smi_handlers = |
590 | { | 588 | { |
591 | .version = IPMI_SMIC_VERSION, | ||
592 | .init_data = init_smic_data, | 589 | .init_data = init_smic_data, |
593 | .start_transaction = start_smic_transaction, | 590 | .start_transaction = start_smic_transaction, |
594 | .get_result = smic_get_result, | 591 | .get_result = smic_get_result, |
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index d35a953961cb..e71aaae855ad 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
@@ -53,8 +53,6 @@ | |||
53 | 53 | ||
54 | #define PFX "IPMI Watchdog: " | 54 | #define PFX "IPMI Watchdog: " |
55 | 55 | ||
56 | #define IPMI_WATCHDOG_VERSION "v33" | ||
57 | |||
58 | /* | 56 | /* |
59 | * The IPMI command/response information for the watchdog timer. | 57 | * The IPMI command/response information for the watchdog timer. |
60 | */ | 58 | */ |
@@ -259,7 +257,7 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, | |||
259 | 257 | ||
260 | data[1] = 0; | 258 | data[1] = 0; |
261 | WDOG_SET_TIMEOUT_ACT(data[1], ipmi_watchdog_state); | 259 | WDOG_SET_TIMEOUT_ACT(data[1], ipmi_watchdog_state); |
262 | if (pretimeout > 0) { | 260 | if ((pretimeout > 0) && (ipmi_watchdog_state != WDOG_TIMEOUT_NONE)) { |
263 | WDOG_SET_PRETIMEOUT_ACT(data[1], preaction_val); | 261 | WDOG_SET_PRETIMEOUT_ACT(data[1], preaction_val); |
264 | data[2] = pretimeout; | 262 | data[2] = pretimeout; |
265 | } else { | 263 | } else { |
@@ -659,19 +657,18 @@ static ssize_t ipmi_read(struct file *file, | |||
659 | 657 | ||
660 | static int ipmi_open(struct inode *ino, struct file *filep) | 658 | static int ipmi_open(struct inode *ino, struct file *filep) |
661 | { | 659 | { |
662 | switch (iminor(ino)) | 660 | switch (iminor(ino)) { |
663 | { | 661 | case WATCHDOG_MINOR: |
664 | case WATCHDOG_MINOR: | 662 | if (test_and_set_bit(0, &ipmi_wdog_open)) |
665 | if(test_and_set_bit(0, &ipmi_wdog_open)) | ||
666 | return -EBUSY; | 663 | return -EBUSY; |
667 | 664 | ||
668 | /* Don't start the timer now, let it start on the | 665 | /* Don't start the timer now, let it start on the |
669 | first heartbeat. */ | 666 | first heartbeat. */ |
670 | ipmi_start_timer_on_heartbeat = 1; | 667 | ipmi_start_timer_on_heartbeat = 1; |
671 | return nonseekable_open(ino, filep); | 668 | return nonseekable_open(ino, filep); |
672 | 669 | ||
673 | default: | 670 | default: |
674 | return (-ENODEV); | 671 | return (-ENODEV); |
675 | } | 672 | } |
676 | } | 673 | } |
677 | 674 | ||
@@ -817,15 +814,19 @@ static void ipmi_register_watchdog(int ipmi_intf) | |||
817 | static int | 814 | static int |
818 | ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled) | 815 | ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled) |
819 | { | 816 | { |
817 | /* If we are not expecting a timeout, ignore it. */ | ||
818 | if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) | ||
819 | return NOTIFY_DONE; | ||
820 | |||
820 | /* If no one else handled the NMI, we assume it was the IPMI | 821 | /* If no one else handled the NMI, we assume it was the IPMI |
821 | watchdog. */ | 822 | watchdog. */ |
822 | if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) | 823 | if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) { |
824 | /* On some machines, the heartbeat will give | ||
825 | an error and not work unless we re-enable | ||
826 | the timer. So do so. */ | ||
827 | pretimeout_since_last_heartbeat = 1; | ||
823 | panic(PFX "pre-timeout"); | 828 | panic(PFX "pre-timeout"); |
824 | 829 | } | |
825 | /* On some machines, the heartbeat will give | ||
826 | an error and not work unless we re-enable | ||
827 | the timer. So do so. */ | ||
828 | pretimeout_since_last_heartbeat = 1; | ||
829 | 830 | ||
830 | return NOTIFY_DONE; | 831 | return NOTIFY_DONE; |
831 | } | 832 | } |
@@ -924,9 +925,6 @@ static int __init ipmi_wdog_init(void) | |||
924 | { | 925 | { |
925 | int rv; | 926 | int rv; |
926 | 927 | ||
927 | printk(KERN_INFO PFX "driver version " | ||
928 | IPMI_WATCHDOG_VERSION "\n"); | ||
929 | |||
930 | if (strcmp(action, "reset") == 0) { | 928 | if (strcmp(action, "reset") == 0) { |
931 | action_val = WDOG_TIMEOUT_RESET; | 929 | action_val = WDOG_TIMEOUT_RESET; |
932 | } else if (strcmp(action, "none") == 0) { | 930 | } else if (strcmp(action, "none") == 0) { |
@@ -1011,6 +1009,8 @@ static int __init ipmi_wdog_init(void) | |||
1011 | register_reboot_notifier(&wdog_reboot_notifier); | 1009 | register_reboot_notifier(&wdog_reboot_notifier); |
1012 | notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier); | 1010 | notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier); |
1013 | 1011 | ||
1012 | printk(KERN_INFO PFX "driver initialized\n"); | ||
1013 | |||
1014 | return 0; | 1014 | return 0; |
1015 | } | 1015 | } |
1016 | 1016 | ||
@@ -1062,3 +1062,5 @@ static void __exit ipmi_wdog_exit(void) | |||
1062 | module_exit(ipmi_wdog_exit); | 1062 | module_exit(ipmi_wdog_exit); |
1063 | module_init(ipmi_wdog_init); | 1063 | module_init(ipmi_wdog_init); |
1064 | MODULE_LICENSE("GPL"); | 1064 | MODULE_LICENSE("GPL"); |
1065 | MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>"); | ||
1066 | MODULE_DESCRIPTION("watchdog timer based upon the IPMI interface."); | ||
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c index 115dbb35334b..3fa64c631108 100644 --- a/drivers/char/mbcs.c +++ b/drivers/char/mbcs.c | |||
@@ -750,7 +750,7 @@ static int mbcs_probe(struct cx_dev *dev, const struct cx_device_id *id) | |||
750 | 750 | ||
751 | dev->soft = NULL; | 751 | dev->soft = NULL; |
752 | 752 | ||
753 | soft = kcalloc(1, sizeof(struct mbcs_soft), GFP_KERNEL); | 753 | soft = kzalloc(sizeof(struct mbcs_soft), GFP_KERNEL); |
754 | if (soft == NULL) | 754 | if (soft == NULL) |
755 | return -ENOMEM; | 755 | return -ENOMEM; |
756 | 756 | ||
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 850a78c9c4bc..f182752fe918 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -35,10 +35,6 @@ | |||
35 | # include <linux/efi.h> | 35 | # include <linux/efi.h> |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | #if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR) | ||
39 | extern void tapechar_init(void); | ||
40 | #endif | ||
41 | |||
42 | /* | 38 | /* |
43 | * Architectures vary in how they handle caching for addresses | 39 | * Architectures vary in how they handle caching for addresses |
44 | * outside of main memory. | 40 | * outside of main memory. |
diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 931efd58f87a..0c8375165e29 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c | |||
@@ -63,8 +63,6 @@ static DECLARE_MUTEX(misc_sem); | |||
63 | #define DYNAMIC_MINORS 64 /* like dynamic majors */ | 63 | #define DYNAMIC_MINORS 64 /* like dynamic majors */ |
64 | static unsigned char misc_minors[DYNAMIC_MINORS / 8]; | 64 | static unsigned char misc_minors[DYNAMIC_MINORS / 8]; |
65 | 65 | ||
66 | extern int rtc_DP8570A_init(void); | ||
67 | extern int rtc_MK48T08_init(void); | ||
68 | extern int pmu_device_init(void); | 66 | extern int pmu_device_init(void); |
69 | 67 | ||
70 | #ifdef CONFIG_PROC_FS | 68 | #ifdef CONFIG_PROC_FS |
@@ -303,12 +301,7 @@ static int __init misc_init(void) | |||
303 | misc_class = class_create(THIS_MODULE, "misc"); | 301 | misc_class = class_create(THIS_MODULE, "misc"); |
304 | if (IS_ERR(misc_class)) | 302 | if (IS_ERR(misc_class)) |
305 | return PTR_ERR(misc_class); | 303 | return PTR_ERR(misc_class); |
306 | #ifdef CONFIG_MVME16x | 304 | |
307 | rtc_MK48T08_init(); | ||
308 | #endif | ||
309 | #ifdef CONFIG_BVME6000 | ||
310 | rtc_DP8570A_init(); | ||
311 | #endif | ||
312 | if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { | 305 | if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { |
313 | printk("unable to get major %d for misc devices\n", | 306 | printk("unable to get major %d for misc devices\n", |
314 | MISC_MAJOR); | 307 | MISC_MAJOR); |
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index cefbe985e55c..36ae9ad2598c 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c | |||
@@ -98,12 +98,13 @@ MODULE_PARM_DESC(useinput, | |||
98 | 98 | ||
99 | #define SONYPI_DEVICE_MODEL_TYPE1 1 | 99 | #define SONYPI_DEVICE_MODEL_TYPE1 1 |
100 | #define SONYPI_DEVICE_MODEL_TYPE2 2 | 100 | #define SONYPI_DEVICE_MODEL_TYPE2 2 |
101 | #define SONYPI_DEVICE_MODEL_TYPE3 3 | ||
101 | 102 | ||
102 | /* type1 models use those */ | 103 | /* type1 models use those */ |
103 | #define SONYPI_IRQ_PORT 0x8034 | 104 | #define SONYPI_IRQ_PORT 0x8034 |
104 | #define SONYPI_IRQ_SHIFT 22 | 105 | #define SONYPI_IRQ_SHIFT 22 |
105 | #define SONYPI_BASE 0x50 | 106 | #define SONYPI_TYPE1_BASE 0x50 |
106 | #define SONYPI_G10A (SONYPI_BASE+0x14) | 107 | #define SONYPI_G10A (SONYPI_TYPE1_BASE+0x14) |
107 | #define SONYPI_TYPE1_REGION_SIZE 0x08 | 108 | #define SONYPI_TYPE1_REGION_SIZE 0x08 |
108 | #define SONYPI_TYPE1_EVTYPE_OFFSET 0x04 | 109 | #define SONYPI_TYPE1_EVTYPE_OFFSET 0x04 |
109 | 110 | ||
@@ -114,6 +115,13 @@ MODULE_PARM_DESC(useinput, | |||
114 | #define SONYPI_TYPE2_REGION_SIZE 0x20 | 115 | #define SONYPI_TYPE2_REGION_SIZE 0x20 |
115 | #define SONYPI_TYPE2_EVTYPE_OFFSET 0x12 | 116 | #define SONYPI_TYPE2_EVTYPE_OFFSET 0x12 |
116 | 117 | ||
118 | /* type3 series specifics */ | ||
119 | #define SONYPI_TYPE3_BASE 0x40 | ||
120 | #define SONYPI_TYPE3_GID2 (SONYPI_TYPE3_BASE+0x48) /* 16 bits */ | ||
121 | #define SONYPI_TYPE3_MISC (SONYPI_TYPE3_BASE+0x6d) /* 8 bits */ | ||
122 | #define SONYPI_TYPE3_REGION_SIZE 0x20 | ||
123 | #define SONYPI_TYPE3_EVTYPE_OFFSET 0x12 | ||
124 | |||
117 | /* battery / brightness addresses */ | 125 | /* battery / brightness addresses */ |
118 | #define SONYPI_BAT_FLAGS 0x81 | 126 | #define SONYPI_BAT_FLAGS 0x81 |
119 | #define SONYPI_LCD_LIGHT 0x96 | 127 | #define SONYPI_LCD_LIGHT 0x96 |
@@ -159,6 +167,10 @@ static struct sonypi_ioport_list sonypi_type2_ioport_list[] = { | |||
159 | { 0x0, 0x0 } | 167 | { 0x0, 0x0 } |
160 | }; | 168 | }; |
161 | 169 | ||
170 | /* same as in type 2 models */ | ||
171 | static struct sonypi_ioport_list *sonypi_type3_ioport_list = | ||
172 | sonypi_type2_ioport_list; | ||
173 | |||
162 | /* The set of possible interrupts */ | 174 | /* The set of possible interrupts */ |
163 | struct sonypi_irq_list { | 175 | struct sonypi_irq_list { |
164 | u16 irq; | 176 | u16 irq; |
@@ -180,6 +192,9 @@ static struct sonypi_irq_list sonypi_type2_irq_list[] = { | |||
180 | { 0, 0x00 } /* no IRQ, 0x00 in SIRQ in AML */ | 192 | { 0, 0x00 } /* no IRQ, 0x00 in SIRQ in AML */ |
181 | }; | 193 | }; |
182 | 194 | ||
195 | /* same as in type2 models */ | ||
196 | static struct sonypi_irq_list *sonypi_type3_irq_list = sonypi_type2_irq_list; | ||
197 | |||
183 | #define SONYPI_CAMERA_BRIGHTNESS 0 | 198 | #define SONYPI_CAMERA_BRIGHTNESS 0 |
184 | #define SONYPI_CAMERA_CONTRAST 1 | 199 | #define SONYPI_CAMERA_CONTRAST 1 |
185 | #define SONYPI_CAMERA_HUE 2 | 200 | #define SONYPI_CAMERA_HUE 2 |
@@ -223,6 +238,7 @@ static struct sonypi_irq_list sonypi_type2_irq_list[] = { | |||
223 | #define SONYPI_MEYE_MASK 0x00000400 | 238 | #define SONYPI_MEYE_MASK 0x00000400 |
224 | #define SONYPI_MEMORYSTICK_MASK 0x00000800 | 239 | #define SONYPI_MEMORYSTICK_MASK 0x00000800 |
225 | #define SONYPI_BATTERY_MASK 0x00001000 | 240 | #define SONYPI_BATTERY_MASK 0x00001000 |
241 | #define SONYPI_WIRELESS_MASK 0x00002000 | ||
226 | 242 | ||
227 | struct sonypi_event { | 243 | struct sonypi_event { |
228 | u8 data; | 244 | u8 data; |
@@ -305,6 +321,13 @@ static struct sonypi_event sonypi_blueev[] = { | |||
305 | { 0, 0 } | 321 | { 0, 0 } |
306 | }; | 322 | }; |
307 | 323 | ||
324 | /* The set of possible wireless events */ | ||
325 | static struct sonypi_event sonypi_wlessev[] = { | ||
326 | { 0x59, SONYPI_EVENT_WIRELESS_ON }, | ||
327 | { 0x5a, SONYPI_EVENT_WIRELESS_OFF }, | ||
328 | { 0, 0 } | ||
329 | }; | ||
330 | |||
308 | /* The set of possible back button events */ | 331 | /* The set of possible back button events */ |
309 | static struct sonypi_event sonypi_backev[] = { | 332 | static struct sonypi_event sonypi_backev[] = { |
310 | { 0x20, SONYPI_EVENT_BACK_PRESSED }, | 333 | { 0x20, SONYPI_EVENT_BACK_PRESSED }, |
@@ -383,7 +406,6 @@ static struct sonypi_eventtypes { | |||
383 | { SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, | 406 | { SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, |
384 | { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev }, | 407 | { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev }, |
385 | { SONYPI_DEVICE_MODEL_TYPE2, 0x11, SONYPI_BACK_MASK, sonypi_backev }, | 408 | { SONYPI_DEVICE_MODEL_TYPE2, 0x11, SONYPI_BACK_MASK, sonypi_backev }, |
386 | { SONYPI_DEVICE_MODEL_TYPE2, 0x08, SONYPI_HELP_MASK, sonypi_helpev }, | ||
387 | { SONYPI_DEVICE_MODEL_TYPE2, 0x21, SONYPI_HELP_MASK, sonypi_helpev }, | 409 | { SONYPI_DEVICE_MODEL_TYPE2, 0x21, SONYPI_HELP_MASK, sonypi_helpev }, |
388 | { SONYPI_DEVICE_MODEL_TYPE2, 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev }, | 410 | { SONYPI_DEVICE_MODEL_TYPE2, 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev }, |
389 | { SONYPI_DEVICE_MODEL_TYPE2, 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev }, | 411 | { SONYPI_DEVICE_MODEL_TYPE2, 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev }, |
@@ -391,6 +413,12 @@ static struct sonypi_eventtypes { | |||
391 | { SONYPI_DEVICE_MODEL_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, | 413 | { SONYPI_DEVICE_MODEL_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, |
392 | { SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, | 414 | { SONYPI_DEVICE_MODEL_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, |
393 | 415 | ||
416 | { SONYPI_DEVICE_MODEL_TYPE3, 0, 0xffffffff, sonypi_releaseev }, | ||
417 | { SONYPI_DEVICE_MODEL_TYPE3, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, | ||
418 | { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, | ||
419 | { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, | ||
420 | { SONYPI_DEVICE_MODEL_TYPE3, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, | ||
421 | { SONYPI_DEVICE_MODEL_TYPE3, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, | ||
394 | { 0 } | 422 | { 0 } |
395 | }; | 423 | }; |
396 | 424 | ||
@@ -563,6 +591,23 @@ static void sonypi_type2_srs(void) | |||
563 | udelay(10); | 591 | udelay(10); |
564 | } | 592 | } |
565 | 593 | ||
594 | static void sonypi_type3_srs(void) | ||
595 | { | ||
596 | u16 v16; | ||
597 | u8 v8; | ||
598 | |||
599 | /* This model type uses the same initialiazation of | ||
600 | * the embedded controller as the type2 models. */ | ||
601 | sonypi_type2_srs(); | ||
602 | |||
603 | /* Initialization of PCI config space of the LPC interface bridge. */ | ||
604 | v16 = (sonypi_device.ioport1 & 0xFFF0) | 0x01; | ||
605 | pci_write_config_word(sonypi_device.dev, SONYPI_TYPE3_GID2, v16); | ||
606 | pci_read_config_byte(sonypi_device.dev, SONYPI_TYPE3_MISC, &v8); | ||
607 | v8 = (v8 & 0xCF) | 0x10; | ||
608 | pci_write_config_byte(sonypi_device.dev, SONYPI_TYPE3_MISC, v8); | ||
609 | } | ||
610 | |||
566 | /* Disables the device - this comes from the AML code in the ACPI bios */ | 611 | /* Disables the device - this comes from the AML code in the ACPI bios */ |
567 | static void sonypi_type1_dis(void) | 612 | static void sonypi_type1_dis(void) |
568 | { | 613 | { |
@@ -587,6 +632,13 @@ static void sonypi_type2_dis(void) | |||
587 | printk(KERN_WARNING "ec_write failed\n"); | 632 | printk(KERN_WARNING "ec_write failed\n"); |
588 | } | 633 | } |
589 | 634 | ||
635 | static void sonypi_type3_dis(void) | ||
636 | { | ||
637 | sonypi_type2_dis(); | ||
638 | udelay(10); | ||
639 | pci_write_config_word(sonypi_device.dev, SONYPI_TYPE3_GID2, 0); | ||
640 | } | ||
641 | |||
590 | static u8 sonypi_call1(u8 dev) | 642 | static u8 sonypi_call1(u8 dev) |
591 | { | 643 | { |
592 | u8 v1, v2; | 644 | u8 v1, v2; |
@@ -1067,10 +1119,17 @@ static struct miscdevice sonypi_misc_device = { | |||
1067 | 1119 | ||
1068 | static void sonypi_enable(unsigned int camera_on) | 1120 | static void sonypi_enable(unsigned int camera_on) |
1069 | { | 1121 | { |
1070 | if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) | 1122 | switch (sonypi_device.model) { |
1071 | sonypi_type2_srs(); | 1123 | case SONYPI_DEVICE_MODEL_TYPE1: |
1072 | else | ||
1073 | sonypi_type1_srs(); | 1124 | sonypi_type1_srs(); |
1125 | break; | ||
1126 | case SONYPI_DEVICE_MODEL_TYPE2: | ||
1127 | sonypi_type2_srs(); | ||
1128 | break; | ||
1129 | case SONYPI_DEVICE_MODEL_TYPE3: | ||
1130 | sonypi_type3_srs(); | ||
1131 | break; | ||
1132 | } | ||
1074 | 1133 | ||
1075 | sonypi_call1(0x82); | 1134 | sonypi_call1(0x82); |
1076 | sonypi_call2(0x81, 0xff); | 1135 | sonypi_call2(0x81, 0xff); |
@@ -1094,10 +1153,18 @@ static int sonypi_disable(void) | |||
1094 | if (!SONYPI_ACPI_ACTIVE && fnkeyinit) | 1153 | if (!SONYPI_ACPI_ACTIVE && fnkeyinit) |
1095 | outb(0xf1, 0xb2); | 1154 | outb(0xf1, 0xb2); |
1096 | 1155 | ||
1097 | if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) | 1156 | switch (sonypi_device.model) { |
1098 | sonypi_type2_dis(); | 1157 | case SONYPI_DEVICE_MODEL_TYPE1: |
1099 | else | ||
1100 | sonypi_type1_dis(); | 1158 | sonypi_type1_dis(); |
1159 | break; | ||
1160 | case SONYPI_DEVICE_MODEL_TYPE2: | ||
1161 | sonypi_type2_dis(); | ||
1162 | break; | ||
1163 | case SONYPI_DEVICE_MODEL_TYPE3: | ||
1164 | sonypi_type3_dis(); | ||
1165 | break; | ||
1166 | } | ||
1167 | |||
1101 | return 0; | 1168 | return 0; |
1102 | } | 1169 | } |
1103 | 1170 | ||
@@ -1143,12 +1210,16 @@ static int __devinit sonypi_probe(void) | |||
1143 | struct sonypi_irq_list *irq_list; | 1210 | struct sonypi_irq_list *irq_list; |
1144 | struct pci_dev *pcidev; | 1211 | struct pci_dev *pcidev; |
1145 | 1212 | ||
1146 | pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1213 | if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, |
1147 | PCI_DEVICE_ID_INTEL_82371AB_3, NULL); | 1214 | PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) |
1215 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1; | ||
1216 | else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1217 | PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) | ||
1218 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3; | ||
1219 | else | ||
1220 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2; | ||
1148 | 1221 | ||
1149 | sonypi_device.dev = pcidev; | 1222 | sonypi_device.dev = pcidev; |
1150 | sonypi_device.model = pcidev ? | ||
1151 | SONYPI_DEVICE_MODEL_TYPE1 : SONYPI_DEVICE_MODEL_TYPE2; | ||
1152 | 1223 | ||
1153 | spin_lock_init(&sonypi_device.fifo_lock); | 1224 | spin_lock_init(&sonypi_device.fifo_lock); |
1154 | sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, | 1225 | sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, |
@@ -1176,16 +1247,22 @@ static int __devinit sonypi_probe(void) | |||
1176 | goto out_miscreg; | 1247 | goto out_miscreg; |
1177 | } | 1248 | } |
1178 | 1249 | ||
1179 | if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) { | 1250 | |
1251 | if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) { | ||
1252 | ioport_list = sonypi_type1_ioport_list; | ||
1253 | sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE; | ||
1254 | sonypi_device.evtype_offset = SONYPI_TYPE1_EVTYPE_OFFSET; | ||
1255 | irq_list = sonypi_type1_irq_list; | ||
1256 | } else if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2) { | ||
1180 | ioport_list = sonypi_type2_ioport_list; | 1257 | ioport_list = sonypi_type2_ioport_list; |
1181 | sonypi_device.region_size = SONYPI_TYPE2_REGION_SIZE; | 1258 | sonypi_device.region_size = SONYPI_TYPE2_REGION_SIZE; |
1182 | sonypi_device.evtype_offset = SONYPI_TYPE2_EVTYPE_OFFSET; | 1259 | sonypi_device.evtype_offset = SONYPI_TYPE2_EVTYPE_OFFSET; |
1183 | irq_list = sonypi_type2_irq_list; | 1260 | irq_list = sonypi_type2_irq_list; |
1184 | } else { | 1261 | } else { |
1185 | ioport_list = sonypi_type1_ioport_list; | 1262 | ioport_list = sonypi_type3_ioport_list; |
1186 | sonypi_device.region_size = SONYPI_TYPE1_REGION_SIZE; | 1263 | sonypi_device.region_size = SONYPI_TYPE3_REGION_SIZE; |
1187 | sonypi_device.evtype_offset = SONYPI_TYPE1_EVTYPE_OFFSET; | 1264 | sonypi_device.evtype_offset = SONYPI_TYPE3_EVTYPE_OFFSET; |
1188 | irq_list = sonypi_type1_irq_list; | 1265 | irq_list = sonypi_type3_irq_list; |
1189 | } | 1266 | } |
1190 | 1267 | ||
1191 | for (i = 0; ioport_list[i].port1; i++) { | 1268 | for (i = 0; ioport_list[i].port1; i++) { |
@@ -1274,11 +1351,10 @@ static int __devinit sonypi_probe(void) | |||
1274 | 1351 | ||
1275 | printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver" | 1352 | printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver" |
1276 | "v%s.\n", SONYPI_DRIVER_VERSION); | 1353 | "v%s.\n", SONYPI_DRIVER_VERSION); |
1277 | printk(KERN_INFO "sonypi: detected %s model, " | 1354 | printk(KERN_INFO "sonypi: detected type%d model, " |
1278 | "verbose = %d, fnkeyinit = %s, camera = %s, " | 1355 | "verbose = %d, fnkeyinit = %s, camera = %s, " |
1279 | "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n", | 1356 | "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n", |
1280 | (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) ? | 1357 | sonypi_device.model, |
1281 | "type1" : "type2", | ||
1282 | verbose, | 1358 | verbose, |
1283 | fnkeyinit ? "on" : "off", | 1359 | fnkeyinit ? "on" : "off", |
1284 | camera ? "on" : "off", | 1360 | camera ? "on" : "off", |
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index cc2cc77fd174..c0d64914595f 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c | |||
@@ -206,6 +206,9 @@ static struct pci_device_id tpm_pci_tbl[] __devinitdata = { | |||
206 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)}, | 206 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)}, |
207 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)}, | 207 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)}, |
208 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)}, | 208 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)}, |
209 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)}, | ||
210 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)}, | ||
211 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)}, | ||
209 | {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)}, | 212 | {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)}, |
210 | {PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)}, | 213 | {PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)}, |
211 | {0,} | 214 | {0,} |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 6e4be3bb2d89..9d657127f313 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -153,7 +153,6 @@ static int tty_release(struct inode *, struct file *); | |||
153 | int tty_ioctl(struct inode * inode, struct file * file, | 153 | int tty_ioctl(struct inode * inode, struct file * file, |
154 | unsigned int cmd, unsigned long arg); | 154 | unsigned int cmd, unsigned long arg); |
155 | static int tty_fasync(int fd, struct file * filp, int on); | 155 | static int tty_fasync(int fd, struct file * filp, int on); |
156 | extern void rs_360_init(void); | ||
157 | static void release_mem(struct tty_struct *tty, int idx); | 156 | static void release_mem(struct tty_struct *tty, int idx); |
158 | 157 | ||
159 | 158 | ||
@@ -2911,11 +2910,6 @@ void __init console_init(void) | |||
2911 | #ifdef CONFIG_EARLY_PRINTK | 2910 | #ifdef CONFIG_EARLY_PRINTK |
2912 | disable_early_printk(); | 2911 | disable_early_printk(); |
2913 | #endif | 2912 | #endif |
2914 | #ifdef CONFIG_SERIAL_68360 | ||
2915 | /* This is not a console initcall. I know not what it's doing here. | ||
2916 | So I haven't moved it. dwmw2 */ | ||
2917 | rs_360_init(); | ||
2918 | #endif | ||
2919 | call = __con_initcall_start; | 2913 | call = __con_initcall_start; |
2920 | while (call < __con_initcall_end) { | 2914 | while (call < __con_initcall_end) { |
2921 | (*call)(); | 2915 | (*call)(); |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 665103ccaee8..b8d0c290b0db 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -434,21 +434,25 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed) | |||
434 | /* used by selection: complement pointer position */ | 434 | /* used by selection: complement pointer position */ |
435 | void complement_pos(struct vc_data *vc, int offset) | 435 | void complement_pos(struct vc_data *vc, int offset) |
436 | { | 436 | { |
437 | static unsigned short *p; | 437 | static int old_offset = -1; |
438 | static unsigned short old; | 438 | static unsigned short old; |
439 | static unsigned short oldx, oldy; | 439 | static unsigned short oldx, oldy; |
440 | 440 | ||
441 | WARN_CONSOLE_UNLOCKED(); | 441 | WARN_CONSOLE_UNLOCKED(); |
442 | 442 | ||
443 | if (p) { | 443 | if (old_offset != -1 && old_offset >= 0 && |
444 | scr_writew(old, p); | 444 | old_offset < vc->vc_screenbuf_size) { |
445 | scr_writew(old, screenpos(vc, old_offset, 1)); | ||
445 | if (DO_UPDATE(vc)) | 446 | if (DO_UPDATE(vc)) |
446 | vc->vc_sw->con_putc(vc, old, oldy, oldx); | 447 | vc->vc_sw->con_putc(vc, old, oldy, oldx); |
447 | } | 448 | } |
448 | if (offset == -1) | 449 | |
449 | p = NULL; | 450 | old_offset = offset; |
450 | else { | 451 | |
452 | if (offset != -1 && offset >= 0 && | ||
453 | offset < vc->vc_screenbuf_size) { | ||
451 | unsigned short new; | 454 | unsigned short new; |
455 | unsigned short *p; | ||
452 | p = screenpos(vc, offset, 1); | 456 | p = screenpos(vc, offset, 1); |
453 | old = scr_readw(p); | 457 | old = scr_readw(p); |
454 | new = old ^ vc->vc_complement_mask; | 458 | new = old ^ vc->vc_complement_mask; |
@@ -459,6 +463,7 @@ void complement_pos(struct vc_data *vc, int offset) | |||
459 | vc->vc_sw->con_putc(vc, new, oldy, oldx); | 463 | vc->vc_sw->con_putc(vc, new, oldy, oldx); |
460 | } | 464 | } |
461 | } | 465 | } |
466 | |||
462 | } | 467 | } |
463 | 468 | ||
464 | static void insert_char(struct vc_data *vc, unsigned int nr) | 469 | static void insert_char(struct vc_data *vc, unsigned int nr) |
@@ -2272,7 +2277,9 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) | |||
2272 | ret = paste_selection(tty); | 2277 | ret = paste_selection(tty); |
2273 | break; | 2278 | break; |
2274 | case TIOCL_UNBLANKSCREEN: | 2279 | case TIOCL_UNBLANKSCREEN: |
2280 | acquire_console_sem(); | ||
2275 | unblank_screen(); | 2281 | unblank_screen(); |
2282 | release_console_sem(); | ||
2276 | break; | 2283 | break; |
2277 | case TIOCL_SELLOADLUT: | 2284 | case TIOCL_SELLOADLUT: |
2278 | ret = sel_loadlut(p); | 2285 | ret = sel_loadlut(p); |
@@ -2317,8 +2324,10 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) | |||
2317 | } | 2324 | } |
2318 | break; | 2325 | break; |
2319 | case TIOCL_BLANKSCREEN: /* until explicitly unblanked, not only poked */ | 2326 | case TIOCL_BLANKSCREEN: /* until explicitly unblanked, not only poked */ |
2327 | acquire_console_sem(); | ||
2320 | ignore_poke = 1; | 2328 | ignore_poke = 1; |
2321 | do_blank_screen(0); | 2329 | do_blank_screen(0); |
2330 | release_console_sem(); | ||
2322 | break; | 2331 | break; |
2323 | case TIOCL_BLANKEDSCREEN: | 2332 | case TIOCL_BLANKEDSCREEN: |
2324 | ret = console_blanked; | 2333 | ret = console_blanked; |
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 5b29c3b2a331..327b58e64875 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig | |||
@@ -58,4 +58,31 @@ config EFI_PCDP | |||
58 | 58 | ||
59 | See <http://www.dig64.org/specifications/DIG64_HCDPv20_042804.pdf> | 59 | See <http://www.dig64.org/specifications/DIG64_HCDPv20_042804.pdf> |
60 | 60 | ||
61 | config DELL_RBU | ||
62 | tristate "BIOS update support for DELL systems via sysfs" | ||
63 | select FW_LOADER | ||
64 | help | ||
65 | Say m if you want to have the option of updating the BIOS for your | ||
66 | DELL system. Note you need a Dell OpenManage or Dell Update package (DUP) | ||
67 | supporting application to comunicate with the BIOS regarding the new | ||
68 | image for the image update to take effect. | ||
69 | See <file:Documentation/dell_rbu.txt> for more details on the driver. | ||
70 | |||
71 | config DCDBAS | ||
72 | tristate "Dell Systems Management Base Driver" | ||
73 | depends on X86 || X86_64 | ||
74 | default m | ||
75 | help | ||
76 | The Dell Systems Management Base Driver provides a sysfs interface | ||
77 | for systems management software to perform System Management | ||
78 | Interrupts (SMIs) and Host Control Actions (system power cycle or | ||
79 | power off after OS shutdown) on certain Dell systems. | ||
80 | |||
81 | See <file:Documentation/dcdbas.txt> for more details on the driver | ||
82 | and the Dell systems on which Dell systems management software makes | ||
83 | use of this driver. | ||
84 | |||
85 | Say Y or M here to enable the driver for use by Dell systems | ||
86 | management software such as Dell OpenManage. | ||
87 | |||
61 | endmenu | 88 | endmenu |
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 90fd0b26db8b..85429979d0db 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile | |||
@@ -4,3 +4,5 @@ | |||
4 | obj-$(CONFIG_EDD) += edd.o | 4 | obj-$(CONFIG_EDD) += edd.o |
5 | obj-$(CONFIG_EFI_VARS) += efivars.o | 5 | obj-$(CONFIG_EFI_VARS) += efivars.o |
6 | obj-$(CONFIG_EFI_PCDP) += pcdp.o | 6 | obj-$(CONFIG_EFI_PCDP) += pcdp.o |
7 | obj-$(CONFIG_DELL_RBU) += dell_rbu.o | ||
8 | obj-$(CONFIG_DCDBAS) += dcdbas.o | ||
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c new file mode 100644 index 000000000000..955537fe9958 --- /dev/null +++ b/drivers/firmware/dcdbas.c | |||
@@ -0,0 +1,596 @@ | |||
1 | /* | ||
2 | * dcdbas.c: Dell Systems Management Base Driver | ||
3 | * | ||
4 | * The Dell Systems Management Base Driver provides a sysfs interface for | ||
5 | * systems management software to perform System Management Interrupts (SMIs) | ||
6 | * and Host Control Actions (power cycle or power off after OS shutdown) on | ||
7 | * Dell systems. | ||
8 | * | ||
9 | * See Documentation/dcdbas.txt for more information. | ||
10 | * | ||
11 | * Copyright (C) 1995-2005 Dell Inc. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License v2.0 as published by | ||
15 | * the Free Software Foundation. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | */ | ||
22 | |||
23 | #include <linux/device.h> | ||
24 | #include <linux/dma-mapping.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/mc146818rtc.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/reboot.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/smp.h> | ||
33 | #include <linux/spinlock.h> | ||
34 | #include <linux/string.h> | ||
35 | #include <linux/types.h> | ||
36 | #include <asm/io.h> | ||
37 | #include <asm/semaphore.h> | ||
38 | |||
39 | #include "dcdbas.h" | ||
40 | |||
41 | #define DRIVER_NAME "dcdbas" | ||
42 | #define DRIVER_VERSION "5.6.0-1" | ||
43 | #define DRIVER_DESCRIPTION "Dell Systems Management Base Driver" | ||
44 | |||
45 | static struct platform_device *dcdbas_pdev; | ||
46 | |||
47 | static u8 *smi_data_buf; | ||
48 | static dma_addr_t smi_data_buf_handle; | ||
49 | static unsigned long smi_data_buf_size; | ||
50 | static u32 smi_data_buf_phys_addr; | ||
51 | static DECLARE_MUTEX(smi_data_lock); | ||
52 | |||
53 | static unsigned int host_control_action; | ||
54 | static unsigned int host_control_smi_type; | ||
55 | static unsigned int host_control_on_shutdown; | ||
56 | |||
57 | /** | ||
58 | * smi_data_buf_free: free SMI data buffer | ||
59 | */ | ||
60 | static void smi_data_buf_free(void) | ||
61 | { | ||
62 | if (!smi_data_buf) | ||
63 | return; | ||
64 | |||
65 | dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n", | ||
66 | __FUNCTION__, smi_data_buf_phys_addr, smi_data_buf_size); | ||
67 | |||
68 | dma_free_coherent(&dcdbas_pdev->dev, smi_data_buf_size, smi_data_buf, | ||
69 | smi_data_buf_handle); | ||
70 | smi_data_buf = NULL; | ||
71 | smi_data_buf_handle = 0; | ||
72 | smi_data_buf_phys_addr = 0; | ||
73 | smi_data_buf_size = 0; | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * smi_data_buf_realloc: grow SMI data buffer if needed | ||
78 | */ | ||
79 | static int smi_data_buf_realloc(unsigned long size) | ||
80 | { | ||
81 | void *buf; | ||
82 | dma_addr_t handle; | ||
83 | |||
84 | if (smi_data_buf_size >= size) | ||
85 | return 0; | ||
86 | |||
87 | if (size > MAX_SMI_DATA_BUF_SIZE) | ||
88 | return -EINVAL; | ||
89 | |||
90 | /* new buffer is needed */ | ||
91 | buf = dma_alloc_coherent(&dcdbas_pdev->dev, size, &handle, GFP_KERNEL); | ||
92 | if (!buf) { | ||
93 | dev_dbg(&dcdbas_pdev->dev, | ||
94 | "%s: failed to allocate memory size %lu\n", | ||
95 | __FUNCTION__, size); | ||
96 | return -ENOMEM; | ||
97 | } | ||
98 | /* memory zeroed by dma_alloc_coherent */ | ||
99 | |||
100 | if (smi_data_buf) | ||
101 | memcpy(buf, smi_data_buf, smi_data_buf_size); | ||
102 | |||
103 | /* free any existing buffer */ | ||
104 | smi_data_buf_free(); | ||
105 | |||
106 | /* set up new buffer for use */ | ||
107 | smi_data_buf = buf; | ||
108 | smi_data_buf_handle = handle; | ||
109 | smi_data_buf_phys_addr = (u32) virt_to_phys(buf); | ||
110 | smi_data_buf_size = size; | ||
111 | |||
112 | dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n", | ||
113 | __FUNCTION__, smi_data_buf_phys_addr, smi_data_buf_size); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static ssize_t smi_data_buf_phys_addr_show(struct device *dev, | ||
119 | struct device_attribute *attr, | ||
120 | char *buf) | ||
121 | { | ||
122 | return sprintf(buf, "%x\n", smi_data_buf_phys_addr); | ||
123 | } | ||
124 | |||
125 | static ssize_t smi_data_buf_size_show(struct device *dev, | ||
126 | struct device_attribute *attr, | ||
127 | char *buf) | ||
128 | { | ||
129 | return sprintf(buf, "%lu\n", smi_data_buf_size); | ||
130 | } | ||
131 | |||
132 | static ssize_t smi_data_buf_size_store(struct device *dev, | ||
133 | struct device_attribute *attr, | ||
134 | const char *buf, size_t count) | ||
135 | { | ||
136 | unsigned long buf_size; | ||
137 | ssize_t ret; | ||
138 | |||
139 | buf_size = simple_strtoul(buf, NULL, 10); | ||
140 | |||
141 | /* make sure SMI data buffer is at least buf_size */ | ||
142 | down(&smi_data_lock); | ||
143 | ret = smi_data_buf_realloc(buf_size); | ||
144 | up(&smi_data_lock); | ||
145 | if (ret) | ||
146 | return ret; | ||
147 | |||
148 | return count; | ||
149 | } | ||
150 | |||
151 | static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos, | ||
152 | size_t count) | ||
153 | { | ||
154 | size_t max_read; | ||
155 | ssize_t ret; | ||
156 | |||
157 | down(&smi_data_lock); | ||
158 | |||
159 | if (pos >= smi_data_buf_size) { | ||
160 | ret = 0; | ||
161 | goto out; | ||
162 | } | ||
163 | |||
164 | max_read = smi_data_buf_size - pos; | ||
165 | ret = min(max_read, count); | ||
166 | memcpy(buf, smi_data_buf + pos, ret); | ||
167 | out: | ||
168 | up(&smi_data_lock); | ||
169 | return ret; | ||
170 | } | ||
171 | |||
172 | static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos, | ||
173 | size_t count) | ||
174 | { | ||
175 | ssize_t ret; | ||
176 | |||
177 | down(&smi_data_lock); | ||
178 | |||
179 | ret = smi_data_buf_realloc(pos + count); | ||
180 | if (ret) | ||
181 | goto out; | ||
182 | |||
183 | memcpy(smi_data_buf + pos, buf, count); | ||
184 | ret = count; | ||
185 | out: | ||
186 | up(&smi_data_lock); | ||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | static ssize_t host_control_action_show(struct device *dev, | ||
191 | struct device_attribute *attr, | ||
192 | char *buf) | ||
193 | { | ||
194 | return sprintf(buf, "%u\n", host_control_action); | ||
195 | } | ||
196 | |||
197 | static ssize_t host_control_action_store(struct device *dev, | ||
198 | struct device_attribute *attr, | ||
199 | const char *buf, size_t count) | ||
200 | { | ||
201 | ssize_t ret; | ||
202 | |||
203 | /* make sure buffer is available for host control command */ | ||
204 | down(&smi_data_lock); | ||
205 | ret = smi_data_buf_realloc(sizeof(struct apm_cmd)); | ||
206 | up(&smi_data_lock); | ||
207 | if (ret) | ||
208 | return ret; | ||
209 | |||
210 | host_control_action = simple_strtoul(buf, NULL, 10); | ||
211 | return count; | ||
212 | } | ||
213 | |||
214 | static ssize_t host_control_smi_type_show(struct device *dev, | ||
215 | struct device_attribute *attr, | ||
216 | char *buf) | ||
217 | { | ||
218 | return sprintf(buf, "%u\n", host_control_smi_type); | ||
219 | } | ||
220 | |||
221 | static ssize_t host_control_smi_type_store(struct device *dev, | ||
222 | struct device_attribute *attr, | ||
223 | const char *buf, size_t count) | ||
224 | { | ||
225 | host_control_smi_type = simple_strtoul(buf, NULL, 10); | ||
226 | return count; | ||
227 | } | ||
228 | |||
229 | static ssize_t host_control_on_shutdown_show(struct device *dev, | ||
230 | struct device_attribute *attr, | ||
231 | char *buf) | ||
232 | { | ||
233 | return sprintf(buf, "%u\n", host_control_on_shutdown); | ||
234 | } | ||
235 | |||
236 | static ssize_t host_control_on_shutdown_store(struct device *dev, | ||
237 | struct device_attribute *attr, | ||
238 | const char *buf, size_t count) | ||
239 | { | ||
240 | host_control_on_shutdown = simple_strtoul(buf, NULL, 10); | ||
241 | return count; | ||
242 | } | ||
243 | |||
244 | /** | ||
245 | * smi_request: generate SMI request | ||
246 | * | ||
247 | * Called with smi_data_lock. | ||
248 | */ | ||
249 | static int smi_request(struct smi_cmd *smi_cmd) | ||
250 | { | ||
251 | cpumask_t old_mask; | ||
252 | int ret = 0; | ||
253 | |||
254 | if (smi_cmd->magic != SMI_CMD_MAGIC) { | ||
255 | dev_info(&dcdbas_pdev->dev, "%s: invalid magic value\n", | ||
256 | __FUNCTION__); | ||
257 | return -EBADR; | ||
258 | } | ||
259 | |||
260 | /* SMI requires CPU 0 */ | ||
261 | old_mask = current->cpus_allowed; | ||
262 | set_cpus_allowed(current, cpumask_of_cpu(0)); | ||
263 | if (smp_processor_id() != 0) { | ||
264 | dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n", | ||
265 | __FUNCTION__); | ||
266 | ret = -EBUSY; | ||
267 | goto out; | ||
268 | } | ||
269 | |||
270 | /* generate SMI */ | ||
271 | asm volatile ( | ||
272 | "outb %b0,%w1" | ||
273 | : /* no output args */ | ||
274 | : "a" (smi_cmd->command_code), | ||
275 | "d" (smi_cmd->command_address), | ||
276 | "b" (smi_cmd->ebx), | ||
277 | "c" (smi_cmd->ecx) | ||
278 | : "memory" | ||
279 | ); | ||
280 | |||
281 | out: | ||
282 | set_cpus_allowed(current, old_mask); | ||
283 | return ret; | ||
284 | } | ||
285 | |||
286 | /** | ||
287 | * smi_request_store: | ||
288 | * | ||
289 | * The valid values are: | ||
290 | * 0: zero SMI data buffer | ||
291 | * 1: generate calling interface SMI | ||
292 | * 2: generate raw SMI | ||
293 | * | ||
294 | * User application writes smi_cmd to smi_data before telling driver | ||
295 | * to generate SMI. | ||
296 | */ | ||
297 | static ssize_t smi_request_store(struct device *dev, | ||
298 | struct device_attribute *attr, | ||
299 | const char *buf, size_t count) | ||
300 | { | ||
301 | struct smi_cmd *smi_cmd; | ||
302 | unsigned long val = simple_strtoul(buf, NULL, 10); | ||
303 | ssize_t ret; | ||
304 | |||
305 | down(&smi_data_lock); | ||
306 | |||
307 | if (smi_data_buf_size < sizeof(struct smi_cmd)) { | ||
308 | ret = -ENODEV; | ||
309 | goto out; | ||
310 | } | ||
311 | smi_cmd = (struct smi_cmd *)smi_data_buf; | ||
312 | |||
313 | switch (val) { | ||
314 | case 2: | ||
315 | /* Raw SMI */ | ||
316 | ret = smi_request(smi_cmd); | ||
317 | if (!ret) | ||
318 | ret = count; | ||
319 | break; | ||
320 | case 1: | ||
321 | /* Calling Interface SMI */ | ||
322 | smi_cmd->ebx = (u32) virt_to_phys(smi_cmd->command_buffer); | ||
323 | ret = smi_request(smi_cmd); | ||
324 | if (!ret) | ||
325 | ret = count; | ||
326 | break; | ||
327 | case 0: | ||
328 | memset(smi_data_buf, 0, smi_data_buf_size); | ||
329 | ret = count; | ||
330 | break; | ||
331 | default: | ||
332 | ret = -EINVAL; | ||
333 | break; | ||
334 | } | ||
335 | |||
336 | out: | ||
337 | up(&smi_data_lock); | ||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | /** | ||
342 | * host_control_smi: generate host control SMI | ||
343 | * | ||
344 | * Caller must set up the host control command in smi_data_buf. | ||
345 | */ | ||
346 | static int host_control_smi(void) | ||
347 | { | ||
348 | struct apm_cmd *apm_cmd; | ||
349 | u8 *data; | ||
350 | unsigned long flags; | ||
351 | u32 num_ticks; | ||
352 | s8 cmd_status; | ||
353 | u8 index; | ||
354 | |||
355 | apm_cmd = (struct apm_cmd *)smi_data_buf; | ||
356 | apm_cmd->status = ESM_STATUS_CMD_UNSUCCESSFUL; | ||
357 | |||
358 | switch (host_control_smi_type) { | ||
359 | case HC_SMITYPE_TYPE1: | ||
360 | spin_lock_irqsave(&rtc_lock, flags); | ||
361 | /* write SMI data buffer physical address */ | ||
362 | data = (u8 *)&smi_data_buf_phys_addr; | ||
363 | for (index = PE1300_CMOS_CMD_STRUCT_PTR; | ||
364 | index < (PE1300_CMOS_CMD_STRUCT_PTR + 4); | ||
365 | index++, data++) { | ||
366 | outb(index, | ||
367 | (CMOS_BASE_PORT + CMOS_PAGE2_INDEX_PORT_PIIX4)); | ||
368 | outb(*data, | ||
369 | (CMOS_BASE_PORT + CMOS_PAGE2_DATA_PORT_PIIX4)); | ||
370 | } | ||
371 | |||
372 | /* first set status to -1 as called by spec */ | ||
373 | cmd_status = ESM_STATUS_CMD_UNSUCCESSFUL; | ||
374 | outb((u8) cmd_status, PCAT_APM_STATUS_PORT); | ||
375 | |||
376 | /* generate SMM call */ | ||
377 | outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT); | ||
378 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
379 | |||
380 | /* wait a few to see if it executed */ | ||
381 | num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING; | ||
382 | while ((cmd_status = inb(PCAT_APM_STATUS_PORT)) | ||
383 | == ESM_STATUS_CMD_UNSUCCESSFUL) { | ||
384 | num_ticks--; | ||
385 | if (num_ticks == EXPIRED_TIMER) | ||
386 | return -ETIME; | ||
387 | } | ||
388 | break; | ||
389 | |||
390 | case HC_SMITYPE_TYPE2: | ||
391 | case HC_SMITYPE_TYPE3: | ||
392 | spin_lock_irqsave(&rtc_lock, flags); | ||
393 | /* write SMI data buffer physical address */ | ||
394 | data = (u8 *)&smi_data_buf_phys_addr; | ||
395 | for (index = PE1400_CMOS_CMD_STRUCT_PTR; | ||
396 | index < (PE1400_CMOS_CMD_STRUCT_PTR + 4); | ||
397 | index++, data++) { | ||
398 | outb(index, (CMOS_BASE_PORT + CMOS_PAGE1_INDEX_PORT)); | ||
399 | outb(*data, (CMOS_BASE_PORT + CMOS_PAGE1_DATA_PORT)); | ||
400 | } | ||
401 | |||
402 | /* generate SMM call */ | ||
403 | if (host_control_smi_type == HC_SMITYPE_TYPE3) | ||
404 | outb(ESM_APM_CMD, PCAT_APM_CONTROL_PORT); | ||
405 | else | ||
406 | outb(ESM_APM_CMD, PE1400_APM_CONTROL_PORT); | ||
407 | |||
408 | /* restore RTC index pointer since it was written to above */ | ||
409 | CMOS_READ(RTC_REG_C); | ||
410 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
411 | |||
412 | /* read control port back to serialize write */ | ||
413 | cmd_status = inb(PE1400_APM_CONTROL_PORT); | ||
414 | |||
415 | /* wait a few to see if it executed */ | ||
416 | num_ticks = TIMEOUT_USEC_SHORT_SEMA_BLOCKING; | ||
417 | while (apm_cmd->status == ESM_STATUS_CMD_UNSUCCESSFUL) { | ||
418 | num_ticks--; | ||
419 | if (num_ticks == EXPIRED_TIMER) | ||
420 | return -ETIME; | ||
421 | } | ||
422 | break; | ||
423 | |||
424 | default: | ||
425 | dev_dbg(&dcdbas_pdev->dev, "%s: invalid SMI type %u\n", | ||
426 | __FUNCTION__, host_control_smi_type); | ||
427 | return -ENOSYS; | ||
428 | } | ||
429 | |||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | /** | ||
434 | * dcdbas_host_control: initiate host control | ||
435 | * | ||
436 | * This function is called by the driver after the system has | ||
437 | * finished shutting down if the user application specified a | ||
438 | * host control action to perform on shutdown. It is safe to | ||
439 | * use smi_data_buf at this point because the system has finished | ||
440 | * shutting down and no userspace apps are running. | ||
441 | */ | ||
442 | static void dcdbas_host_control(void) | ||
443 | { | ||
444 | struct apm_cmd *apm_cmd; | ||
445 | u8 action; | ||
446 | |||
447 | if (host_control_action == HC_ACTION_NONE) | ||
448 | return; | ||
449 | |||
450 | action = host_control_action; | ||
451 | host_control_action = HC_ACTION_NONE; | ||
452 | |||
453 | if (!smi_data_buf) { | ||
454 | dev_dbg(&dcdbas_pdev->dev, "%s: no SMI buffer\n", __FUNCTION__); | ||
455 | return; | ||
456 | } | ||
457 | |||
458 | if (smi_data_buf_size < sizeof(struct apm_cmd)) { | ||
459 | dev_dbg(&dcdbas_pdev->dev, "%s: SMI buffer too small\n", | ||
460 | __FUNCTION__); | ||
461 | return; | ||
462 | } | ||
463 | |||
464 | apm_cmd = (struct apm_cmd *)smi_data_buf; | ||
465 | |||
466 | /* power off takes precedence */ | ||
467 | if (action & HC_ACTION_HOST_CONTROL_POWEROFF) { | ||
468 | apm_cmd->command = ESM_APM_POWER_CYCLE; | ||
469 | apm_cmd->reserved = 0; | ||
470 | *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 0; | ||
471 | host_control_smi(); | ||
472 | } else if (action & HC_ACTION_HOST_CONTROL_POWERCYCLE) { | ||
473 | apm_cmd->command = ESM_APM_POWER_CYCLE; | ||
474 | apm_cmd->reserved = 0; | ||
475 | *((s16 *)&apm_cmd->parameters.shortreq.parm[0]) = (s16) 20; | ||
476 | host_control_smi(); | ||
477 | } | ||
478 | } | ||
479 | |||
480 | /** | ||
481 | * dcdbas_reboot_notify: handle reboot notification for host control | ||
482 | */ | ||
483 | static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code, | ||
484 | void *unused) | ||
485 | { | ||
486 | static unsigned int notify_cnt = 0; | ||
487 | |||
488 | switch (code) { | ||
489 | case SYS_DOWN: | ||
490 | case SYS_HALT: | ||
491 | case SYS_POWER_OFF: | ||
492 | if (host_control_on_shutdown) { | ||
493 | /* firmware is going to perform host control action */ | ||
494 | if (++notify_cnt == 2) { | ||
495 | printk(KERN_WARNING | ||
496 | "Please wait for shutdown " | ||
497 | "action to complete...\n"); | ||
498 | dcdbas_host_control(); | ||
499 | } | ||
500 | /* | ||
501 | * register again and initiate the host control | ||
502 | * action on the second notification to allow | ||
503 | * everyone that registered to be notified | ||
504 | */ | ||
505 | register_reboot_notifier(nb); | ||
506 | } | ||
507 | break; | ||
508 | } | ||
509 | |||
510 | return NOTIFY_DONE; | ||
511 | } | ||
512 | |||
513 | static struct notifier_block dcdbas_reboot_nb = { | ||
514 | .notifier_call = dcdbas_reboot_notify, | ||
515 | .next = NULL, | ||
516 | .priority = 0 | ||
517 | }; | ||
518 | |||
519 | static DCDBAS_BIN_ATTR_RW(smi_data); | ||
520 | |||
521 | static struct bin_attribute *dcdbas_bin_attrs[] = { | ||
522 | &bin_attr_smi_data, | ||
523 | NULL | ||
524 | }; | ||
525 | |||
526 | static DCDBAS_DEV_ATTR_RW(smi_data_buf_size); | ||
527 | static DCDBAS_DEV_ATTR_RO(smi_data_buf_phys_addr); | ||
528 | static DCDBAS_DEV_ATTR_WO(smi_request); | ||
529 | static DCDBAS_DEV_ATTR_RW(host_control_action); | ||
530 | static DCDBAS_DEV_ATTR_RW(host_control_smi_type); | ||
531 | static DCDBAS_DEV_ATTR_RW(host_control_on_shutdown); | ||
532 | |||
533 | static struct device_attribute *dcdbas_dev_attrs[] = { | ||
534 | &dev_attr_smi_data_buf_size, | ||
535 | &dev_attr_smi_data_buf_phys_addr, | ||
536 | &dev_attr_smi_request, | ||
537 | &dev_attr_host_control_action, | ||
538 | &dev_attr_host_control_smi_type, | ||
539 | &dev_attr_host_control_on_shutdown, | ||
540 | NULL | ||
541 | }; | ||
542 | |||
543 | /** | ||
544 | * dcdbas_init: initialize driver | ||
545 | */ | ||
546 | static int __init dcdbas_init(void) | ||
547 | { | ||
548 | int i; | ||
549 | |||
550 | host_control_action = HC_ACTION_NONE; | ||
551 | host_control_smi_type = HC_SMITYPE_NONE; | ||
552 | |||
553 | dcdbas_pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); | ||
554 | if (IS_ERR(dcdbas_pdev)) | ||
555 | return PTR_ERR(dcdbas_pdev); | ||
556 | |||
557 | /* | ||
558 | * BIOS SMI calls require buffer addresses be in 32-bit address space. | ||
559 | * This is done by setting the DMA mask below. | ||
560 | */ | ||
561 | dcdbas_pdev->dev.coherent_dma_mask = DMA_32BIT_MASK; | ||
562 | dcdbas_pdev->dev.dma_mask = &dcdbas_pdev->dev.coherent_dma_mask; | ||
563 | |||
564 | register_reboot_notifier(&dcdbas_reboot_nb); | ||
565 | |||
566 | for (i = 0; dcdbas_bin_attrs[i]; i++) | ||
567 | sysfs_create_bin_file(&dcdbas_pdev->dev.kobj, | ||
568 | dcdbas_bin_attrs[i]); | ||
569 | |||
570 | for (i = 0; dcdbas_dev_attrs[i]; i++) | ||
571 | device_create_file(&dcdbas_pdev->dev, dcdbas_dev_attrs[i]); | ||
572 | |||
573 | dev_info(&dcdbas_pdev->dev, "%s (version %s)\n", | ||
574 | DRIVER_DESCRIPTION, DRIVER_VERSION); | ||
575 | |||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | /** | ||
580 | * dcdbas_exit: perform driver cleanup | ||
581 | */ | ||
582 | static void __exit dcdbas_exit(void) | ||
583 | { | ||
584 | platform_device_unregister(dcdbas_pdev); | ||
585 | unregister_reboot_notifier(&dcdbas_reboot_nb); | ||
586 | smi_data_buf_free(); | ||
587 | } | ||
588 | |||
589 | module_init(dcdbas_init); | ||
590 | module_exit(dcdbas_exit); | ||
591 | |||
592 | MODULE_DESCRIPTION(DRIVER_DESCRIPTION " (version " DRIVER_VERSION ")"); | ||
593 | MODULE_VERSION(DRIVER_VERSION); | ||
594 | MODULE_AUTHOR("Dell Inc."); | ||
595 | MODULE_LICENSE("GPL"); | ||
596 | |||
diff --git a/drivers/firmware/dcdbas.h b/drivers/firmware/dcdbas.h new file mode 100644 index 000000000000..58a85182b3e8 --- /dev/null +++ b/drivers/firmware/dcdbas.h | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * dcdbas.h: Definitions for Dell Systems Management Base driver | ||
3 | * | ||
4 | * Copyright (C) 1995-2005 Dell Inc. | ||
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 v2.0 as published by | ||
8 | * the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #ifndef _DCDBAS_H_ | ||
17 | #define _DCDBAS_H_ | ||
18 | |||
19 | #include <linux/device.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/sysfs.h> | ||
22 | #include <linux/types.h> | ||
23 | |||
24 | #define MAX_SMI_DATA_BUF_SIZE (256 * 1024) | ||
25 | |||
26 | #define HC_ACTION_NONE (0) | ||
27 | #define HC_ACTION_HOST_CONTROL_POWEROFF BIT(1) | ||
28 | #define HC_ACTION_HOST_CONTROL_POWERCYCLE BIT(2) | ||
29 | |||
30 | #define HC_SMITYPE_NONE (0) | ||
31 | #define HC_SMITYPE_TYPE1 (1) | ||
32 | #define HC_SMITYPE_TYPE2 (2) | ||
33 | #define HC_SMITYPE_TYPE3 (3) | ||
34 | |||
35 | #define ESM_APM_CMD (0x0A0) | ||
36 | #define ESM_APM_POWER_CYCLE (0x10) | ||
37 | #define ESM_STATUS_CMD_UNSUCCESSFUL (-1) | ||
38 | |||
39 | #define CMOS_BASE_PORT (0x070) | ||
40 | #define CMOS_PAGE1_INDEX_PORT (0) | ||
41 | #define CMOS_PAGE1_DATA_PORT (1) | ||
42 | #define CMOS_PAGE2_INDEX_PORT_PIIX4 (2) | ||
43 | #define CMOS_PAGE2_DATA_PORT_PIIX4 (3) | ||
44 | #define PE1400_APM_CONTROL_PORT (0x0B0) | ||
45 | #define PCAT_APM_CONTROL_PORT (0x0B2) | ||
46 | #define PCAT_APM_STATUS_PORT (0x0B3) | ||
47 | #define PE1300_CMOS_CMD_STRUCT_PTR (0x38) | ||
48 | #define PE1400_CMOS_CMD_STRUCT_PTR (0x70) | ||
49 | |||
50 | #define MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN (14) | ||
51 | #define MAX_SYSMGMT_LONGCMD_SGENTRY_NUM (16) | ||
52 | |||
53 | #define TIMEOUT_USEC_SHORT_SEMA_BLOCKING (10000) | ||
54 | #define EXPIRED_TIMER (0) | ||
55 | |||
56 | #define SMI_CMD_MAGIC (0x534D4931) | ||
57 | |||
58 | #define DCDBAS_DEV_ATTR_RW(_name) \ | ||
59 | DEVICE_ATTR(_name,0600,_name##_show,_name##_store); | ||
60 | |||
61 | #define DCDBAS_DEV_ATTR_RO(_name) \ | ||
62 | DEVICE_ATTR(_name,0400,_name##_show,NULL); | ||
63 | |||
64 | #define DCDBAS_DEV_ATTR_WO(_name) \ | ||
65 | DEVICE_ATTR(_name,0200,NULL,_name##_store); | ||
66 | |||
67 | #define DCDBAS_BIN_ATTR_RW(_name) \ | ||
68 | struct bin_attribute bin_attr_##_name = { \ | ||
69 | .attr = { .name = __stringify(_name), \ | ||
70 | .mode = 0600, \ | ||
71 | .owner = THIS_MODULE }, \ | ||
72 | .read = _name##_read, \ | ||
73 | .write = _name##_write, \ | ||
74 | } | ||
75 | |||
76 | struct smi_cmd { | ||
77 | __u32 magic; | ||
78 | __u32 ebx; | ||
79 | __u32 ecx; | ||
80 | __u16 command_address; | ||
81 | __u8 command_code; | ||
82 | __u8 reserved; | ||
83 | __u8 command_buffer[1]; | ||
84 | } __attribute__ ((packed)); | ||
85 | |||
86 | struct apm_cmd { | ||
87 | __u8 command; | ||
88 | __s8 status; | ||
89 | __u16 reserved; | ||
90 | union { | ||
91 | struct { | ||
92 | __u8 parm[MAX_SYSMGMT_SHORTCMD_PARMBUF_LEN]; | ||
93 | } __attribute__ ((packed)) shortreq; | ||
94 | |||
95 | struct { | ||
96 | __u16 num_sg_entries; | ||
97 | struct { | ||
98 | __u32 size; | ||
99 | __u64 addr; | ||
100 | } __attribute__ ((packed)) | ||
101 | sglist[MAX_SYSMGMT_LONGCMD_SGENTRY_NUM]; | ||
102 | } __attribute__ ((packed)) longreq; | ||
103 | } __attribute__ ((packed)) parameters; | ||
104 | } __attribute__ ((packed)); | ||
105 | |||
106 | #endif /* _DCDBAS_H_ */ | ||
107 | |||
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c new file mode 100644 index 000000000000..3b865f34a095 --- /dev/null +++ b/drivers/firmware/dell_rbu.c | |||
@@ -0,0 +1,634 @@ | |||
1 | /* | ||
2 | * dell_rbu.c | ||
3 | * Bios Update driver for Dell systems | ||
4 | * Author: Dell Inc | ||
5 | * Abhay Salunke <abhay_salunke@dell.com> | ||
6 | * | ||
7 | * Copyright (C) 2005 Dell Inc. | ||
8 | * | ||
9 | * Remote BIOS Update (rbu) driver is used for updating DELL BIOS by | ||
10 | * creating entries in the /sys file systems on Linux 2.6 and higher | ||
11 | * kernels. The driver supports two mechanism to update the BIOS namely | ||
12 | * contiguous and packetized. Both these methods still require having some | ||
13 | * application to set the CMOS bit indicating the BIOS to update itself | ||
14 | * after a reboot. | ||
15 | * | ||
16 | * Contiguous method: | ||
17 | * This driver writes the incoming data in a monolithic image by allocating | ||
18 | * contiguous physical pages large enough to accommodate the incoming BIOS | ||
19 | * image size. | ||
20 | * | ||
21 | * Packetized method: | ||
22 | * The driver writes the incoming packet image by allocating a new packet | ||
23 | * on every time the packet data is written. This driver requires an | ||
24 | * application to break the BIOS image in to fixed sized packet chunks. | ||
25 | * | ||
26 | * See Documentation/dell_rbu.txt for more info. | ||
27 | * | ||
28 | * This program is free software; you can redistribute it and/or modify | ||
29 | * it under the terms of the GNU General Public License v2.0 as published by | ||
30 | * the Free Software Foundation | ||
31 | * | ||
32 | * This program is distributed in the hope that it will be useful, | ||
33 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
34 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
35 | * GNU General Public License for more details. | ||
36 | */ | ||
37 | #include <linux/version.h> | ||
38 | #include <linux/config.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <linux/module.h> | ||
41 | #include <linux/string.h> | ||
42 | #include <linux/errno.h> | ||
43 | #include <linux/blkdev.h> | ||
44 | #include <linux/device.h> | ||
45 | #include <linux/spinlock.h> | ||
46 | #include <linux/moduleparam.h> | ||
47 | #include <linux/firmware.h> | ||
48 | #include <linux/dma-mapping.h> | ||
49 | |||
50 | MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); | ||
51 | MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); | ||
52 | MODULE_LICENSE("GPL"); | ||
53 | MODULE_VERSION("1.0"); | ||
54 | |||
55 | #define BIOS_SCAN_LIMIT 0xffffffff | ||
56 | #define MAX_IMAGE_LENGTH 16 | ||
57 | static struct _rbu_data { | ||
58 | void *image_update_buffer; | ||
59 | unsigned long image_update_buffer_size; | ||
60 | unsigned long bios_image_size; | ||
61 | int image_update_ordernum; | ||
62 | int dma_alloc; | ||
63 | spinlock_t lock; | ||
64 | unsigned long packet_read_count; | ||
65 | unsigned long packet_write_count; | ||
66 | unsigned long num_packets; | ||
67 | unsigned long packetsize; | ||
68 | } rbu_data; | ||
69 | |||
70 | static char image_type[MAX_IMAGE_LENGTH] = "mono"; | ||
71 | module_param_string(image_type, image_type, sizeof(image_type), 0); | ||
72 | MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet"); | ||
73 | |||
74 | struct packet_data { | ||
75 | struct list_head list; | ||
76 | size_t length; | ||
77 | void *data; | ||
78 | int ordernum; | ||
79 | }; | ||
80 | |||
81 | static struct packet_data packet_data_head; | ||
82 | |||
83 | static struct platform_device *rbu_device; | ||
84 | static int context; | ||
85 | static dma_addr_t dell_rbu_dmaaddr; | ||
86 | |||
87 | static void init_packet_head(void) | ||
88 | { | ||
89 | INIT_LIST_HEAD(&packet_data_head.list); | ||
90 | rbu_data.packet_write_count = 0; | ||
91 | rbu_data.packet_read_count = 0; | ||
92 | rbu_data.num_packets = 0; | ||
93 | rbu_data.packetsize = 0; | ||
94 | } | ||
95 | |||
96 | static int fill_last_packet(void *data, size_t length) | ||
97 | { | ||
98 | struct list_head *ptemp_list; | ||
99 | struct packet_data *packet = NULL; | ||
100 | int packet_count = 0; | ||
101 | |||
102 | pr_debug("fill_last_packet: entry \n"); | ||
103 | |||
104 | if (!rbu_data.num_packets) { | ||
105 | pr_debug("fill_last_packet: num_packets=0\n"); | ||
106 | return -ENOMEM; | ||
107 | } | ||
108 | |||
109 | packet_count = rbu_data.num_packets; | ||
110 | |||
111 | ptemp_list = (&packet_data_head.list)->prev; | ||
112 | |||
113 | packet = list_entry(ptemp_list, struct packet_data, list); | ||
114 | |||
115 | if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) { | ||
116 | pr_debug("dell_rbu:%s: packet size data " | ||
117 | "overrun\n", __FUNCTION__); | ||
118 | return -EINVAL; | ||
119 | } | ||
120 | |||
121 | pr_debug("fill_last_packet : buffer = %p\n", packet->data); | ||
122 | |||
123 | memcpy((packet->data + rbu_data.packet_write_count), data, length); | ||
124 | |||
125 | if ((rbu_data.packet_write_count + length) == rbu_data.packetsize) { | ||
126 | /* | ||
127 | * this was the last data chunk in the packet | ||
128 | * so reinitialize the packet data counter to zero | ||
129 | */ | ||
130 | rbu_data.packet_write_count = 0; | ||
131 | } else | ||
132 | rbu_data.packet_write_count += length; | ||
133 | |||
134 | pr_debug("fill_last_packet: exit \n"); | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static int create_packet(size_t length) | ||
139 | { | ||
140 | struct packet_data *newpacket; | ||
141 | int ordernum = 0; | ||
142 | |||
143 | pr_debug("create_packet: entry \n"); | ||
144 | |||
145 | if (!rbu_data.packetsize) { | ||
146 | pr_debug("create_packet: packetsize not specified\n"); | ||
147 | return -EINVAL; | ||
148 | } | ||
149 | |||
150 | newpacket = kmalloc(sizeof(struct packet_data), GFP_KERNEL); | ||
151 | if (!newpacket) { | ||
152 | printk(KERN_WARNING | ||
153 | "dell_rbu:%s: failed to allocate new " | ||
154 | "packet\n", __FUNCTION__); | ||
155 | return -ENOMEM; | ||
156 | } | ||
157 | |||
158 | ordernum = get_order(length); | ||
159 | /* | ||
160 | * there is no upper limit on memory | ||
161 | * address for packetized mechanism | ||
162 | */ | ||
163 | newpacket->data = (unsigned char *)__get_free_pages(GFP_KERNEL, | ||
164 | ordernum); | ||
165 | |||
166 | pr_debug("create_packet: newpacket %p\n", newpacket->data); | ||
167 | |||
168 | if (!newpacket->data) { | ||
169 | printk(KERN_WARNING | ||
170 | "dell_rbu:%s: failed to allocate new " | ||
171 | "packet\n", __FUNCTION__); | ||
172 | kfree(newpacket); | ||
173 | return -ENOMEM; | ||
174 | } | ||
175 | |||
176 | newpacket->ordernum = ordernum; | ||
177 | ++rbu_data.num_packets; | ||
178 | /* | ||
179 | * initialize the newly created packet headers | ||
180 | */ | ||
181 | INIT_LIST_HEAD(&newpacket->list); | ||
182 | list_add_tail(&newpacket->list, &packet_data_head.list); | ||
183 | /* | ||
184 | * packets have fixed size | ||
185 | */ | ||
186 | newpacket->length = rbu_data.packetsize; | ||
187 | |||
188 | pr_debug("create_packet: exit \n"); | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static int packetize_data(void *data, size_t length) | ||
194 | { | ||
195 | int rc = 0; | ||
196 | |||
197 | if (!rbu_data.packet_write_count) { | ||
198 | if ((rc = create_packet(length))) | ||
199 | return rc; | ||
200 | } | ||
201 | if ((rc = fill_last_packet(data, length))) | ||
202 | return rc; | ||
203 | |||
204 | return rc; | ||
205 | } | ||
206 | |||
207 | static int | ||
208 | do_packet_read(char *data, struct list_head *ptemp_list, | ||
209 | int length, int bytes_read, int *list_read_count) | ||
210 | { | ||
211 | void *ptemp_buf; | ||
212 | struct packet_data *newpacket = NULL; | ||
213 | int bytes_copied = 0; | ||
214 | int j = 0; | ||
215 | |||
216 | newpacket = list_entry(ptemp_list, struct packet_data, list); | ||
217 | *list_read_count += newpacket->length; | ||
218 | |||
219 | if (*list_read_count > bytes_read) { | ||
220 | /* point to the start of unread data */ | ||
221 | j = newpacket->length - (*list_read_count - bytes_read); | ||
222 | /* point to the offset in the packet buffer */ | ||
223 | ptemp_buf = (u8 *) newpacket->data + j; | ||
224 | /* | ||
225 | * check if there is enough room in | ||
226 | * * the incoming buffer | ||
227 | */ | ||
228 | if (length > (*list_read_count - bytes_read)) | ||
229 | /* | ||
230 | * copy what ever is there in this | ||
231 | * packet and move on | ||
232 | */ | ||
233 | bytes_copied = (*list_read_count - bytes_read); | ||
234 | else | ||
235 | /* copy the remaining */ | ||
236 | bytes_copied = length; | ||
237 | memcpy(data, ptemp_buf, bytes_copied); | ||
238 | } | ||
239 | return bytes_copied; | ||
240 | } | ||
241 | |||
242 | static int packet_read_list(char *data, size_t * pread_length) | ||
243 | { | ||
244 | struct list_head *ptemp_list; | ||
245 | int temp_count = 0; | ||
246 | int bytes_copied = 0; | ||
247 | int bytes_read = 0; | ||
248 | int remaining_bytes = 0; | ||
249 | char *pdest = data; | ||
250 | |||
251 | /* check if we have any packets */ | ||
252 | if (0 == rbu_data.num_packets) | ||
253 | return -ENOMEM; | ||
254 | |||
255 | remaining_bytes = *pread_length; | ||
256 | bytes_read = rbu_data.packet_read_count; | ||
257 | |||
258 | ptemp_list = (&packet_data_head.list)->next; | ||
259 | while (!list_empty(ptemp_list)) { | ||
260 | bytes_copied = do_packet_read(pdest, ptemp_list, | ||
261 | remaining_bytes, bytes_read, | ||
262 | &temp_count); | ||
263 | remaining_bytes -= bytes_copied; | ||
264 | bytes_read += bytes_copied; | ||
265 | pdest += bytes_copied; | ||
266 | /* | ||
267 | * check if we reached end of buffer before reaching the | ||
268 | * last packet | ||
269 | */ | ||
270 | if (remaining_bytes == 0) | ||
271 | break; | ||
272 | |||
273 | ptemp_list = ptemp_list->next; | ||
274 | } | ||
275 | /*finally set the bytes read */ | ||
276 | *pread_length = bytes_read - rbu_data.packet_read_count; | ||
277 | rbu_data.packet_read_count = bytes_read; | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static void packet_empty_list(void) | ||
282 | { | ||
283 | struct list_head *ptemp_list; | ||
284 | struct list_head *pnext_list; | ||
285 | struct packet_data *newpacket; | ||
286 | |||
287 | ptemp_list = (&packet_data_head.list)->next; | ||
288 | while (!list_empty(ptemp_list)) { | ||
289 | newpacket = | ||
290 | list_entry(ptemp_list, struct packet_data, list); | ||
291 | pnext_list = ptemp_list->next; | ||
292 | list_del(ptemp_list); | ||
293 | ptemp_list = pnext_list; | ||
294 | /* | ||
295 | * zero out the RBU packet memory before freeing | ||
296 | * to make sure there are no stale RBU packets left in memory | ||
297 | */ | ||
298 | memset(newpacket->data, 0, rbu_data.packetsize); | ||
299 | free_pages((unsigned long)newpacket->data, | ||
300 | newpacket->ordernum); | ||
301 | kfree(newpacket); | ||
302 | } | ||
303 | rbu_data.packet_write_count = 0; | ||
304 | rbu_data.packet_read_count = 0; | ||
305 | rbu_data.num_packets = 0; | ||
306 | rbu_data.packetsize = 0; | ||
307 | } | ||
308 | |||
309 | /* | ||
310 | * img_update_free: Frees the buffer allocated for storing BIOS image | ||
311 | * Always called with lock held and returned with lock held | ||
312 | */ | ||
313 | static void img_update_free(void) | ||
314 | { | ||
315 | if (!rbu_data.image_update_buffer) | ||
316 | return; | ||
317 | /* | ||
318 | * zero out this buffer before freeing it to get rid of any stale | ||
319 | * BIOS image copied in memory. | ||
320 | */ | ||
321 | memset(rbu_data.image_update_buffer, 0, | ||
322 | rbu_data.image_update_buffer_size); | ||
323 | if (rbu_data.dma_alloc == 1) | ||
324 | dma_free_coherent(NULL, rbu_data.bios_image_size, | ||
325 | rbu_data.image_update_buffer, | ||
326 | dell_rbu_dmaaddr); | ||
327 | else | ||
328 | free_pages((unsigned long)rbu_data.image_update_buffer, | ||
329 | rbu_data.image_update_ordernum); | ||
330 | |||
331 | /* | ||
332 | * Re-initialize the rbu_data variables after a free | ||
333 | */ | ||
334 | rbu_data.image_update_ordernum = -1; | ||
335 | rbu_data.image_update_buffer = NULL; | ||
336 | rbu_data.image_update_buffer_size = 0; | ||
337 | rbu_data.bios_image_size = 0; | ||
338 | rbu_data.dma_alloc = 0; | ||
339 | } | ||
340 | |||
341 | /* | ||
342 | * img_update_realloc: This function allocates the contiguous pages to | ||
343 | * accommodate the requested size of data. The memory address and size | ||
344 | * values are stored globally and on every call to this function the new | ||
345 | * size is checked to see if more data is required than the existing size. | ||
346 | * If true the previous memory is freed and new allocation is done to | ||
347 | * accommodate the new size. If the incoming size is less then than the | ||
348 | * already allocated size, then that memory is reused. This function is | ||
349 | * called with lock held and returns with lock held. | ||
350 | */ | ||
351 | static int img_update_realloc(unsigned long size) | ||
352 | { | ||
353 | unsigned char *image_update_buffer = NULL; | ||
354 | unsigned long rc; | ||
355 | unsigned long img_buf_phys_addr; | ||
356 | int ordernum; | ||
357 | int dma_alloc = 0; | ||
358 | |||
359 | /* | ||
360 | * check if the buffer of sufficient size has been | ||
361 | * already allocated | ||
362 | */ | ||
363 | if (rbu_data.image_update_buffer_size >= size) { | ||
364 | /* | ||
365 | * check for corruption | ||
366 | */ | ||
367 | if ((size != 0) && (rbu_data.image_update_buffer == NULL)) { | ||
368 | printk(KERN_ERR "dell_rbu:%s: corruption " | ||
369 | "check failed\n", __FUNCTION__); | ||
370 | return -EINVAL; | ||
371 | } | ||
372 | /* | ||
373 | * we have a valid pre-allocated buffer with | ||
374 | * sufficient size | ||
375 | */ | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | /* | ||
380 | * free any previously allocated buffer | ||
381 | */ | ||
382 | img_update_free(); | ||
383 | |||
384 | spin_unlock(&rbu_data.lock); | ||
385 | |||
386 | ordernum = get_order(size); | ||
387 | image_update_buffer = | ||
388 | (unsigned char *)__get_free_pages(GFP_KERNEL, ordernum); | ||
389 | |||
390 | img_buf_phys_addr = | ||
391 | (unsigned long)virt_to_phys(image_update_buffer); | ||
392 | |||
393 | if (img_buf_phys_addr > BIOS_SCAN_LIMIT) { | ||
394 | free_pages((unsigned long)image_update_buffer, ordernum); | ||
395 | ordernum = -1; | ||
396 | image_update_buffer = dma_alloc_coherent(NULL, size, | ||
397 | &dell_rbu_dmaaddr, | ||
398 | GFP_KERNEL); | ||
399 | dma_alloc = 1; | ||
400 | } | ||
401 | |||
402 | spin_lock(&rbu_data.lock); | ||
403 | |||
404 | if (image_update_buffer != NULL) { | ||
405 | rbu_data.image_update_buffer = image_update_buffer; | ||
406 | rbu_data.image_update_buffer_size = size; | ||
407 | rbu_data.bios_image_size = | ||
408 | rbu_data.image_update_buffer_size; | ||
409 | rbu_data.image_update_ordernum = ordernum; | ||
410 | rbu_data.dma_alloc = dma_alloc; | ||
411 | rc = 0; | ||
412 | } else { | ||
413 | pr_debug("Not enough memory for image update:" | ||
414 | "size = %ld\n", size); | ||
415 | rc = -ENOMEM; | ||
416 | } | ||
417 | |||
418 | return rc; | ||
419 | } | ||
420 | |||
421 | static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) | ||
422 | { | ||
423 | int retval; | ||
424 | size_t bytes_left; | ||
425 | size_t data_length; | ||
426 | char *ptempBuf = buffer; | ||
427 | unsigned long imagesize; | ||
428 | |||
429 | /* check to see if we have something to return */ | ||
430 | if (rbu_data.num_packets == 0) { | ||
431 | pr_debug("read_packet_data: no packets written\n"); | ||
432 | retval = -ENOMEM; | ||
433 | goto read_rbu_data_exit; | ||
434 | } | ||
435 | |||
436 | imagesize = rbu_data.num_packets * rbu_data.packetsize; | ||
437 | |||
438 | if (pos > imagesize) { | ||
439 | retval = 0; | ||
440 | printk(KERN_WARNING "dell_rbu:read_packet_data: " | ||
441 | "data underrun\n"); | ||
442 | goto read_rbu_data_exit; | ||
443 | } | ||
444 | |||
445 | bytes_left = imagesize - pos; | ||
446 | data_length = min(bytes_left, count); | ||
447 | |||
448 | if ((retval = packet_read_list(ptempBuf, &data_length)) < 0) | ||
449 | goto read_rbu_data_exit; | ||
450 | |||
451 | if ((pos + count) > imagesize) { | ||
452 | rbu_data.packet_read_count = 0; | ||
453 | /* this was the last copy */ | ||
454 | retval = bytes_left; | ||
455 | } else | ||
456 | retval = count; | ||
457 | |||
458 | read_rbu_data_exit: | ||
459 | return retval; | ||
460 | } | ||
461 | |||
462 | static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) | ||
463 | { | ||
464 | unsigned char *ptemp = NULL; | ||
465 | size_t bytes_left = 0; | ||
466 | size_t data_length = 0; | ||
467 | ssize_t ret_count = 0; | ||
468 | |||
469 | /* check to see if we have something to return */ | ||
470 | if ((rbu_data.image_update_buffer == NULL) || | ||
471 | (rbu_data.bios_image_size == 0)) { | ||
472 | pr_debug("read_rbu_data_mono: image_update_buffer %p ," | ||
473 | "bios_image_size %lu\n", | ||
474 | rbu_data.image_update_buffer, | ||
475 | rbu_data.bios_image_size); | ||
476 | ret_count = -ENOMEM; | ||
477 | goto read_rbu_data_exit; | ||
478 | } | ||
479 | |||
480 | if (pos > rbu_data.bios_image_size) { | ||
481 | ret_count = 0; | ||
482 | goto read_rbu_data_exit; | ||
483 | } | ||
484 | |||
485 | bytes_left = rbu_data.bios_image_size - pos; | ||
486 | data_length = min(bytes_left, count); | ||
487 | |||
488 | ptemp = rbu_data.image_update_buffer; | ||
489 | memcpy(buffer, (ptemp + pos), data_length); | ||
490 | |||
491 | if ((pos + count) > rbu_data.bios_image_size) | ||
492 | /* this was the last copy */ | ||
493 | ret_count = bytes_left; | ||
494 | else | ||
495 | ret_count = count; | ||
496 | read_rbu_data_exit: | ||
497 | return ret_count; | ||
498 | } | ||
499 | |||
500 | static ssize_t | ||
501 | read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count) | ||
502 | { | ||
503 | ssize_t ret_count = 0; | ||
504 | |||
505 | spin_lock(&rbu_data.lock); | ||
506 | |||
507 | if (!strcmp(image_type, "mono")) | ||
508 | ret_count = read_rbu_mono_data(buffer, pos, count); | ||
509 | else if (!strcmp(image_type, "packet")) | ||
510 | ret_count = read_packet_data(buffer, pos, count); | ||
511 | else | ||
512 | pr_debug("read_rbu_data: invalid image type specified\n"); | ||
513 | |||
514 | spin_unlock(&rbu_data.lock); | ||
515 | return ret_count; | ||
516 | } | ||
517 | |||
518 | static ssize_t | ||
519 | read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, | ||
520 | size_t count) | ||
521 | { | ||
522 | int size = 0; | ||
523 | if (!pos) | ||
524 | size = sprintf(buffer, "%s\n", image_type); | ||
525 | return size; | ||
526 | } | ||
527 | |||
528 | static ssize_t | ||
529 | write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, | ||
530 | size_t count) | ||
531 | { | ||
532 | int rc = count; | ||
533 | spin_lock(&rbu_data.lock); | ||
534 | |||
535 | if (strlen(buffer) < MAX_IMAGE_LENGTH) | ||
536 | sscanf(buffer, "%s", image_type); | ||
537 | else | ||
538 | printk(KERN_WARNING "dell_rbu: image_type is invalid" | ||
539 | "max chars = %d, \n incoming str--%s-- \n", | ||
540 | MAX_IMAGE_LENGTH, buffer); | ||
541 | |||
542 | /* we must free all previous allocations */ | ||
543 | packet_empty_list(); | ||
544 | img_update_free(); | ||
545 | |||
546 | spin_unlock(&rbu_data.lock); | ||
547 | return rc; | ||
548 | |||
549 | } | ||
550 | |||
551 | static struct bin_attribute rbu_data_attr = { | ||
552 | .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444}, | ||
553 | .read = read_rbu_data, | ||
554 | }; | ||
555 | |||
556 | static struct bin_attribute rbu_image_type_attr = { | ||
557 | .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644}, | ||
558 | .read = read_rbu_image_type, | ||
559 | .write = write_rbu_image_type, | ||
560 | }; | ||
561 | |||
562 | static void callbackfn_rbu(const struct firmware *fw, void *context) | ||
563 | { | ||
564 | int rc = 0; | ||
565 | |||
566 | if (!fw || !fw->size) | ||
567 | return; | ||
568 | |||
569 | spin_lock(&rbu_data.lock); | ||
570 | if (!strcmp(image_type, "mono")) { | ||
571 | if (!img_update_realloc(fw->size)) | ||
572 | memcpy(rbu_data.image_update_buffer, | ||
573 | fw->data, fw->size); | ||
574 | } else if (!strcmp(image_type, "packet")) { | ||
575 | if (!rbu_data.packetsize) | ||
576 | rbu_data.packetsize = fw->size; | ||
577 | else if (rbu_data.packetsize != fw->size) { | ||
578 | packet_empty_list(); | ||
579 | rbu_data.packetsize = fw->size; | ||
580 | } | ||
581 | packetize_data(fw->data, fw->size); | ||
582 | } else | ||
583 | pr_debug("invalid image type specified.\n"); | ||
584 | spin_unlock(&rbu_data.lock); | ||
585 | |||
586 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | ||
587 | "dell_rbu", &rbu_device->dev, | ||
588 | &context, callbackfn_rbu); | ||
589 | if (rc) | ||
590 | printk(KERN_ERR | ||
591 | "dell_rbu:%s request_firmware_nowait failed" | ||
592 | " %d\n", __FUNCTION__, rc); | ||
593 | } | ||
594 | |||
595 | static int __init dcdrbu_init(void) | ||
596 | { | ||
597 | int rc = 0; | ||
598 | spin_lock_init(&rbu_data.lock); | ||
599 | |||
600 | init_packet_head(); | ||
601 | rbu_device = | ||
602 | platform_device_register_simple("dell_rbu", -1, NULL, 0); | ||
603 | if (!rbu_device) { | ||
604 | printk(KERN_ERR | ||
605 | "dell_rbu:%s:platform_device_register_simple " | ||
606 | "failed\n", __FUNCTION__); | ||
607 | return -EIO; | ||
608 | } | ||
609 | |||
610 | sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr); | ||
611 | sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); | ||
612 | |||
613 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | ||
614 | "dell_rbu", &rbu_device->dev, | ||
615 | &context, callbackfn_rbu); | ||
616 | if (rc) | ||
617 | printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait" | ||
618 | " failed %d\n", __FUNCTION__, rc); | ||
619 | |||
620 | return rc; | ||
621 | |||
622 | } | ||
623 | |||
624 | static __exit void dcdrbu_exit(void) | ||
625 | { | ||
626 | spin_lock(&rbu_data.lock); | ||
627 | packet_empty_list(); | ||
628 | img_update_free(); | ||
629 | spin_unlock(&rbu_data.lock); | ||
630 | platform_device_unregister(rbu_device); | ||
631 | } | ||
632 | |||
633 | module_exit(dcdrbu_exit); | ||
634 | module_init(dcdrbu_init); | ||
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c index 354a26295672..8ee56d4b3891 100644 --- a/drivers/i2c/chips/isp1301_omap.c +++ b/drivers/i2c/chips/isp1301_omap.c | |||
@@ -1489,7 +1489,7 @@ static int isp1301_probe(struct i2c_adapter *bus, int address, int kind) | |||
1489 | if (the_transceiver) | 1489 | if (the_transceiver) |
1490 | return 0; | 1490 | return 0; |
1491 | 1491 | ||
1492 | isp = kcalloc(1, sizeof *isp, GFP_KERNEL); | 1492 | isp = kzalloc(sizeof *isp, GFP_KERNEL); |
1493 | if (!isp) | 1493 | if (!isp) |
1494 | return 0; | 1494 | return 0; |
1495 | 1495 | ||
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index bebcc47ab06c..b23322523ef5 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c | |||
@@ -1068,6 +1068,8 @@ static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp, | |||
1068 | struct unit_directory *ud; | 1068 | struct unit_directory *ud; |
1069 | int i = 0; | 1069 | int i = 0; |
1070 | int length = 0; | 1070 | int length = 0; |
1071 | /* ieee1394:venNmoNspNverN */ | ||
1072 | char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1]; | ||
1071 | 1073 | ||
1072 | if (!cdev) | 1074 | if (!cdev) |
1073 | return -ENODEV; | 1075 | return -ENODEV; |
@@ -1094,6 +1096,12 @@ do { \ | |||
1094 | PUT_ENVP("GUID=%016Lx", (unsigned long long)ud->ne->guid); | 1096 | PUT_ENVP("GUID=%016Lx", (unsigned long long)ud->ne->guid); |
1095 | PUT_ENVP("SPECIFIER_ID=%06x", ud->specifier_id); | 1097 | PUT_ENVP("SPECIFIER_ID=%06x", ud->specifier_id); |
1096 | PUT_ENVP("VERSION=%06x", ud->version); | 1098 | PUT_ENVP("VERSION=%06x", ud->version); |
1099 | snprintf(buf, sizeof(buf), "ieee1394:ven%08Xmo%08Xsp%08Xver%08X", | ||
1100 | ud->vendor_id, | ||
1101 | ud->model_id, | ||
1102 | ud->specifier_id, | ||
1103 | ud->version); | ||
1104 | PUT_ENVP("MODALIAS=%s", buf); | ||
1097 | 1105 | ||
1098 | #undef PUT_ENVP | 1106 | #undef PUT_ENVP |
1099 | 1107 | ||
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index fae1c2dcee51..211ba3223f65 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c | |||
@@ -463,7 +463,7 @@ alloc_group_attrs(ssize_t (*show)(struct ib_port *, | |||
463 | return NULL; | 463 | return NULL; |
464 | 464 | ||
465 | for (i = 0; i < len; i++) { | 465 | for (i = 0; i < len; i++) { |
466 | element = kcalloc(1, sizeof(struct port_table_attribute), | 466 | element = kzalloc(sizeof(struct port_table_attribute), |
467 | GFP_KERNEL); | 467 | GFP_KERNEL); |
468 | if (!element) | 468 | if (!element) |
469 | goto err; | 469 | goto err; |
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index f8b278d3559b..19c14c4beb44 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -393,6 +393,7 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
393 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | 393 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; |
394 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | 394 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; |
395 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | 395 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; |
396 | case EV_SW: bits = dev->swbit; len = SW_MAX; break; | ||
396 | default: return -EINVAL; | 397 | default: return -EINVAL; |
397 | } | 398 | } |
398 | len = NBITS(len) * sizeof(long); | 399 | len = NBITS(len) * sizeof(long); |
@@ -421,6 +422,13 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
421 | return copy_to_user(p, dev->snd, len) ? -EFAULT : len; | 422 | return copy_to_user(p, dev->snd, len) ? -EFAULT : len; |
422 | } | 423 | } |
423 | 424 | ||
425 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0))) { | ||
426 | int len; | ||
427 | len = NBITS(SW_MAX) * sizeof(long); | ||
428 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
429 | return copy_to_user(p, dev->sw, len) ? -EFAULT : len; | ||
430 | } | ||
431 | |||
424 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { | 432 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { |
425 | int len; | 433 | int len; |
426 | if (!dev->name) return -ENOENT; | 434 | if (!dev->name) return -ENOENT; |
diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c index a0118038330a..462f8d300aae 100644 --- a/drivers/input/gameport/emu10k1-gp.c +++ b/drivers/input/gameport/emu10k1-gp.c | |||
@@ -75,7 +75,7 @@ static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id | |||
75 | if (!request_region(ioport, iolen, "emu10k1-gp")) | 75 | if (!request_region(ioport, iolen, "emu10k1-gp")) |
76 | return -EBUSY; | 76 | return -EBUSY; |
77 | 77 | ||
78 | emu = kcalloc(1, sizeof(struct emu), GFP_KERNEL); | 78 | emu = kzalloc(sizeof(struct emu), GFP_KERNEL); |
79 | port = gameport_allocate_port(); | 79 | port = gameport_allocate_port(); |
80 | if (!emu || !port) { | 80 | if (!emu || !port) { |
81 | printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n"); | 81 | printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n"); |
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c index 57615bc63906..47e93daa0fa7 100644 --- a/drivers/input/gameport/fm801-gp.c +++ b/drivers/input/gameport/fm801-gp.c | |||
@@ -83,7 +83,7 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device | |||
83 | struct fm801_gp *gp; | 83 | struct fm801_gp *gp; |
84 | struct gameport *port; | 84 | struct gameport *port; |
85 | 85 | ||
86 | gp = kcalloc(1, sizeof(struct fm801_gp), GFP_KERNEL); | 86 | gp = kzalloc(sizeof(struct fm801_gp), GFP_KERNEL); |
87 | port = gameport_allocate_port(); | 87 | port = gameport_allocate_port(); |
88 | if (!gp || !port) { | 88 | if (!gp || !port) { |
89 | printk(KERN_ERR "fm801-gp: Memory allocation failed\n"); | 89 | printk(KERN_ERR "fm801-gp: Memory allocation failed\n"); |
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c index 70f051894a3c..d2e55dc956ba 100644 --- a/drivers/input/gameport/ns558.c +++ b/drivers/input/gameport/ns558.c | |||
@@ -142,7 +142,7 @@ static int ns558_isa_probe(int io) | |||
142 | return -EBUSY; | 142 | return -EBUSY; |
143 | } | 143 | } |
144 | 144 | ||
145 | ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL); | 145 | ns558 = kzalloc(sizeof(struct ns558), GFP_KERNEL); |
146 | port = gameport_allocate_port(); | 146 | port = gameport_allocate_port(); |
147 | if (!ns558 || !port) { | 147 | if (!ns558 || !port) { |
148 | printk(KERN_ERR "ns558: Memory allocation failed.\n"); | 148 | printk(KERN_ERR "ns558: Memory allocation failed.\n"); |
@@ -215,7 +215,7 @@ static int ns558_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *did) | |||
215 | if (!request_region(ioport, iolen, "ns558-pnp")) | 215 | if (!request_region(ioport, iolen, "ns558-pnp")) |
216 | return -EBUSY; | 216 | return -EBUSY; |
217 | 217 | ||
218 | ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL); | 218 | ns558 = kzalloc(sizeof(struct ns558), GFP_KERNEL); |
219 | port = gameport_allocate_port(); | 219 | port = gameport_allocate_port(); |
220 | if (!ns558 || !port) { | 220 | if (!ns558 || !port) { |
221 | printk(KERN_ERR "ns558: Memory allocation failed\n"); | 221 | printk(KERN_ERR "ns558: Memory allocation failed\n"); |
diff --git a/drivers/input/input.c b/drivers/input/input.c index a275211c8e1e..88636a204525 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -89,6 +89,15 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in | |||
89 | 89 | ||
90 | break; | 90 | break; |
91 | 91 | ||
92 | case EV_SW: | ||
93 | |||
94 | if (code > SW_MAX || !test_bit(code, dev->swbit) || !!test_bit(code, dev->sw) == value) | ||
95 | return; | ||
96 | |||
97 | change_bit(code, dev->sw); | ||
98 | |||
99 | break; | ||
100 | |||
92 | case EV_ABS: | 101 | case EV_ABS: |
93 | 102 | ||
94 | if (code > ABS_MAX || !test_bit(code, dev->absbit)) | 103 | if (code > ABS_MAX || !test_bit(code, dev->absbit)) |
@@ -402,6 +411,7 @@ static void input_call_hotplug(char *verb, struct input_dev *dev) | |||
402 | SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED); | 411 | SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED); |
403 | SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND); | 412 | SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND); |
404 | SPRINTF_BIT_A2(ffbit, "FF=", FF_MAX, EV_FF); | 413 | SPRINTF_BIT_A2(ffbit, "FF=", FF_MAX, EV_FF); |
414 | SPRINTF_BIT_A2(swbit, "SW=", SW_MAX, EV_SW); | ||
405 | 415 | ||
406 | envp[i++] = NULL; | 416 | envp[i++] = NULL; |
407 | 417 | ||
@@ -490,6 +500,7 @@ static int input_devices_read(char *buf, char **start, off_t pos, int count, int | |||
490 | SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED); | 500 | SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED); |
491 | SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND); | 501 | SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND); |
492 | SPRINTF_BIT_B2(ffbit, "FF=", FF_MAX, EV_FF); | 502 | SPRINTF_BIT_B2(ffbit, "FF=", FF_MAX, EV_FF); |
503 | SPRINTF_BIT_B2(swbit, "SW=", SW_MAX, EV_SW); | ||
493 | 504 | ||
494 | len += sprintf(buf + len, "\n"); | 505 | len += sprintf(buf + len, "\n"); |
495 | 506 | ||
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index bf34f75b9467..bf65430181fa 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c | |||
@@ -269,7 +269,7 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
269 | int i; | 269 | int i; |
270 | int err; | 270 | int err; |
271 | 271 | ||
272 | if (!(a3d = kcalloc(1, sizeof(struct a3d), GFP_KERNEL))) | 272 | if (!(a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL))) |
273 | return -ENOMEM; | 273 | return -ENOMEM; |
274 | 274 | ||
275 | a3d->gameport = gameport; | 275 | a3d->gameport = gameport; |
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index 265962956c63..cf35ae638a0d 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c | |||
@@ -469,7 +469,7 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
469 | int i; | 469 | int i; |
470 | int err; | 470 | int err; |
471 | 471 | ||
472 | if (!(port = kcalloc(1, sizeof(struct adi_port), GFP_KERNEL))) | 472 | if (!(port = kzalloc(sizeof(struct adi_port), GFP_KERNEL))) |
473 | return -ENOMEM; | 473 | return -ENOMEM; |
474 | 474 | ||
475 | port->gameport = gameport; | 475 | port->gameport = gameport; |
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index c3a5739030c3..64b1313a3c66 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c | |||
@@ -655,7 +655,7 @@ static int analog_connect(struct gameport *gameport, struct gameport_driver *drv | |||
655 | int i; | 655 | int i; |
656 | int err; | 656 | int err; |
657 | 657 | ||
658 | if (!(port = kcalloc(1, sizeof(struct analog_port), GFP_KERNEL))) | 658 | if (!(port = kzalloc(sizeof(struct analog_port), GFP_KERNEL))) |
659 | return - ENOMEM; | 659 | return - ENOMEM; |
660 | 660 | ||
661 | err = analog_init_port(gameport, drv, port); | 661 | err = analog_init_port(gameport, drv, port); |
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c index a6002205328f..0b2e9fa26579 100644 --- a/drivers/input/joystick/cobra.c +++ b/drivers/input/joystick/cobra.c | |||
@@ -163,7 +163,7 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
163 | int i, j; | 163 | int i, j; |
164 | int err; | 164 | int err; |
165 | 165 | ||
166 | if (!(cobra = kcalloc(1, sizeof(struct cobra), GFP_KERNEL))) | 166 | if (!(cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL))) |
167 | return -ENOMEM; | 167 | return -ENOMEM; |
168 | 168 | ||
169 | cobra->gameport = gameport; | 169 | cobra->gameport = gameport; |
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index fbd3eed07f90..2a3e4bb2da50 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c | |||
@@ -572,7 +572,7 @@ static struct db9 __init *db9_probe(int *config, int nargs) | |||
572 | } | 572 | } |
573 | } | 573 | } |
574 | 574 | ||
575 | if (!(db9 = kcalloc(1, sizeof(struct db9), GFP_KERNEL))) { | 575 | if (!(db9 = kzalloc(sizeof(struct db9), GFP_KERNEL))) { |
576 | parport_put_port(pp); | 576 | parport_put_port(pp); |
577 | return NULL; | 577 | return NULL; |
578 | } | 578 | } |
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 95bbdd302aad..5427bf9fc862 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c | |||
@@ -554,7 +554,7 @@ static struct gc __init *gc_probe(int *config, int nargs) | |||
554 | return NULL; | 554 | return NULL; |
555 | } | 555 | } |
556 | 556 | ||
557 | if (!(gc = kcalloc(1, sizeof(struct gc), GFP_KERNEL))) { | 557 | if (!(gc = kzalloc(sizeof(struct gc), GFP_KERNEL))) { |
558 | parport_put_port(pp); | 558 | parport_put_port(pp); |
559 | return NULL; | 559 | return NULL; |
560 | } | 560 | } |
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index 7d969420066c..8e4f92b115e6 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c | |||
@@ -242,7 +242,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
242 | unsigned char data[GF2K_LENGTH]; | 242 | unsigned char data[GF2K_LENGTH]; |
243 | int i, err; | 243 | int i, err; |
244 | 244 | ||
245 | if (!(gf2k = kcalloc(1, sizeof(struct gf2k), GFP_KERNEL))) | 245 | if (!(gf2k = kzalloc(sizeof(struct gf2k), GFP_KERNEL))) |
246 | return -ENOMEM; | 246 | return -ENOMEM; |
247 | 247 | ||
248 | gf2k->gameport = gameport; | 248 | gf2k->gameport = gameport; |
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c index d1500d2562d6..9d3f910dd568 100644 --- a/drivers/input/joystick/grip.c +++ b/drivers/input/joystick/grip.c | |||
@@ -301,7 +301,7 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
301 | int i, j, t; | 301 | int i, j, t; |
302 | int err; | 302 | int err; |
303 | 303 | ||
304 | if (!(grip = kcalloc(1, sizeof(struct grip), GFP_KERNEL))) | 304 | if (!(grip = kzalloc(sizeof(struct grip), GFP_KERNEL))) |
305 | return -ENOMEM; | 305 | return -ENOMEM; |
306 | 306 | ||
307 | grip->gameport = gameport; | 307 | grip->gameport = gameport; |
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 0da7bd133ccf..da17eee6f574 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c | |||
@@ -607,7 +607,7 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
607 | struct grip_mp *grip; | 607 | struct grip_mp *grip; |
608 | int err; | 608 | int err; |
609 | 609 | ||
610 | if (!(grip = kcalloc(1, sizeof(struct grip_mp), GFP_KERNEL))) | 610 | if (!(grip = kzalloc(sizeof(struct grip_mp), GFP_KERNEL))) |
611 | return -ENOMEM; | 611 | return -ENOMEM; |
612 | 612 | ||
613 | grip->gameport = gameport; | 613 | grip->gameport = gameport; |
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c index f93da7bc082d..6a70ec429f06 100644 --- a/drivers/input/joystick/guillemot.c +++ b/drivers/input/joystick/guillemot.c | |||
@@ -183,7 +183,7 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver * | |||
183 | int i, t; | 183 | int i, t; |
184 | int err; | 184 | int err; |
185 | 185 | ||
186 | if (!(guillemot = kcalloc(1, sizeof(struct guillemot), GFP_KERNEL))) | 186 | if (!(guillemot = kzalloc(sizeof(struct guillemot), GFP_KERNEL))) |
187 | return -ENOMEM; | 187 | return -ENOMEM; |
188 | 188 | ||
189 | guillemot->gameport = gameport; | 189 | guillemot->gameport = gameport; |
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c index 9d3f8c38cb09..d7b3472bd686 100644 --- a/drivers/input/joystick/interact.c +++ b/drivers/input/joystick/interact.c | |||
@@ -212,7 +212,7 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d | |||
212 | int i, t; | 212 | int i, t; |
213 | int err; | 213 | int err; |
214 | 214 | ||
215 | if (!(interact = kcalloc(1, sizeof(struct interact), GFP_KERNEL))) | 215 | if (!(interact = kzalloc(sizeof(struct interact), GFP_KERNEL))) |
216 | return -ENOMEM; | 216 | return -ENOMEM; |
217 | 217 | ||
218 | interact->gameport = gameport; | 218 | interact->gameport = gameport; |
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index 47144a7ed9e7..9e0353721a35 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c | |||
@@ -590,7 +590,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
590 | 590 | ||
591 | comment[0] = 0; | 591 | comment[0] = 0; |
592 | 592 | ||
593 | sw = kcalloc(1, sizeof(struct sw), GFP_KERNEL); | 593 | sw = kzalloc(sizeof(struct sw), GFP_KERNEL); |
594 | buf = kmalloc(SW_LENGTH, GFP_KERNEL); | 594 | buf = kmalloc(SW_LENGTH, GFP_KERNEL); |
595 | idbuf = kmalloc(SW_LENGTH, GFP_KERNEL); | 595 | idbuf = kmalloc(SW_LENGTH, GFP_KERNEL); |
596 | if (!sw || !buf || !idbuf) { | 596 | if (!sw || !buf || !idbuf) { |
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c index 9eb9954cac6e..7431efc4330e 100644 --- a/drivers/input/joystick/tmdc.c +++ b/drivers/input/joystick/tmdc.c | |||
@@ -262,7 +262,7 @@ static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
262 | int i, j, k, l, m; | 262 | int i, j, k, l, m; |
263 | int err; | 263 | int err; |
264 | 264 | ||
265 | if (!(tmdc = kcalloc(1, sizeof(struct tmdc), GFP_KERNEL))) | 265 | if (!(tmdc = kzalloc(sizeof(struct tmdc), GFP_KERNEL))) |
266 | return -ENOMEM; | 266 | return -ENOMEM; |
267 | 267 | ||
268 | tmdc->gameport = gameport; | 268 | tmdc->gameport = gameport; |
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index 28100d461cb7..0c5b9c8297cd 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c | |||
@@ -178,7 +178,7 @@ static struct tgfx __init *tgfx_probe(int *config, int nargs) | |||
178 | return NULL; | 178 | return NULL; |
179 | } | 179 | } |
180 | 180 | ||
181 | if (!(tgfx = kcalloc(1, sizeof(struct tgfx), GFP_KERNEL))) { | 181 | if (!(tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL))) { |
182 | parport_put_port(pp); | 182 | parport_put_port(pp); |
183 | return NULL; | 183 | return NULL; |
184 | } | 184 | } |
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index a8551711e8d6..cd4b6e795013 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/input.h> | 17 | #include <linux/input.h> |
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/jiffies.h> | ||
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
21 | #include <asm/irq.h> | 22 | #include <asm/irq.h> |
@@ -32,7 +33,6 @@ | |||
32 | /* zero code, 124 scancodes + 3 hinge combinations */ | 33 | /* zero code, 124 scancodes + 3 hinge combinations */ |
33 | #define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 ) | 34 | #define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 ) |
34 | #define SCAN_INTERVAL (HZ/10) | 35 | #define SCAN_INTERVAL (HZ/10) |
35 | #define CORGIKBD_PRESSED 1 | ||
36 | 36 | ||
37 | #define HINGE_SCAN_INTERVAL (HZ/4) | 37 | #define HINGE_SCAN_INTERVAL (HZ/4) |
38 | 38 | ||
@@ -73,25 +73,13 @@ struct corgikbd { | |||
73 | struct input_dev input; | 73 | struct input_dev input; |
74 | char phys[32]; | 74 | char phys[32]; |
75 | 75 | ||
76 | unsigned char state[ARRAY_SIZE(corgikbd_keycode)]; | ||
77 | spinlock_t lock; | 76 | spinlock_t lock; |
78 | |||
79 | struct timer_list timer; | 77 | struct timer_list timer; |
80 | struct timer_list htimer; | 78 | struct timer_list htimer; |
81 | }; | ||
82 | 79 | ||
83 | static void handle_scancode(unsigned int pressed,unsigned int scancode, struct corgikbd *corgikbd_data) | 80 | unsigned int suspended; |
84 | { | 81 | unsigned long suspend_jiffies; |
85 | if (pressed && !(corgikbd_data->state[scancode] & CORGIKBD_PRESSED)) { | 82 | }; |
86 | corgikbd_data->state[scancode] |= CORGIKBD_PRESSED; | ||
87 | input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 1); | ||
88 | if (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF) | ||
89 | input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1); | ||
90 | } else if (!pressed && corgikbd_data->state[scancode] & CORGIKBD_PRESSED) { | ||
91 | corgikbd_data->state[scancode] &= ~CORGIKBD_PRESSED; | ||
92 | input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 0); | ||
93 | } | ||
94 | } | ||
95 | 83 | ||
96 | #define KB_DISCHARGE_DELAY 10 | 84 | #define KB_DISCHARGE_DELAY 10 |
97 | #define KB_ACTIVATE_DELAY 10 | 85 | #define KB_ACTIVATE_DELAY 10 |
@@ -105,36 +93,36 @@ static void handle_scancode(unsigned int pressed,unsigned int scancode, struct c | |||
105 | */ | 93 | */ |
106 | static inline void corgikbd_discharge_all(void) | 94 | static inline void corgikbd_discharge_all(void) |
107 | { | 95 | { |
108 | // STROBE All HiZ | 96 | /* STROBE All HiZ */ |
109 | GPCR2 = CORGI_GPIO_ALL_STROBE_BIT; | 97 | GPCR2 = CORGI_GPIO_ALL_STROBE_BIT; |
110 | GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT; | 98 | GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT; |
111 | } | 99 | } |
112 | 100 | ||
113 | static inline void corgikbd_activate_all(void) | 101 | static inline void corgikbd_activate_all(void) |
114 | { | 102 | { |
115 | // STROBE ALL -> High | 103 | /* STROBE ALL -> High */ |
116 | GPSR2 = CORGI_GPIO_ALL_STROBE_BIT; | 104 | GPSR2 = CORGI_GPIO_ALL_STROBE_BIT; |
117 | GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT; | 105 | GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT; |
118 | 106 | ||
119 | udelay(KB_DISCHARGE_DELAY); | 107 | udelay(KB_DISCHARGE_DELAY); |
120 | 108 | ||
121 | // Clear any interrupts we may have triggered when altering the GPIO lines | 109 | /* Clear any interrupts we may have triggered when altering the GPIO lines */ |
122 | GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT; | 110 | GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT; |
123 | GEDR2 = CORGI_GPIO_LOW_SENSE_BIT; | 111 | GEDR2 = CORGI_GPIO_LOW_SENSE_BIT; |
124 | } | 112 | } |
125 | 113 | ||
126 | static inline void corgikbd_activate_col(int col) | 114 | static inline void corgikbd_activate_col(int col) |
127 | { | 115 | { |
128 | // STROBE col -> High, not col -> HiZ | 116 | /* STROBE col -> High, not col -> HiZ */ |
129 | GPSR2 = CORGI_GPIO_STROBE_BIT(col); | 117 | GPSR2 = CORGI_GPIO_STROBE_BIT(col); |
130 | GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); | 118 | GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); |
131 | } | 119 | } |
132 | 120 | ||
133 | static inline void corgikbd_reset_col(int col) | 121 | static inline void corgikbd_reset_col(int col) |
134 | { | 122 | { |
135 | // STROBE col -> Low | 123 | /* STROBE col -> Low */ |
136 | GPCR2 = CORGI_GPIO_STROBE_BIT(col); | 124 | GPCR2 = CORGI_GPIO_STROBE_BIT(col); |
137 | // STROBE col -> out, not col -> HiZ | 125 | /* STROBE col -> out, not col -> HiZ */ |
138 | GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); | 126 | GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); |
139 | } | 127 | } |
140 | 128 | ||
@@ -149,10 +137,13 @@ static inline void corgikbd_reset_col(int col) | |||
149 | /* Scan the hardware keyboard and push any changes up through the input layer */ | 137 | /* Scan the hardware keyboard and push any changes up through the input layer */ |
150 | static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs) | 138 | static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs) |
151 | { | 139 | { |
152 | unsigned int row, col, rowd, scancode; | 140 | unsigned int row, col, rowd; |
153 | unsigned long flags; | 141 | unsigned long flags; |
154 | unsigned int num_pressed; | 142 | unsigned int num_pressed; |
155 | 143 | ||
144 | if (corgikbd_data->suspended) | ||
145 | return; | ||
146 | |||
156 | spin_lock_irqsave(&corgikbd_data->lock, flags); | 147 | spin_lock_irqsave(&corgikbd_data->lock, flags); |
157 | 148 | ||
158 | if (regs) | 149 | if (regs) |
@@ -173,10 +164,21 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs | |||
173 | 164 | ||
174 | rowd = GET_ROWS_STATUS(col); | 165 | rowd = GET_ROWS_STATUS(col); |
175 | for (row = 0; row < KB_ROWS; row++) { | 166 | for (row = 0; row < KB_ROWS; row++) { |
167 | unsigned int scancode, pressed; | ||
168 | |||
176 | scancode = SCANCODE(row, col); | 169 | scancode = SCANCODE(row, col); |
177 | handle_scancode((rowd & KB_ROWMASK(row)), scancode, corgikbd_data); | 170 | pressed = rowd & KB_ROWMASK(row); |
178 | if (rowd & KB_ROWMASK(row)) | 171 | |
172 | input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], pressed); | ||
173 | |||
174 | if (pressed) | ||
179 | num_pressed++; | 175 | num_pressed++; |
176 | |||
177 | if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF) | ||
178 | && time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) { | ||
179 | input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1); | ||
180 | corgikbd_data->suspend_jiffies=jiffies; | ||
181 | } | ||
180 | } | 182 | } |
181 | corgikbd_reset_col(col); | 183 | corgikbd_reset_col(col); |
182 | } | 184 | } |
@@ -221,8 +223,11 @@ static void corgikbd_timer_callback(unsigned long data) | |||
221 | * The hinge switches generate no interrupt so they need to be | 223 | * The hinge switches generate no interrupt so they need to be |
222 | * monitored by a timer. | 224 | * monitored by a timer. |
223 | * | 225 | * |
224 | * When we detect changes, we debounce it and then pass the three | 226 | * We debounce the switches and pass them to the input system. |
225 | * positions the system can take as keypresses to the input system. | 227 | * |
228 | * gprr == 0x00 - Keyboard with Landscape Screen | ||
229 | * 0x08 - No Keyboard with Portrait Screen | ||
230 | * 0x0c - Keyboard and Screen Closed | ||
226 | */ | 231 | */ |
227 | 232 | ||
228 | #define HINGE_STABLE_COUNT 2 | 233 | #define HINGE_STABLE_COUNT 2 |
@@ -235,7 +240,7 @@ static void corgikbd_hinge_timer(unsigned long data) | |||
235 | unsigned long gprr; | 240 | unsigned long gprr; |
236 | unsigned long flags; | 241 | unsigned long flags; |
237 | 242 | ||
238 | gprr = read_scoop_reg(SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB); | 243 | gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB); |
239 | if (gprr != sharpsl_hinge_state) { | 244 | if (gprr != sharpsl_hinge_state) { |
240 | hinge_count = 0; | 245 | hinge_count = 0; |
241 | sharpsl_hinge_state = gprr; | 246 | sharpsl_hinge_state = gprr; |
@@ -244,9 +249,8 @@ static void corgikbd_hinge_timer(unsigned long data) | |||
244 | if (hinge_count >= HINGE_STABLE_COUNT) { | 249 | if (hinge_count >= HINGE_STABLE_COUNT) { |
245 | spin_lock_irqsave(&corgikbd_data->lock, flags); | 250 | spin_lock_irqsave(&corgikbd_data->lock, flags); |
246 | 251 | ||
247 | handle_scancode((sharpsl_hinge_state == 0x00), 125, corgikbd_data); /* Keyboard with Landscape Screen */ | 252 | input_report_switch(&corgikbd_data->input, SW_0, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0)); |
248 | handle_scancode((sharpsl_hinge_state == 0x08), 126, corgikbd_data); /* No Keyboard with Portrait Screen */ | 253 | input_report_switch(&corgikbd_data->input, SW_1, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0)); |
249 | handle_scancode((sharpsl_hinge_state == 0x0c), 127, corgikbd_data); /* Keyboard and Screen Closed */ | ||
250 | input_sync(&corgikbd_data->input); | 254 | input_sync(&corgikbd_data->input); |
251 | 255 | ||
252 | spin_unlock_irqrestore(&corgikbd_data->lock, flags); | 256 | spin_unlock_irqrestore(&corgikbd_data->lock, flags); |
@@ -255,19 +259,45 @@ static void corgikbd_hinge_timer(unsigned long data) | |||
255 | mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL); | 259 | mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL); |
256 | } | 260 | } |
257 | 261 | ||
262 | #ifdef CONFIG_PM | ||
263 | static int corgikbd_suspend(struct device *dev, pm_message_t state, uint32_t level) | ||
264 | { | ||
265 | if (level == SUSPEND_POWER_DOWN) { | ||
266 | struct corgikbd *corgikbd = dev_get_drvdata(dev); | ||
267 | corgikbd->suspended = 1; | ||
268 | } | ||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int corgikbd_resume(struct device *dev, uint32_t level) | ||
273 | { | ||
274 | if (level == RESUME_POWER_ON) { | ||
275 | struct corgikbd *corgikbd = dev_get_drvdata(dev); | ||
276 | |||
277 | /* Upon resume, ignore the suspend key for a short while */ | ||
278 | corgikbd->suspend_jiffies=jiffies; | ||
279 | corgikbd->suspended = 0; | ||
280 | } | ||
281 | return 0; | ||
282 | } | ||
283 | #else | ||
284 | #define corgikbd_suspend NULL | ||
285 | #define corgikbd_resume NULL | ||
286 | #endif | ||
287 | |||
258 | static int __init corgikbd_probe(struct device *dev) | 288 | static int __init corgikbd_probe(struct device *dev) |
259 | { | 289 | { |
260 | int i; | 290 | int i; |
261 | struct corgikbd *corgikbd; | 291 | struct corgikbd *corgikbd; |
262 | 292 | ||
263 | corgikbd = kcalloc(1, sizeof(struct corgikbd), GFP_KERNEL); | 293 | corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL); |
264 | if (!corgikbd) | 294 | if (!corgikbd) |
265 | return -ENOMEM; | 295 | return -ENOMEM; |
266 | 296 | ||
267 | dev_set_drvdata(dev,corgikbd); | 297 | dev_set_drvdata(dev,corgikbd); |
268 | strcpy(corgikbd->phys, "corgikbd/input0"); | 298 | strcpy(corgikbd->phys, "corgikbd/input0"); |
269 | 299 | ||
270 | spin_lock_init(corgikbd->lock); | 300 | spin_lock_init(&corgikbd->lock); |
271 | 301 | ||
272 | /* Init Keyboard rescan timer */ | 302 | /* Init Keyboard rescan timer */ |
273 | init_timer(&corgikbd->timer); | 303 | init_timer(&corgikbd->timer); |
@@ -279,6 +309,8 @@ static int __init corgikbd_probe(struct device *dev) | |||
279 | corgikbd->htimer.function = corgikbd_hinge_timer; | 309 | corgikbd->htimer.function = corgikbd_hinge_timer; |
280 | corgikbd->htimer.data = (unsigned long) corgikbd; | 310 | corgikbd->htimer.data = (unsigned long) corgikbd; |
281 | 311 | ||
312 | corgikbd->suspend_jiffies=jiffies; | ||
313 | |||
282 | init_input_dev(&corgikbd->input); | 314 | init_input_dev(&corgikbd->input); |
283 | corgikbd->input.private = corgikbd; | 315 | corgikbd->input.private = corgikbd; |
284 | corgikbd->input.name = "Corgi Keyboard"; | 316 | corgikbd->input.name = "Corgi Keyboard"; |
@@ -288,7 +320,7 @@ static int __init corgikbd_probe(struct device *dev) | |||
288 | corgikbd->input.id.vendor = 0x0001; | 320 | corgikbd->input.id.vendor = 0x0001; |
289 | corgikbd->input.id.product = 0x0001; | 321 | corgikbd->input.id.product = 0x0001; |
290 | corgikbd->input.id.version = 0x0100; | 322 | corgikbd->input.id.version = 0x0100; |
291 | corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR); | 323 | corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW); |
292 | corgikbd->input.keycode = corgikbd->keycode; | 324 | corgikbd->input.keycode = corgikbd->keycode; |
293 | corgikbd->input.keycodesize = sizeof(unsigned char); | 325 | corgikbd->input.keycodesize = sizeof(unsigned char); |
294 | corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode); | 326 | corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode); |
@@ -297,6 +329,8 @@ static int __init corgikbd_probe(struct device *dev) | |||
297 | for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++) | 329 | for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++) |
298 | set_bit(corgikbd->keycode[i], corgikbd->input.keybit); | 330 | set_bit(corgikbd->keycode[i], corgikbd->input.keybit); |
299 | clear_bit(0, corgikbd->input.keybit); | 331 | clear_bit(0, corgikbd->input.keybit); |
332 | set_bit(SW_0, corgikbd->input.swbit); | ||
333 | set_bit(SW_1, corgikbd->input.swbit); | ||
300 | 334 | ||
301 | input_register_device(&corgikbd->input); | 335 | input_register_device(&corgikbd->input); |
302 | mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL); | 336 | mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL); |
@@ -343,6 +377,8 @@ static struct device_driver corgikbd_driver = { | |||
343 | .bus = &platform_bus_type, | 377 | .bus = &platform_bus_type, |
344 | .probe = corgikbd_probe, | 378 | .probe = corgikbd_probe, |
345 | .remove = corgikbd_remove, | 379 | .remove = corgikbd_remove, |
380 | .suspend = corgikbd_suspend, | ||
381 | .resume = corgikbd_resume, | ||
346 | }; | 382 | }; |
347 | 383 | ||
348 | static int __devinit corgikbd_init(void) | 384 | static int __devinit corgikbd_init(void) |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 2bb2fe78bdca..12bdd3eff923 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -883,7 +883,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
883 | psmouse_deactivate(parent); | 883 | psmouse_deactivate(parent); |
884 | } | 884 | } |
885 | 885 | ||
886 | if (!(psmouse = kcalloc(1, sizeof(struct psmouse), GFP_KERNEL))) { | 886 | if (!(psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL))) { |
887 | retval = -ENOMEM; | 887 | retval = -ENOMEM; |
888 | goto out; | 888 | goto out; |
889 | } | 889 | } |
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 79ca38469159..1bd88fca0542 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c | |||
@@ -87,7 +87,7 @@ static int serport_ldisc_open(struct tty_struct *tty) | |||
87 | if (!capable(CAP_SYS_ADMIN)) | 87 | if (!capable(CAP_SYS_ADMIN)) |
88 | return -EPERM; | 88 | return -EPERM; |
89 | 89 | ||
90 | serport = kcalloc(1, sizeof(struct serport), GFP_KERNEL); | 90 | serport = kzalloc(sizeof(struct serport), GFP_KERNEL); |
91 | if (!serport) | 91 | if (!serport) |
92 | return -ENOMEM; | 92 | return -ENOMEM; |
93 | 93 | ||
@@ -165,7 +165,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u | |||
165 | if (test_and_set_bit(SERPORT_BUSY, &serport->flags)) | 165 | if (test_and_set_bit(SERPORT_BUSY, &serport->flags)) |
166 | return -EBUSY; | 166 | return -EBUSY; |
167 | 167 | ||
168 | serport->serio = serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL); | 168 | serport->serio = serio = kzalloc(sizeof(struct serio), GFP_KERNEL); |
169 | if (!serio) | 169 | if (!serio) |
170 | return -ENOMEM; | 170 | return -ENOMEM; |
171 | 171 | ||
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c index 3f8b61cfbc37..5d19261b884f 100644 --- a/drivers/input/touchscreen/corgi_ts.c +++ b/drivers/input/touchscreen/corgi_ts.c | |||
@@ -53,11 +53,8 @@ struct corgi_ts { | |||
53 | 53 | ||
54 | #define SyncHS() while((STATUS_HSYNC) == 0); while((STATUS_HSYNC) != 0); | 54 | #define SyncHS() while((STATUS_HSYNC) == 0); while((STATUS_HSYNC) != 0); |
55 | #define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a)) | 55 | #define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a)) |
56 | #define CCNT_ON() {int pmnc = 1; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));} | 56 | #define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x)) |
57 | #define CCNT_OFF() {int pmnc = 0; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));} | 57 | #define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x)) |
58 | |||
59 | #define WAIT_HS_400_VGA 7013U // 17.615us | ||
60 | #define WAIT_HS_400_QVGA 16622U // 41.750us | ||
61 | 58 | ||
62 | 59 | ||
63 | /* ADS7846 Touch Screen Controller bit definitions */ | 60 | /* ADS7846 Touch Screen Controller bit definitions */ |
@@ -69,41 +66,29 @@ struct corgi_ts { | |||
69 | #define ADSCTRL_STS (1u << 7) /* Start Bit */ | 66 | #define ADSCTRL_STS (1u << 7) /* Start Bit */ |
70 | 67 | ||
71 | /* External Functions */ | 68 | /* External Functions */ |
72 | extern int w100fb_get_xres(void); | 69 | extern unsigned long w100fb_get_hsynclen(struct device *dev); |
73 | extern int w100fb_get_blanking(void); | ||
74 | extern int w100fb_get_fastsysclk(void); | ||
75 | extern unsigned int get_clk_frequency_khz(int info); | 70 | extern unsigned int get_clk_frequency_khz(int info); |
76 | 71 | ||
77 | static unsigned long calc_waittime(void) | 72 | static unsigned long calc_waittime(void) |
78 | { | 73 | { |
79 | int w100fb_xres = w100fb_get_xres(); | 74 | unsigned long hsync_len = w100fb_get_hsynclen(&corgifb_device.dev); |
80 | unsigned int waittime = 0; | ||
81 | |||
82 | if (w100fb_xres == 480 || w100fb_xres == 640) { | ||
83 | waittime = WAIT_HS_400_VGA * get_clk_frequency_khz(0) / 398131U; | ||
84 | |||
85 | if (w100fb_get_fastsysclk() == 100) | ||
86 | waittime = waittime * 75 / 100; | ||
87 | |||
88 | if (w100fb_xres == 640) | ||
89 | waittime *= 3; | ||
90 | 75 | ||
91 | return waittime; | 76 | if (hsync_len) |
92 | } | 77 | return get_clk_frequency_khz(0)*1000/hsync_len; |
93 | 78 | else | |
94 | return WAIT_HS_400_QVGA * get_clk_frequency_khz(0) / 398131U; | 79 | return 0; |
95 | } | 80 | } |
96 | 81 | ||
97 | static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int address, unsigned long wait_time) | 82 | static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int address, unsigned long wait_time) |
98 | { | 83 | { |
84 | unsigned long timer1 = 0, timer2, pmnc = 0; | ||
99 | int pos = 0; | 85 | int pos = 0; |
100 | unsigned long timer1 = 0, timer2; | ||
101 | int dosleep; | ||
102 | 86 | ||
103 | dosleep = !w100fb_get_blanking(); | 87 | if (wait_time && doSend) { |
88 | PMNC_GET(pmnc); | ||
89 | if (!(pmnc & 0x01)) | ||
90 | PMNC_SET(0x01); | ||
104 | 91 | ||
105 | if (dosleep && doSend) { | ||
106 | CCNT_ON(); | ||
107 | /* polling HSync */ | 92 | /* polling HSync */ |
108 | SyncHS(); | 93 | SyncHS(); |
109 | /* get CCNT */ | 94 | /* get CCNT */ |
@@ -119,11 +104,11 @@ static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int add | |||
119 | corgi_ssp_ads7846_put(cmd); | 104 | corgi_ssp_ads7846_put(cmd); |
120 | corgi_ssp_ads7846_get(); | 105 | corgi_ssp_ads7846_get(); |
121 | 106 | ||
122 | if (dosleep) { | 107 | if (wait_time) { |
123 | /* Wait after HSync */ | 108 | /* Wait after HSync */ |
124 | CCNT(timer2); | 109 | CCNT(timer2); |
125 | if (timer2-timer1 > wait_time) { | 110 | if (timer2-timer1 > wait_time) { |
126 | /* timeout */ | 111 | /* too slow - timeout, try again */ |
127 | SyncHS(); | 112 | SyncHS(); |
128 | /* get OSCR */ | 113 | /* get OSCR */ |
129 | CCNT(timer1); | 114 | CCNT(timer1); |
@@ -134,8 +119,8 @@ static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int add | |||
134 | CCNT(timer2); | 119 | CCNT(timer2); |
135 | } | 120 | } |
136 | corgi_ssp_ads7846_put(cmd); | 121 | corgi_ssp_ads7846_put(cmd); |
137 | if (dosleep) | 122 | if (wait_time && !(pmnc & 0x01)) |
138 | CCNT_OFF(); | 123 | PMNC_SET(pmnc); |
139 | } | 124 | } |
140 | return pos; | 125 | return pos; |
141 | } | 126 | } |
@@ -244,7 +229,7 @@ static irqreturn_t ts_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
244 | } | 229 | } |
245 | 230 | ||
246 | #ifdef CONFIG_PM | 231 | #ifdef CONFIG_PM |
247 | static int corgits_suspend(struct device *dev, uint32_t state, uint32_t level) | 232 | static int corgits_suspend(struct device *dev, pm_message_t state, uint32_t level) |
248 | { | 233 | { |
249 | if (level == SUSPEND_POWER_DOWN) { | 234 | if (level == SUSPEND_POWER_DOWN) { |
250 | struct corgi_ts *corgi_ts = dev_get_drvdata(dev); | 235 | struct corgi_ts *corgi_ts = dev_get_drvdata(dev); |
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 17cf7663c582..6eb96cba4d29 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
11 | #include <linux/fs.h> | 11 | #include <linux/fs.h> |
12 | #include <linux/major.h> | 12 | #include <linux/major.h> |
13 | #include <asm/segment.h> | ||
14 | #include <asm/io.h> | 13 | #include <asm/io.h> |
15 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
16 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
diff --git a/drivers/isdn/i4l/isdn_v110.c b/drivers/isdn/i4l/isdn_v110.c index f47f2b9846d8..38619e8cd823 100644 --- a/drivers/isdn/i4l/isdn_v110.c +++ b/drivers/isdn/i4l/isdn_v110.c | |||
@@ -516,11 +516,11 @@ buffer_full: | |||
516 | } | 516 | } |
517 | 517 | ||
518 | int | 518 | int |
519 | isdn_v110_stat_callback(int idx, isdn_ctrl * c) | 519 | isdn_v110_stat_callback(int idx, isdn_ctrl *c) |
520 | { | 520 | { |
521 | isdn_v110_stream *v = NULL; | 521 | isdn_v110_stream *v = NULL; |
522 | int i; | 522 | int i; |
523 | int ret; | 523 | int ret = 0; |
524 | 524 | ||
525 | if (idx < 0) | 525 | if (idx < 0) |
526 | return 0; | 526 | return 0; |
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 45754bb6a799..9de000131a8a 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c | |||
@@ -239,6 +239,11 @@ static void vm_dp_init(struct dpages *dp, void *data) | |||
239 | dp->context_ptr = data; | 239 | dp->context_ptr = data; |
240 | } | 240 | } |
241 | 241 | ||
242 | static void dm_bio_destructor(struct bio *bio) | ||
243 | { | ||
244 | bio_free(bio, _bios); | ||
245 | } | ||
246 | |||
242 | /*----------------------------------------------------------------- | 247 | /*----------------------------------------------------------------- |
243 | * IO routines that accept a list of pages. | 248 | * IO routines that accept a list of pages. |
244 | *---------------------------------------------------------------*/ | 249 | *---------------------------------------------------------------*/ |
@@ -263,6 +268,7 @@ static void do_region(int rw, unsigned int region, struct io_region *where, | |||
263 | bio->bi_bdev = where->bdev; | 268 | bio->bi_bdev = where->bdev; |
264 | bio->bi_end_io = endio; | 269 | bio->bi_end_io = endio; |
265 | bio->bi_private = io; | 270 | bio->bi_private = io; |
271 | bio->bi_destructor = dm_bio_destructor; | ||
266 | bio_set_region(bio, region); | 272 | bio_set_region(bio, region); |
267 | 273 | ||
268 | /* | 274 | /* |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index d487d9deb98e..930b9fc27953 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -399,6 +399,11 @@ struct clone_info { | |||
399 | unsigned short idx; | 399 | unsigned short idx; |
400 | }; | 400 | }; |
401 | 401 | ||
402 | static void dm_bio_destructor(struct bio *bio) | ||
403 | { | ||
404 | bio_free(bio, dm_set); | ||
405 | } | ||
406 | |||
402 | /* | 407 | /* |
403 | * Creates a little bio that is just does part of a bvec. | 408 | * Creates a little bio that is just does part of a bvec. |
404 | */ | 409 | */ |
@@ -410,6 +415,7 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector, | |||
410 | struct bio_vec *bv = bio->bi_io_vec + idx; | 415 | struct bio_vec *bv = bio->bi_io_vec + idx; |
411 | 416 | ||
412 | clone = bio_alloc_bioset(GFP_NOIO, 1, dm_set); | 417 | clone = bio_alloc_bioset(GFP_NOIO, 1, dm_set); |
418 | clone->bi_destructor = dm_bio_destructor; | ||
413 | *clone->bi_io_vec = *bv; | 419 | *clone->bi_io_vec = *bv; |
414 | 420 | ||
415 | clone->bi_sector = sector; | 421 | clone->bi_sector = sector; |
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig index b12545f093f8..1e85d16491b0 100644 --- a/drivers/media/dvb/bt8xx/Kconfig +++ b/drivers/media/dvb/bt8xx/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | config DVB_BT8XX | 1 | config DVB_BT8XX |
2 | tristate "Nebula/Pinnacle PCTV/Twinhan PCI cards" | 2 | tristate "BT8xx based PCI cards" |
3 | depends on DVB_CORE && PCI && VIDEO_BT848 | 3 | depends on DVB_CORE && PCI && VIDEO_BT848 |
4 | select DVB_MT352 | 4 | select DVB_MT352 |
5 | select DVB_SP887X | 5 | select DVB_SP887X |
@@ -8,8 +8,8 @@ config DVB_BT8XX | |||
8 | select DVB_OR51211 | 8 | select DVB_OR51211 |
9 | help | 9 | help |
10 | Support for PCI cards based on the Bt8xx PCI bridge. Examples are | 10 | Support for PCI cards based on the Bt8xx PCI bridge. Examples are |
11 | the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards and | 11 | the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards, |
12 | pcHDTV HD2000 cards. | 12 | the pcHDTV HD2000 cards, and certain AVerMedia cards. |
13 | 13 | ||
14 | Since these cards have no MPEG decoder onboard, they transmit | 14 | Since these cards have no MPEG decoder onboard, they transmit |
15 | only compressed MPEG data over the PCI bus, so you need | 15 | only compressed MPEG data over the PCI bus, so you need |
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index 1f1cd7a8d500..7142b9c51dd2 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c | |||
@@ -69,8 +69,8 @@ struct lgdt330x_state | |||
69 | }; | 69 | }; |
70 | 70 | ||
71 | static int i2c_write_demod_bytes (struct lgdt330x_state* state, | 71 | static int i2c_write_demod_bytes (struct lgdt330x_state* state, |
72 | u8 *buf, /* data bytes to send */ | 72 | u8 *buf, /* data bytes to send */ |
73 | int len /* number of bytes to send */ ) | 73 | int len /* number of bytes to send */ ) |
74 | { | 74 | { |
75 | struct i2c_msg msg = | 75 | struct i2c_msg msg = |
76 | { .addr = state->config->demod_address, | 76 | { .addr = state->config->demod_address, |
@@ -129,13 +129,13 @@ static int lgdt3302_SwReset(struct lgdt330x_state* state) | |||
129 | }; | 129 | }; |
130 | 130 | ||
131 | ret = i2c_write_demod_bytes(state, | 131 | ret = i2c_write_demod_bytes(state, |
132 | reset, sizeof(reset)); | 132 | reset, sizeof(reset)); |
133 | if (ret == 0) { | 133 | if (ret == 0) { |
134 | 134 | ||
135 | /* force reset high (inactive) and unmask interrupts */ | 135 | /* force reset high (inactive) and unmask interrupts */ |
136 | reset[1] = 0x7f; | 136 | reset[1] = 0x7f; |
137 | ret = i2c_write_demod_bytes(state, | 137 | ret = i2c_write_demod_bytes(state, |
138 | reset, sizeof(reset)); | 138 | reset, sizeof(reset)); |
139 | } | 139 | } |
140 | return ret; | 140 | return ret; |
141 | } | 141 | } |
@@ -149,13 +149,13 @@ static int lgdt3303_SwReset(struct lgdt330x_state* state) | |||
149 | }; | 149 | }; |
150 | 150 | ||
151 | ret = i2c_write_demod_bytes(state, | 151 | ret = i2c_write_demod_bytes(state, |
152 | reset, sizeof(reset)); | 152 | reset, sizeof(reset)); |
153 | if (ret == 0) { | 153 | if (ret == 0) { |
154 | 154 | ||
155 | /* force reset high (inactive) */ | 155 | /* force reset high (inactive) */ |
156 | reset[1] = 0x01; | 156 | reset[1] = 0x01; |
157 | ret = i2c_write_demod_bytes(state, | 157 | ret = i2c_write_demod_bytes(state, |
158 | reset, sizeof(reset)); | 158 | reset, sizeof(reset)); |
159 | } | 159 | } |
160 | return ret; | 160 | return ret; |
161 | } | 161 | } |
@@ -172,7 +172,6 @@ static int lgdt330x_SwReset(struct lgdt330x_state* state) | |||
172 | } | 172 | } |
173 | } | 173 | } |
174 | 174 | ||
175 | |||
176 | static int lgdt330x_init(struct dvb_frontend* fe) | 175 | static int lgdt330x_init(struct dvb_frontend* fe) |
177 | { | 176 | { |
178 | /* Hardware reset is done using gpio[0] of cx23880x chip. | 177 | /* Hardware reset is done using gpio[0] of cx23880x chip. |
@@ -229,13 +228,13 @@ static int lgdt330x_init(struct dvb_frontend* fe) | |||
229 | case LGDT3302: | 228 | case LGDT3302: |
230 | chip_name = "LGDT3302"; | 229 | chip_name = "LGDT3302"; |
231 | err = i2c_write_demod_bytes(state, lgdt3302_init_data, | 230 | err = i2c_write_demod_bytes(state, lgdt3302_init_data, |
232 | sizeof(lgdt3302_init_data)); | 231 | sizeof(lgdt3302_init_data)); |
233 | break; | 232 | break; |
234 | case LGDT3303: | 233 | case LGDT3303: |
235 | chip_name = "LGDT3303"; | 234 | chip_name = "LGDT3303"; |
236 | err = i2c_write_demod_bytes(state, lgdt3303_init_data, | 235 | err = i2c_write_demod_bytes(state, lgdt3303_init_data, |
237 | sizeof(lgdt3303_init_data)); | 236 | sizeof(lgdt3303_init_data)); |
238 | break; | 237 | break; |
239 | default: | 238 | default: |
240 | chip_name = "undefined"; | 239 | chip_name = "undefined"; |
241 | printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n"); | 240 | printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n"); |
@@ -262,15 +261,15 @@ static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | |||
262 | switch (state->config->demod_chip) { | 261 | switch (state->config->demod_chip) { |
263 | case LGDT3302: | 262 | case LGDT3302: |
264 | err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1, | 263 | err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1, |
265 | buf, sizeof(buf)); | 264 | buf, sizeof(buf)); |
266 | break; | 265 | break; |
267 | case LGDT3303: | 266 | case LGDT3303: |
268 | err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1, | 267 | err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1, |
269 | buf, sizeof(buf)); | 268 | buf, sizeof(buf)); |
270 | break; | 269 | break; |
271 | default: | 270 | default: |
272 | printk(KERN_WARNING | 271 | printk(KERN_WARNING |
273 | "Only LGDT3302 and LGDT3303 are supported chips.\n"); | 272 | "Only LGDT3302 and LGDT3303 are supported chips.\n"); |
274 | err = -ENODEV; | 273 | err = -ENODEV; |
275 | } | 274 | } |
276 | 275 | ||
@@ -330,7 +329,7 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe, | |||
330 | 329 | ||
331 | if (state->config->demod_chip == LGDT3303) { | 330 | if (state->config->demod_chip == LGDT3303) { |
332 | err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data, | 331 | err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data, |
333 | sizeof(lgdt3303_8vsb_44_data)); | 332 | sizeof(lgdt3303_8vsb_44_data)); |
334 | } | 333 | } |
335 | break; | 334 | break; |
336 | 335 | ||
@@ -378,18 +377,19 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe, | |||
378 | 377 | ||
379 | /* Select the requested mode */ | 378 | /* Select the requested mode */ |
380 | i2c_write_demod_bytes(state, top_ctrl_cfg, | 379 | i2c_write_demod_bytes(state, top_ctrl_cfg, |
381 | sizeof(top_ctrl_cfg)); | 380 | sizeof(top_ctrl_cfg)); |
382 | state->config->set_ts_params(fe, 0); | 381 | if (state->config->set_ts_params) |
382 | state->config->set_ts_params(fe, 0); | ||
383 | state->current_modulation = param->u.vsb.modulation; | 383 | state->current_modulation = param->u.vsb.modulation; |
384 | } | 384 | } |
385 | 385 | ||
386 | /* Change only if we are actually changing the channel */ | 386 | /* Tune to the specified frequency */ |
387 | if (state->current_frequency != param->frequency) { | 387 | if (state->config->pll_set) |
388 | /* Tune to the new frequency */ | ||
389 | state->config->pll_set(fe, param); | 388 | state->config->pll_set(fe, param); |
390 | /* Keep track of the new frequency */ | 389 | |
391 | state->current_frequency = param->frequency; | 390 | /* Keep track of the new frequency */ |
392 | } | 391 | state->current_frequency = param->frequency; |
392 | |||
393 | lgdt330x_SwReset(state); | 393 | lgdt330x_SwReset(state); |
394 | return 0; | 394 | return 0; |
395 | } | 395 | } |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 810e7aac0a53..3e6f5347da21 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -29,7 +29,7 @@ obj-$(CONFIG_VIDEO_ZORAN_LML33R10) += saa7114.o adv7170.o zr36060.o | |||
29 | obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o | 29 | obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o |
30 | obj-$(CONFIG_VIDEO_PMS) += pms.o | 30 | obj-$(CONFIG_VIDEO_PMS) += pms.o |
31 | obj-$(CONFIG_VIDEO_PLANB) += planb.o | 31 | obj-$(CONFIG_VIDEO_PLANB) += planb.o |
32 | obj-$(CONFIG_VIDEO_VINO) += vino.o | 32 | obj-$(CONFIG_VIDEO_VINO) += vino.o saa7191.o indycam.o |
33 | obj-$(CONFIG_VIDEO_STRADIS) += stradis.o | 33 | obj-$(CONFIG_VIDEO_STRADIS) += stradis.o |
34 | obj-$(CONFIG_VIDEO_CPIA) += cpia.o | 34 | obj-$(CONFIG_VIDEO_CPIA) += cpia.o |
35 | obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o | 35 | obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o |
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index 52e32f05d625..1ca2b67aedfb 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <asm/pgtable.h> | 43 | #include <asm/pgtable.h> |
44 | #include <asm/page.h> | 44 | #include <asm/page.h> |
45 | #include <linux/sched.h> | 45 | #include <linux/sched.h> |
46 | #include <asm/segment.h> | ||
47 | #include <linux/types.h> | 46 | #include <linux/types.h> |
48 | 47 | ||
49 | #include <linux/videodev.h> | 48 | #include <linux/videodev.h> |
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c index b5ed9544bdea..173bca1e0295 100644 --- a/drivers/media/video/adv7175.c +++ b/drivers/media/video/adv7175.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <asm/pgtable.h> | 39 | #include <asm/pgtable.h> |
40 | #include <asm/page.h> | 40 | #include <asm/page.h> |
41 | #include <linux/sched.h> | 41 | #include <linux/sched.h> |
42 | #include <asm/segment.h> | ||
43 | #include <linux/types.h> | 42 | #include <linux/types.h> |
44 | 43 | ||
45 | #include <linux/videodev.h> | 44 | #include <linux/videodev.h> |
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c index c6cfa7c48b04..3ee0afca76a7 100644 --- a/drivers/media/video/bt819.c +++ b/drivers/media/video/bt819.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <asm/pgtable.h> | 43 | #include <asm/pgtable.h> |
44 | #include <asm/page.h> | 44 | #include <asm/page.h> |
45 | #include <linux/sched.h> | 45 | #include <linux/sched.h> |
46 | #include <asm/segment.h> | ||
47 | #include <linux/types.h> | 46 | #include <linux/types.h> |
48 | 47 | ||
49 | #include <linux/videodev.h> | 48 | #include <linux/videodev.h> |
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c index c13d28658868..8eb871d0e85b 100644 --- a/drivers/media/video/bt856.c +++ b/drivers/media/video/bt856.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <asm/pgtable.h> | 43 | #include <asm/pgtable.h> |
44 | #include <asm/page.h> | 44 | #include <asm/page.h> |
45 | #include <linux/sched.h> | 45 | #include <linux/sched.h> |
46 | #include <asm/segment.h> | ||
47 | #include <linux/types.h> | 46 | #include <linux/types.h> |
48 | 47 | ||
49 | #include <linux/videodev.h> | 48 | #include <linux/videodev.h> |
diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c new file mode 100644 index 000000000000..b2b0384cd4b9 --- /dev/null +++ b/drivers/media/video/indycam.c | |||
@@ -0,0 +1,412 @@ | |||
1 | /* | ||
2 | * indycam.c - Silicon Graphics IndyCam digital camera driver | ||
3 | * | ||
4 | * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org> | ||
5 | * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi> | ||
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 version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/fs.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/major.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/sched.h> | ||
22 | |||
23 | #include <linux/videodev.h> | ||
24 | /* IndyCam decodes stream of photons into digital image representation ;-) */ | ||
25 | #include <linux/video_decoder.h> | ||
26 | #include <linux/i2c.h> | ||
27 | |||
28 | #include "indycam.h" | ||
29 | |||
30 | //#define INDYCAM_DEBUG | ||
31 | |||
32 | #define INDYCAM_MODULE_VERSION "0.0.3" | ||
33 | |||
34 | MODULE_DESCRIPTION("SGI IndyCam driver"); | ||
35 | MODULE_VERSION(INDYCAM_MODULE_VERSION); | ||
36 | MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); | ||
37 | MODULE_LICENSE("GPL"); | ||
38 | |||
39 | #ifdef INDYCAM_DEBUG | ||
40 | #define dprintk(x...) printk("IndyCam: " x); | ||
41 | #define indycam_regdump(client) indycam_regdump_debug(client) | ||
42 | #else | ||
43 | #define dprintk(x...) | ||
44 | #define indycam_regdump(client) | ||
45 | #endif | ||
46 | |||
47 | #define VINO_ADAPTER (I2C_ALGO_SGI | I2C_HW_SGI_VINO) | ||
48 | |||
49 | struct indycam { | ||
50 | struct i2c_client *client; | ||
51 | int version; | ||
52 | }; | ||
53 | |||
54 | static struct i2c_driver i2c_driver_indycam; | ||
55 | |||
56 | static const unsigned char initseq[] = { | ||
57 | INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */ | ||
58 | INDYCAM_SHUTTER_DEFAULT, /* INDYCAM_SHUTTER */ | ||
59 | INDYCAM_GAIN_DEFAULT, /* INDYCAM_GAIN */ | ||
60 | 0x00, /* INDYCAM_BRIGHTNESS (read-only) */ | ||
61 | INDYCAM_RED_BALANCE_DEFAULT, /* INDYCAM_RED_BALANCE */ | ||
62 | INDYCAM_BLUE_BALANCE_DEFAULT, /* INDYCAM_BLUE_BALANCE */ | ||
63 | INDYCAM_RED_SATURATION_DEFAULT, /* INDYCAM_RED_SATURATION */ | ||
64 | INDYCAM_BLUE_SATURATION_DEFAULT,/* INDYCAM_BLUE_SATURATION */ | ||
65 | }; | ||
66 | |||
67 | /* IndyCam register handling */ | ||
68 | |||
69 | static int indycam_read_reg(struct i2c_client *client, unsigned char reg, | ||
70 | unsigned char *value) | ||
71 | { | ||
72 | int ret; | ||
73 | |||
74 | if (reg == INDYCAM_RESET) { | ||
75 | dprintk("indycam_read_reg(): " | ||
76 | "skipping write-only register %d\n", reg); | ||
77 | *value = 0; | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | ret = i2c_smbus_read_byte_data(client, reg); | ||
82 | if (ret < 0) { | ||
83 | printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, " | ||
84 | "register = 0x%02x\n", reg); | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | *value = (unsigned char)ret; | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static int indycam_write_reg(struct i2c_client *client, unsigned char reg, | ||
94 | unsigned char value) | ||
95 | { | ||
96 | int err; | ||
97 | |||
98 | if ((reg == INDYCAM_BRIGHTNESS) | ||
99 | || (reg == INDYCAM_VERSION)) { | ||
100 | dprintk("indycam_write_reg(): " | ||
101 | "skipping read-only register %d\n", reg); | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | dprintk("Writing Reg %d = 0x%02x\n", reg, value); | ||
106 | err = i2c_smbus_write_byte_data(client, reg, value); | ||
107 | if (err) { | ||
108 | printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, " | ||
109 | "register = 0x%02x, value = 0x%02x\n", reg, value); | ||
110 | } | ||
111 | return err; | ||
112 | } | ||
113 | |||
114 | static int indycam_write_block(struct i2c_client *client, unsigned char reg, | ||
115 | unsigned char length, unsigned char *data) | ||
116 | { | ||
117 | unsigned char i; | ||
118 | int err; | ||
119 | |||
120 | for (i = reg; i < length; i++) { | ||
121 | err = indycam_write_reg(client, reg + i, data[i]); | ||
122 | if (err) | ||
123 | return err; | ||
124 | } | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | /* Helper functions */ | ||
130 | |||
131 | #ifdef INDYCAM_DEBUG | ||
132 | static void indycam_regdump_debug(struct i2c_client *client) | ||
133 | { | ||
134 | int i; | ||
135 | unsigned char val; | ||
136 | |||
137 | for (i = 0; i < 9; i++) { | ||
138 | indycam_read_reg(client, i, &val); | ||
139 | dprintk("Reg %d = 0x%02x\n", i, val); | ||
140 | } | ||
141 | } | ||
142 | #endif | ||
143 | |||
144 | static int indycam_get_controls(struct i2c_client *client, | ||
145 | struct indycam_control *ctrl) | ||
146 | { | ||
147 | unsigned char ctrl_reg; | ||
148 | |||
149 | indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg); | ||
150 | ctrl->agc = (ctrl_reg & INDYCAM_CONTROL_AGCENA) | ||
151 | ? INDYCAM_VALUE_ENABLED | ||
152 | : INDYCAM_VALUE_DISABLED; | ||
153 | ctrl->awb = (ctrl_reg & INDYCAM_CONTROL_AWBCTL) | ||
154 | ? INDYCAM_VALUE_ENABLED | ||
155 | : INDYCAM_VALUE_DISABLED; | ||
156 | indycam_read_reg(client, INDYCAM_SHUTTER, | ||
157 | (unsigned char *)&ctrl->shutter); | ||
158 | indycam_read_reg(client, INDYCAM_GAIN, | ||
159 | (unsigned char *)&ctrl->gain); | ||
160 | indycam_read_reg(client, INDYCAM_RED_BALANCE, | ||
161 | (unsigned char *)&ctrl->red_balance); | ||
162 | indycam_read_reg(client, INDYCAM_BLUE_BALANCE, | ||
163 | (unsigned char *)&ctrl->blue_balance); | ||
164 | indycam_read_reg(client, INDYCAM_RED_SATURATION, | ||
165 | (unsigned char *)&ctrl->red_saturation); | ||
166 | indycam_read_reg(client, INDYCAM_BLUE_SATURATION, | ||
167 | (unsigned char *)&ctrl->blue_saturation); | ||
168 | indycam_read_reg(client, INDYCAM_GAMMA, | ||
169 | (unsigned char *)&ctrl->gamma); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static int indycam_set_controls(struct i2c_client *client, | ||
175 | struct indycam_control *ctrl) | ||
176 | { | ||
177 | unsigned char ctrl_reg; | ||
178 | |||
179 | indycam_read_reg(client, INDYCAM_CONTROL, &ctrl_reg); | ||
180 | if (ctrl->agc != INDYCAM_VALUE_UNCHANGED) { | ||
181 | if (ctrl->agc) | ||
182 | ctrl_reg |= INDYCAM_CONTROL_AGCENA; | ||
183 | else | ||
184 | ctrl_reg &= ~INDYCAM_CONTROL_AGCENA; | ||
185 | } | ||
186 | if (ctrl->awb != INDYCAM_VALUE_UNCHANGED) { | ||
187 | if (ctrl->awb) | ||
188 | ctrl_reg |= INDYCAM_CONTROL_AWBCTL; | ||
189 | else | ||
190 | ctrl_reg &= ~INDYCAM_CONTROL_AWBCTL; | ||
191 | } | ||
192 | indycam_write_reg(client, INDYCAM_CONTROL, ctrl_reg); | ||
193 | |||
194 | if (ctrl->shutter >= 0) | ||
195 | indycam_write_reg(client, INDYCAM_SHUTTER, ctrl->shutter); | ||
196 | if (ctrl->gain >= 0) | ||
197 | indycam_write_reg(client, INDYCAM_GAIN, ctrl->gain); | ||
198 | if (ctrl->red_balance >= 0) | ||
199 | indycam_write_reg(client, INDYCAM_RED_BALANCE, | ||
200 | ctrl->red_balance); | ||
201 | if (ctrl->blue_balance >= 0) | ||
202 | indycam_write_reg(client, INDYCAM_BLUE_BALANCE, | ||
203 | ctrl->blue_balance); | ||
204 | if (ctrl->red_saturation >= 0) | ||
205 | indycam_write_reg(client, INDYCAM_RED_SATURATION, | ||
206 | ctrl->red_saturation); | ||
207 | if (ctrl->blue_saturation >= 0) | ||
208 | indycam_write_reg(client, INDYCAM_BLUE_SATURATION, | ||
209 | ctrl->blue_saturation); | ||
210 | if (ctrl->gamma >= 0) | ||
211 | indycam_write_reg(client, INDYCAM_GAMMA, ctrl->gamma); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | /* I2C-interface */ | ||
217 | |||
218 | static int indycam_attach(struct i2c_adapter *adap, int addr, int kind) | ||
219 | { | ||
220 | int err = 0; | ||
221 | struct indycam *camera; | ||
222 | struct i2c_client *client; | ||
223 | |||
224 | printk(KERN_INFO "SGI IndyCam driver version %s\n", | ||
225 | INDYCAM_MODULE_VERSION); | ||
226 | |||
227 | client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
228 | if (!client) | ||
229 | return -ENOMEM; | ||
230 | camera = kmalloc(sizeof(struct indycam), GFP_KERNEL); | ||
231 | if (!camera) { | ||
232 | err = -ENOMEM; | ||
233 | goto out_free_client; | ||
234 | } | ||
235 | |||
236 | memset(client, 0, sizeof(struct i2c_client)); | ||
237 | memset(camera, 0, sizeof(struct indycam)); | ||
238 | |||
239 | client->addr = addr; | ||
240 | client->adapter = adap; | ||
241 | client->driver = &i2c_driver_indycam; | ||
242 | client->flags = 0; | ||
243 | strcpy(client->name, "IndyCam client"); | ||
244 | i2c_set_clientdata(client, camera); | ||
245 | |||
246 | camera->client = client; | ||
247 | |||
248 | err = i2c_attach_client(client); | ||
249 | if (err) | ||
250 | goto out_free_camera; | ||
251 | |||
252 | camera->version = i2c_smbus_read_byte_data(client, INDYCAM_VERSION); | ||
253 | if (camera->version != CAMERA_VERSION_INDY && | ||
254 | camera->version != CAMERA_VERSION_MOOSE) { | ||
255 | err = -ENODEV; | ||
256 | goto out_detach_client; | ||
257 | } | ||
258 | printk(KERN_INFO "IndyCam v%d.%d detected\n", | ||
259 | INDYCAM_VERSION_MAJOR(camera->version), | ||
260 | INDYCAM_VERSION_MINOR(camera->version)); | ||
261 | |||
262 | indycam_regdump(client); | ||
263 | |||
264 | // initialize | ||
265 | err = indycam_write_block(client, 0, sizeof(initseq), | ||
266 | (unsigned char *)&initseq); | ||
267 | if (err) { | ||
268 | printk(KERN_ERR "IndyCam initalization failed\n"); | ||
269 | err = -EIO; | ||
270 | goto out_detach_client; | ||
271 | } | ||
272 | |||
273 | indycam_regdump(client); | ||
274 | |||
275 | // white balance | ||
276 | err = indycam_write_reg(client, INDYCAM_CONTROL, | ||
277 | INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL); | ||
278 | if (err) { | ||
279 | printk(KERN_ERR "IndyCam white balance " | ||
280 | "initialization failed\n"); | ||
281 | err = -EIO; | ||
282 | goto out_detach_client; | ||
283 | } | ||
284 | |||
285 | indycam_regdump(client); | ||
286 | |||
287 | printk(KERN_INFO "IndyCam initialized\n"); | ||
288 | |||
289 | return 0; | ||
290 | |||
291 | out_detach_client: | ||
292 | i2c_detach_client(client); | ||
293 | out_free_camera: | ||
294 | kfree(camera); | ||
295 | out_free_client: | ||
296 | kfree(client); | ||
297 | return err; | ||
298 | } | ||
299 | |||
300 | static int indycam_probe(struct i2c_adapter *adap) | ||
301 | { | ||
302 | /* Indy specific crap */ | ||
303 | if (adap->id == VINO_ADAPTER) | ||
304 | return indycam_attach(adap, INDYCAM_ADDR, 0); | ||
305 | /* Feel free to add probe here :-) */ | ||
306 | return -ENODEV; | ||
307 | } | ||
308 | |||
309 | static int indycam_detach(struct i2c_client *client) | ||
310 | { | ||
311 | struct indycam *camera = i2c_get_clientdata(client); | ||
312 | |||
313 | i2c_detach_client(client); | ||
314 | kfree(camera); | ||
315 | kfree(client); | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static int indycam_command(struct i2c_client *client, unsigned int cmd, | ||
320 | void *arg) | ||
321 | { | ||
322 | // struct indycam *camera = i2c_get_clientdata(client); | ||
323 | |||
324 | /* The old video_decoder interface just isn't enough, | ||
325 | * so we'll use some custom commands. */ | ||
326 | switch (cmd) { | ||
327 | case DECODER_GET_CAPABILITIES: { | ||
328 | struct video_decoder_capability *cap = arg; | ||
329 | |||
330 | cap->flags = VIDEO_DECODER_NTSC; | ||
331 | cap->inputs = 1; | ||
332 | cap->outputs = 1; | ||
333 | break; | ||
334 | } | ||
335 | case DECODER_GET_STATUS: { | ||
336 | int *iarg = arg; | ||
337 | |||
338 | *iarg = DECODER_STATUS_GOOD | DECODER_STATUS_NTSC | | ||
339 | DECODER_STATUS_COLOR; | ||
340 | break; | ||
341 | } | ||
342 | case DECODER_SET_NORM: { | ||
343 | int *iarg = arg; | ||
344 | |||
345 | switch (*iarg) { | ||
346 | case VIDEO_MODE_NTSC: | ||
347 | break; | ||
348 | default: | ||
349 | return -EINVAL; | ||
350 | } | ||
351 | break; | ||
352 | } | ||
353 | case DECODER_SET_INPUT: { | ||
354 | int *iarg = arg; | ||
355 | |||
356 | if (*iarg != 0) | ||
357 | return -EINVAL; | ||
358 | break; | ||
359 | } | ||
360 | case DECODER_SET_OUTPUT: { | ||
361 | int *iarg = arg; | ||
362 | |||
363 | if (*iarg != 0) | ||
364 | return -EINVAL; | ||
365 | break; | ||
366 | } | ||
367 | case DECODER_ENABLE_OUTPUT: { | ||
368 | /* Always enabled */ | ||
369 | break; | ||
370 | } | ||
371 | case DECODER_SET_PICTURE: { | ||
372 | // struct video_picture *pic = arg; | ||
373 | /* TODO: convert values for indycam_set_controls() */ | ||
374 | break; | ||
375 | } | ||
376 | case DECODER_INDYCAM_GET_CONTROLS: { | ||
377 | struct indycam_control *ctrl = arg; | ||
378 | indycam_get_controls(client, ctrl); | ||
379 | } | ||
380 | case DECODER_INDYCAM_SET_CONTROLS: { | ||
381 | struct indycam_control *ctrl = arg; | ||
382 | indycam_set_controls(client, ctrl); | ||
383 | } | ||
384 | default: | ||
385 | return -EINVAL; | ||
386 | } | ||
387 | |||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | static struct i2c_driver i2c_driver_indycam = { | ||
392 | .owner = THIS_MODULE, | ||
393 | .name = "indycam", | ||
394 | .id = I2C_DRIVERID_INDYCAM, | ||
395 | .flags = I2C_DF_NOTIFY, | ||
396 | .attach_adapter = indycam_probe, | ||
397 | .detach_client = indycam_detach, | ||
398 | .command = indycam_command, | ||
399 | }; | ||
400 | |||
401 | static int __init indycam_init(void) | ||
402 | { | ||
403 | return i2c_add_driver(&i2c_driver_indycam); | ||
404 | } | ||
405 | |||
406 | static void __exit indycam_exit(void) | ||
407 | { | ||
408 | i2c_del_driver(&i2c_driver_indycam); | ||
409 | } | ||
410 | |||
411 | module_init(indycam_init); | ||
412 | module_exit(indycam_exit); | ||
diff --git a/drivers/media/video/indycam.h b/drivers/media/video/indycam.h new file mode 100644 index 000000000000..d9ddb6b79a03 --- /dev/null +++ b/drivers/media/video/indycam.h | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * indycam.h - Silicon Graphics IndyCam digital camera driver | ||
3 | * | ||
4 | * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org> | ||
5 | * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi> | ||
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 version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef _INDYCAM_H_ | ||
13 | #define _INDYCAM_H_ | ||
14 | |||
15 | /* I2C address for the Guinness Camera */ | ||
16 | #define INDYCAM_ADDR 0x56 | ||
17 | |||
18 | /* Camera version */ | ||
19 | #define CAMERA_VERSION_INDY 0x10 /* v1.0 */ | ||
20 | #define CAMERA_VERSION_MOOSE 0x12 /* v1.2 */ | ||
21 | #define INDYCAM_VERSION_MAJOR(x) (((x) & 0xf0) >> 4) | ||
22 | #define INDYCAM_VERSION_MINOR(x) ((x) & 0x0f) | ||
23 | |||
24 | /* Register bus addresses */ | ||
25 | #define INDYCAM_CONTROL 0x00 | ||
26 | #define INDYCAM_SHUTTER 0x01 | ||
27 | #define INDYCAM_GAIN 0x02 | ||
28 | #define INDYCAM_BRIGHTNESS 0x03 /* read-only */ | ||
29 | #define INDYCAM_RED_BALANCE 0x04 | ||
30 | #define INDYCAM_BLUE_BALANCE 0x05 | ||
31 | #define INDYCAM_RED_SATURATION 0x06 | ||
32 | #define INDYCAM_BLUE_SATURATION 0x07 | ||
33 | #define INDYCAM_GAMMA 0x08 | ||
34 | #define INDYCAM_VERSION 0x0e /* read-only */ | ||
35 | #define INDYCAM_RESET 0x0f /* write-only */ | ||
36 | |||
37 | #define INDYCAM_LED 0x46 | ||
38 | #define INDYCAM_ORIENTATION 0x47 | ||
39 | #define INDYCAM_BUTTON 0x48 | ||
40 | |||
41 | /* Field definitions of registers */ | ||
42 | #define INDYCAM_CONTROL_AGCENA (1<<0) /* automatic gain control */ | ||
43 | #define INDYCAM_CONTROL_AWBCTL (1<<1) /* automatic white balance */ | ||
44 | /* 2-3 are reserved */ | ||
45 | #define INDYCAM_CONTROL_EVNFLD (1<<4) /* read-only */ | ||
46 | |||
47 | #define INDYCAM_SHUTTER_10000 0x02 /* 1/10000 second */ | ||
48 | #define INDYCAM_SHUTTER_4000 0x04 /* 1/4000 second */ | ||
49 | #define INDYCAM_SHUTTER_2000 0x08 /* 1/2000 second */ | ||
50 | #define INDYCAM_SHUTTER_1000 0x10 /* 1/1000 second */ | ||
51 | #define INDYCAM_SHUTTER_500 0x20 /* 1/500 second */ | ||
52 | #define INDYCAM_SHUTTER_250 0x3f /* 1/250 second */ | ||
53 | #define INDYCAM_SHUTTER_125 0x7e /* 1/125 second */ | ||
54 | #define INDYCAM_SHUTTER_100 0x9e /* 1/100 second */ | ||
55 | #define INDYCAM_SHUTTER_60 0x00 /* 1/60 second */ | ||
56 | |||
57 | #define INDYCAM_LED_ACTIVE 0x10 | ||
58 | #define INDYCAM_LED_INACTIVE 0x30 | ||
59 | #define INDYCAM_ORIENTATION_BOTTOM_TO_TOP 0x40 | ||
60 | #define INDYCAM_BUTTON_RELEASED 0x10 | ||
61 | |||
62 | #define INDYCAM_SHUTTER_MIN 0x00 | ||
63 | #define INDYCAM_SHUTTER_MAX 0xff | ||
64 | #define INDYCAM_GAIN_MIN 0x00 | ||
65 | #define INDYCAM_GAIN_MAX 0xff | ||
66 | #define INDYCAM_RED_BALANCE_MIN 0x00 /* the effect is the opposite? */ | ||
67 | #define INDYCAM_RED_BALANCE_MAX 0xff | ||
68 | #define INDYCAM_BLUE_BALANCE_MIN 0x00 /* the effect is the opposite? */ | ||
69 | #define INDYCAM_BLUE_BALANCE_MAX 0xff | ||
70 | #define INDYCAM_RED_SATURATION_MIN 0x00 | ||
71 | #define INDYCAM_RED_SATURATION_MAX 0xff | ||
72 | #define INDYCAM_BLUE_SATURATION_MIN 0x00 | ||
73 | #define INDYCAM_BLUE_SATURATION_MAX 0xff | ||
74 | #define INDYCAM_GAMMA_MIN 0x00 | ||
75 | #define INDYCAM_GAMMA_MAX 0xff | ||
76 | |||
77 | /* Driver interface definitions */ | ||
78 | |||
79 | #define INDYCAM_VALUE_ENABLED 1 | ||
80 | #define INDYCAM_VALUE_DISABLED 0 | ||
81 | #define INDYCAM_VALUE_UNCHANGED -1 | ||
82 | |||
83 | /* When setting controls, a value of -1 leaves the control unchanged. */ | ||
84 | struct indycam_control { | ||
85 | int agc; /* boolean */ | ||
86 | int awb; /* boolean */ | ||
87 | int shutter; | ||
88 | int gain; | ||
89 | int red_balance; | ||
90 | int blue_balance; | ||
91 | int red_saturation; | ||
92 | int blue_saturation; | ||
93 | int gamma; | ||
94 | }; | ||
95 | |||
96 | #define DECODER_INDYCAM_GET_CONTROLS _IOR('d', 193, struct indycam_control) | ||
97 | #define DECODER_INDYCAM_SET_CONTROLS _IOW('d', 194, struct indycam_control) | ||
98 | |||
99 | /* Default values for controls */ | ||
100 | |||
101 | #define INDYCAM_AGC_DEFAULT INDYCAM_VALUE_ENABLED | ||
102 | #define INDYCAM_AWB_DEFAULT INDYCAM_VALUE_ENABLED | ||
103 | |||
104 | #define INDYCAM_SHUTTER_DEFAULT INDYCAM_SHUTTER_60 | ||
105 | #define INDYCAM_GAIN_DEFAULT 0x80 | ||
106 | #define INDYCAM_RED_BALANCE_DEFAULT 0x18 | ||
107 | #define INDYCAM_BLUE_BALANCE_DEFAULT 0xa4 | ||
108 | #define INDYCAM_RED_SATURATION_DEFAULT 0x80 | ||
109 | #define INDYCAM_BLUE_SATURATION_DEFAULT 0xc0 | ||
110 | #define INDYCAM_GAMMA_DEFAULT 0x80 | ||
111 | |||
112 | #endif | ||
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index fe194012bccf..3f2a882bc20a 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
38 | #include <linux/interrupt.h> | 38 | #include <linux/interrupt.h> |
39 | #include <linux/vmalloc.h> | 39 | #include <linux/vmalloc.h> |
40 | #include <linux/dma-mapping.h> | ||
40 | 41 | ||
41 | #include "meye.h" | 42 | #include "meye.h" |
42 | #include <linux/meye.h> | 43 | #include <linux/meye.h> |
@@ -121,7 +122,7 @@ static int ptable_alloc(void) | |||
121 | memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable)); | 122 | memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable)); |
122 | 123 | ||
123 | /* give only 32 bit DMA addresses */ | 124 | /* give only 32 bit DMA addresses */ |
124 | if (dma_set_mask(&meye.mchip_dev->dev, 0xffffffff)) | 125 | if (dma_set_mask(&meye.mchip_dev->dev, DMA_32BIT_MASK)) |
125 | return -1; | 126 | return -1; |
126 | 127 | ||
127 | meye.mchip_ptable_toc = dma_alloc_coherent(&meye.mchip_dev->dev, | 128 | meye.mchip_ptable_toc = dma_alloc_coherent(&meye.mchip_dev->dev, |
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c index f18df53d98ff..fe8a5e453969 100644 --- a/drivers/media/video/saa7111.c +++ b/drivers/media/video/saa7111.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
43 | #include <asm/page.h> | 43 | #include <asm/page.h> |
44 | #include <linux/sched.h> | 44 | #include <linux/sched.h> |
45 | #include <asm/segment.h> | ||
46 | #include <linux/types.h> | 45 | #include <linux/types.h> |
47 | 46 | ||
48 | #include <linux/videodev.h> | 47 | #include <linux/videodev.h> |
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c index e0c70f54f073..d9f50e2f7b92 100644 --- a/drivers/media/video/saa7114.c +++ b/drivers/media/video/saa7114.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include <asm/pgtable.h> | 45 | #include <asm/pgtable.h> |
46 | #include <asm/page.h> | 46 | #include <asm/page.h> |
47 | #include <linux/sched.h> | 47 | #include <linux/sched.h> |
48 | #include <asm/segment.h> | ||
49 | #include <linux/types.h> | 48 | #include <linux/types.h> |
50 | 49 | ||
51 | #include <linux/videodev.h> | 50 | #include <linux/videodev.h> |
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c index e93412f4407c..132aa7943c16 100644 --- a/drivers/media/video/saa7185.c +++ b/drivers/media/video/saa7185.c | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <asm/pgtable.h> | 39 | #include <asm/pgtable.h> |
40 | #include <asm/page.h> | 40 | #include <asm/page.h> |
41 | #include <linux/sched.h> | 41 | #include <linux/sched.h> |
42 | #include <asm/segment.h> | ||
43 | #include <linux/types.h> | 42 | #include <linux/types.h> |
44 | 43 | ||
45 | #include <linux/videodev.h> | 44 | #include <linux/videodev.h> |
diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c new file mode 100644 index 000000000000..454f5c1199b4 --- /dev/null +++ b/drivers/media/video/saa7191.c | |||
@@ -0,0 +1,512 @@ | |||
1 | /* | ||
2 | * saa7191.c - Philips SAA7191 video decoder driver | ||
3 | * | ||
4 | * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org> | ||
5 | * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi> | ||
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 version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/fs.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/major.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/sched.h> | ||
22 | |||
23 | #include <linux/videodev.h> | ||
24 | #include <linux/video_decoder.h> | ||
25 | #include <linux/i2c.h> | ||
26 | |||
27 | #include "saa7191.h" | ||
28 | |||
29 | #define SAA7191_MODULE_VERSION "0.0.3" | ||
30 | |||
31 | MODULE_DESCRIPTION("Philips SAA7191 video decoder driver"); | ||
32 | MODULE_VERSION(SAA7191_MODULE_VERSION); | ||
33 | MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); | ||
34 | MODULE_LICENSE("GPL"); | ||
35 | |||
36 | #define VINO_ADAPTER (I2C_ALGO_SGI | I2C_HW_SGI_VINO) | ||
37 | |||
38 | struct saa7191 { | ||
39 | struct i2c_client *client; | ||
40 | |||
41 | /* the register values are stored here as the actual | ||
42 | * I2C-registers are write-only */ | ||
43 | unsigned char reg[25]; | ||
44 | |||
45 | unsigned char norm; | ||
46 | unsigned char input; | ||
47 | }; | ||
48 | |||
49 | static struct i2c_driver i2c_driver_saa7191; | ||
50 | |||
51 | static const unsigned char initseq[] = { | ||
52 | 0, /* Subaddress */ | ||
53 | 0x50, /* SAA7191_REG_IDEL */ | ||
54 | 0x30, /* SAA7191_REG_HSYB */ | ||
55 | 0x00, /* SAA7191_REG_HSYS */ | ||
56 | 0xe8, /* SAA7191_REG_HCLB */ | ||
57 | 0xb6, /* SAA7191_REG_HCLS */ | ||
58 | 0xf4, /* SAA7191_REG_HPHI */ | ||
59 | 0x01, /* SAA7191_REG_LUMA - chrominance trap active (CVBS) */ | ||
60 | 0x00, /* SAA7191_REG_HUEC */ | ||
61 | 0xf8, /* SAA7191_REG_CKTQ */ | ||
62 | 0xf8, /* SAA7191_REG_CKTS */ | ||
63 | 0x90, /* SAA7191_REG_PLSE */ | ||
64 | 0x90, /* SAA7191_REG_SESE */ | ||
65 | 0x00, /* SAA7191_REG_GAIN */ | ||
66 | 0x0c, /* SAA7191_REG_STDC - not SECAM, slow time constant */ | ||
67 | 0x78, /* SAA7191_REG_IOCK - chrominance from CVBS, GPSW1 & 2 off */ | ||
68 | 0x99, /* SAA7191_REG_CTL3 - automatic field detection */ | ||
69 | 0x00, /* SAA7191_REG_CTL4 */ | ||
70 | 0x2c, /* SAA7191_REG_CHCV */ | ||
71 | 0x00, /* unused */ | ||
72 | 0x00, /* unused */ | ||
73 | 0x34, /* SAA7191_REG_HS6B */ | ||
74 | 0x0a, /* SAA7191_REG_HS6S */ | ||
75 | 0xf4, /* SAA7191_REG_HC6B */ | ||
76 | 0xce, /* SAA7191_REG_HC6S */ | ||
77 | 0xf4, /* SAA7191_REG_HP6I */ | ||
78 | }; | ||
79 | |||
80 | /* SAA7191 register handling */ | ||
81 | |||
82 | static unsigned char saa7191_read_reg(struct i2c_client *client, | ||
83 | unsigned char reg) | ||
84 | { | ||
85 | return ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg]; | ||
86 | } | ||
87 | |||
88 | static int saa7191_read_status(struct i2c_client *client, | ||
89 | unsigned char *value) | ||
90 | { | ||
91 | int ret; | ||
92 | |||
93 | ret = i2c_master_recv(client, value, 1); | ||
94 | if (ret < 0) { | ||
95 | printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed"); | ||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | |||
103 | static int saa7191_write_reg(struct i2c_client *client, unsigned char reg, | ||
104 | unsigned char value) | ||
105 | { | ||
106 | |||
107 | ((struct saa7191 *)i2c_get_clientdata(client))->reg[reg] = value; | ||
108 | return i2c_smbus_write_byte_data(client, reg, value); | ||
109 | } | ||
110 | |||
111 | /* the first byte of data must be the first subaddress number (register) */ | ||
112 | static int saa7191_write_block(struct i2c_client *client, | ||
113 | unsigned char length, unsigned char *data) | ||
114 | { | ||
115 | int i; | ||
116 | int ret; | ||
117 | |||
118 | struct saa7191 *decoder = (struct saa7191 *)i2c_get_clientdata(client); | ||
119 | for (i = 0; i < (length - 1); i++) { | ||
120 | decoder->reg[data[0] + i] = data[i + 1]; | ||
121 | } | ||
122 | |||
123 | ret = i2c_master_send(client, data, length); | ||
124 | if (ret < 0) { | ||
125 | printk(KERN_ERR "SAA7191: saa7191_write_block(): " | ||
126 | "write failed"); | ||
127 | return ret; | ||
128 | } | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | /* Helper functions */ | ||
134 | |||
135 | static int saa7191_set_input(struct i2c_client *client, int input) | ||
136 | { | ||
137 | unsigned char luma = saa7191_read_reg(client, SAA7191_REG_LUMA); | ||
138 | unsigned char iock = saa7191_read_reg(client, SAA7191_REG_IOCK); | ||
139 | int err; | ||
140 | |||
141 | switch (input) { | ||
142 | case SAA7191_INPUT_COMPOSITE: /* Set Composite input */ | ||
143 | iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1 | ||
144 | | SAA7191_IOCK_GPSW2); | ||
145 | /* Chrominance trap active */ | ||
146 | luma &= ~SAA7191_LUMA_BYPS; | ||
147 | break; | ||
148 | case SAA7191_INPUT_SVIDEO: /* Set S-Video input */ | ||
149 | iock |= SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW2; | ||
150 | /* Chrominance trap bypassed */ | ||
151 | luma |= SAA7191_LUMA_BYPS; | ||
152 | break; | ||
153 | default: | ||
154 | return -EINVAL; | ||
155 | } | ||
156 | |||
157 | err = saa7191_write_reg(client, SAA7191_REG_LUMA, luma); | ||
158 | if (err) | ||
159 | return -EIO; | ||
160 | err = saa7191_write_reg(client, SAA7191_REG_IOCK, iock); | ||
161 | if (err) | ||
162 | return -EIO; | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static int saa7191_set_norm(struct i2c_client *client, int norm) | ||
168 | { | ||
169 | struct saa7191 *decoder = i2c_get_clientdata(client); | ||
170 | unsigned char stdc = saa7191_read_reg(client, SAA7191_REG_STDC); | ||
171 | unsigned char ctl3 = saa7191_read_reg(client, SAA7191_REG_CTL3); | ||
172 | unsigned char chcv = saa7191_read_reg(client, SAA7191_REG_CHCV); | ||
173 | int err; | ||
174 | |||
175 | switch(norm) { | ||
176 | case SAA7191_NORM_AUTO: { | ||
177 | unsigned char status; | ||
178 | |||
179 | // does status depend on current norm ? | ||
180 | if (saa7191_read_status(client, &status)) | ||
181 | return -EIO; | ||
182 | |||
183 | stdc &= ~SAA7191_STDC_SECS; | ||
184 | ctl3 &= ~SAA7191_CTL3_FSEL; | ||
185 | ctl3 |= SAA7191_CTL3_AUFD; | ||
186 | chcv = (status & SAA7191_STATUS_FIDT) | ||
187 | ? SAA7191_CHCV_NTSC : SAA7191_CHCV_PAL; | ||
188 | break; | ||
189 | } | ||
190 | case SAA7191_NORM_PAL: | ||
191 | stdc &= ~SAA7191_STDC_SECS; | ||
192 | ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL); | ||
193 | chcv = SAA7191_CHCV_PAL; | ||
194 | break; | ||
195 | case SAA7191_NORM_NTSC: | ||
196 | stdc &= ~SAA7191_STDC_SECS; | ||
197 | ctl3 &= ~SAA7191_CTL3_AUFD; | ||
198 | ctl3 |= SAA7191_CTL3_FSEL; | ||
199 | chcv = SAA7191_CHCV_NTSC; | ||
200 | break; | ||
201 | case SAA7191_NORM_SECAM: | ||
202 | stdc |= SAA7191_STDC_SECS; | ||
203 | ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL); | ||
204 | chcv = SAA7191_CHCV_PAL; | ||
205 | break; | ||
206 | default: | ||
207 | return -EINVAL; | ||
208 | } | ||
209 | |||
210 | err = saa7191_write_reg(client, SAA7191_REG_CTL3, ctl3); | ||
211 | if (err) | ||
212 | return -EIO; | ||
213 | err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc); | ||
214 | if (err) | ||
215 | return -EIO; | ||
216 | err = saa7191_write_reg(client, SAA7191_REG_CHCV, chcv); | ||
217 | if (err) | ||
218 | return -EIO; | ||
219 | |||
220 | decoder->norm = norm; | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static int saa7191_get_controls(struct i2c_client *client, | ||
226 | struct saa7191_control *ctrl) | ||
227 | { | ||
228 | unsigned char hue = saa7191_read_reg(client, SAA7191_REG_HUEC); | ||
229 | unsigned char stdc = saa7191_read_reg(client, SAA7191_REG_STDC); | ||
230 | |||
231 | if (hue < 0x80) { | ||
232 | hue += 0x80; | ||
233 | } else { | ||
234 | hue -= 0x80; | ||
235 | } | ||
236 | ctrl->hue = hue; | ||
237 | |||
238 | ctrl->vtrc = (stdc & SAA7191_STDC_VTRC) | ||
239 | ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED; | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int saa7191_set_controls(struct i2c_client *client, | ||
245 | struct saa7191_control *ctrl) | ||
246 | { | ||
247 | int err; | ||
248 | |||
249 | if (ctrl->hue >= 0) { | ||
250 | unsigned char hue = ctrl->hue & 0xff; | ||
251 | if (hue < 0x80) { | ||
252 | hue += 0x80; | ||
253 | } else { | ||
254 | hue -= 0x80; | ||
255 | } | ||
256 | err = saa7191_write_reg(client, SAA7191_REG_HUEC, hue); | ||
257 | if (err) | ||
258 | return -EIO; | ||
259 | } | ||
260 | if (ctrl->vtrc >= 0) { | ||
261 | unsigned char stdc = | ||
262 | saa7191_read_reg(client, SAA7191_REG_STDC); | ||
263 | |||
264 | if (ctrl->vtrc) { | ||
265 | stdc |= SAA7191_STDC_VTRC; | ||
266 | } else { | ||
267 | stdc &= ~SAA7191_STDC_VTRC; | ||
268 | } | ||
269 | |||
270 | err = saa7191_write_reg(client, SAA7191_REG_STDC, stdc); | ||
271 | if (err) | ||
272 | return -EIO; | ||
273 | } | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | /* I2C-interface */ | ||
279 | |||
280 | static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind) | ||
281 | { | ||
282 | int err = 0; | ||
283 | struct saa7191 *decoder; | ||
284 | struct i2c_client *client; | ||
285 | |||
286 | printk(KERN_INFO "Philips SAA7191 driver version %s\n", | ||
287 | SAA7191_MODULE_VERSION); | ||
288 | |||
289 | client = kmalloc(sizeof(*client), GFP_KERNEL); | ||
290 | if (!client) | ||
291 | return -ENOMEM; | ||
292 | decoder = kmalloc(sizeof(*decoder), GFP_KERNEL); | ||
293 | if (!decoder) { | ||
294 | err = -ENOMEM; | ||
295 | goto out_free_client; | ||
296 | } | ||
297 | |||
298 | memset(client, 0, sizeof(struct i2c_client)); | ||
299 | memset(decoder, 0, sizeof(struct saa7191)); | ||
300 | |||
301 | client->addr = addr; | ||
302 | client->adapter = adap; | ||
303 | client->driver = &i2c_driver_saa7191; | ||
304 | client->flags = 0; | ||
305 | strcpy(client->name, "saa7191 client"); | ||
306 | i2c_set_clientdata(client, decoder); | ||
307 | |||
308 | decoder->client = client; | ||
309 | |||
310 | err = i2c_attach_client(client); | ||
311 | if (err) | ||
312 | goto out_free_decoder; | ||
313 | |||
314 | decoder->input = SAA7191_INPUT_COMPOSITE; | ||
315 | decoder->norm = SAA7191_NORM_AUTO; | ||
316 | |||
317 | err = saa7191_write_block(client, sizeof(initseq), | ||
318 | (unsigned char *)initseq); | ||
319 | if (err) { | ||
320 | printk(KERN_ERR "SAA7191 initialization failed\n"); | ||
321 | goto out_detach_client; | ||
322 | } | ||
323 | |||
324 | printk(KERN_INFO "SAA7191 initialized\n"); | ||
325 | |||
326 | return 0; | ||
327 | |||
328 | out_detach_client: | ||
329 | i2c_detach_client(client); | ||
330 | out_free_decoder: | ||
331 | kfree(decoder); | ||
332 | out_free_client: | ||
333 | kfree(client); | ||
334 | return err; | ||
335 | } | ||
336 | |||
337 | static int saa7191_probe(struct i2c_adapter *adap) | ||
338 | { | ||
339 | /* Always connected to VINO */ | ||
340 | if (adap->id == VINO_ADAPTER) | ||
341 | return saa7191_attach(adap, SAA7191_ADDR, 0); | ||
342 | /* Feel free to add probe here :-) */ | ||
343 | return -ENODEV; | ||
344 | } | ||
345 | |||
346 | static int saa7191_detach(struct i2c_client *client) | ||
347 | { | ||
348 | struct saa7191 *decoder = i2c_get_clientdata(client); | ||
349 | |||
350 | i2c_detach_client(client); | ||
351 | kfree(decoder); | ||
352 | kfree(client); | ||
353 | return 0; | ||
354 | } | ||
355 | |||
356 | static int saa7191_command(struct i2c_client *client, unsigned int cmd, | ||
357 | void *arg) | ||
358 | { | ||
359 | struct saa7191 *decoder = i2c_get_clientdata(client); | ||
360 | |||
361 | switch (cmd) { | ||
362 | case DECODER_GET_CAPABILITIES: { | ||
363 | struct video_decoder_capability *cap = arg; | ||
364 | |||
365 | cap->flags = VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC | | ||
366 | VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO; | ||
367 | cap->inputs = (client->adapter->id == VINO_ADAPTER) ? 2 : 1; | ||
368 | cap->outputs = 1; | ||
369 | break; | ||
370 | } | ||
371 | case DECODER_GET_STATUS: { | ||
372 | int *iarg = arg; | ||
373 | unsigned char status; | ||
374 | int res = 0; | ||
375 | |||
376 | if (saa7191_read_status(client, &status)) { | ||
377 | return -EIO; | ||
378 | } | ||
379 | if ((status & SAA7191_STATUS_HLCK) == 0) | ||
380 | res |= DECODER_STATUS_GOOD; | ||
381 | if (status & SAA7191_STATUS_CODE) | ||
382 | res |= DECODER_STATUS_COLOR; | ||
383 | switch (decoder->norm) { | ||
384 | case SAA7191_NORM_NTSC: | ||
385 | res |= DECODER_STATUS_NTSC; | ||
386 | break; | ||
387 | case SAA7191_NORM_PAL: | ||
388 | res |= DECODER_STATUS_PAL; | ||
389 | break; | ||
390 | case SAA7191_NORM_SECAM: | ||
391 | res |= DECODER_STATUS_SECAM; | ||
392 | break; | ||
393 | case SAA7191_NORM_AUTO: | ||
394 | default: | ||
395 | if (status & SAA7191_STATUS_FIDT) | ||
396 | res |= DECODER_STATUS_NTSC; | ||
397 | else | ||
398 | res |= DECODER_STATUS_PAL; | ||
399 | break; | ||
400 | } | ||
401 | *iarg = res; | ||
402 | break; | ||
403 | } | ||
404 | case DECODER_SET_NORM: { | ||
405 | int *iarg = arg; | ||
406 | |||
407 | switch (*iarg) { | ||
408 | case VIDEO_MODE_AUTO: | ||
409 | return saa7191_set_norm(client, SAA7191_NORM_AUTO); | ||
410 | case VIDEO_MODE_PAL: | ||
411 | return saa7191_set_norm(client, SAA7191_NORM_PAL); | ||
412 | case VIDEO_MODE_NTSC: | ||
413 | return saa7191_set_norm(client, SAA7191_NORM_NTSC); | ||
414 | case VIDEO_MODE_SECAM: | ||
415 | return saa7191_set_norm(client, SAA7191_NORM_SECAM); | ||
416 | default: | ||
417 | return -EINVAL; | ||
418 | } | ||
419 | break; | ||
420 | } | ||
421 | case DECODER_SET_INPUT: { | ||
422 | int *iarg = arg; | ||
423 | |||
424 | switch (client->adapter->id) { | ||
425 | case VINO_ADAPTER: | ||
426 | return saa7191_set_input(client, *iarg); | ||
427 | default: | ||
428 | if (*iarg != 0) | ||
429 | return -EINVAL; | ||
430 | } | ||
431 | break; | ||
432 | } | ||
433 | case DECODER_SET_OUTPUT: { | ||
434 | int *iarg = arg; | ||
435 | |||
436 | /* not much choice of outputs */ | ||
437 | if (*iarg != 0) | ||
438 | return -EINVAL; | ||
439 | break; | ||
440 | } | ||
441 | case DECODER_ENABLE_OUTPUT: { | ||
442 | /* Always enabled */ | ||
443 | break; | ||
444 | } | ||
445 | case DECODER_SET_PICTURE: { | ||
446 | struct video_picture *pic = arg; | ||
447 | unsigned val; | ||
448 | int err; | ||
449 | |||
450 | val = (pic->hue >> 8) - 0x80; | ||
451 | err = saa7191_write_reg(client, SAA7191_REG_HUEC, val); | ||
452 | if (err) | ||
453 | return -EIO; | ||
454 | break; | ||
455 | } | ||
456 | case DECODER_SAA7191_GET_STATUS: { | ||
457 | struct saa7191_status *status = arg; | ||
458 | unsigned char status_reg; | ||
459 | |||
460 | if (saa7191_read_status(client, &status_reg)) | ||
461 | return -EIO; | ||
462 | status->signal = ((status_reg & SAA7191_STATUS_HLCK) == 0) | ||
463 | ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED; | ||
464 | status->ntsc = (status_reg & SAA7191_STATUS_FIDT) | ||
465 | ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED; | ||
466 | status->color = (status_reg & SAA7191_STATUS_CODE) | ||
467 | ? SAA7191_VALUE_ENABLED : SAA7191_VALUE_DISABLED; | ||
468 | |||
469 | status->input = decoder->input; | ||
470 | status->norm = decoder->norm; | ||
471 | } | ||
472 | case DECODER_SAA7191_SET_NORM: { | ||
473 | int *norm = arg; | ||
474 | return saa7191_set_norm(client, *norm); | ||
475 | } | ||
476 | case DECODER_SAA7191_GET_CONTROLS: { | ||
477 | struct saa7191_control *ctrl = arg; | ||
478 | return saa7191_get_controls(client, ctrl); | ||
479 | } | ||
480 | case DECODER_SAA7191_SET_CONTROLS: { | ||
481 | struct saa7191_control *ctrl = arg; | ||
482 | return saa7191_set_controls(client, ctrl); | ||
483 | } | ||
484 | default: | ||
485 | return -EINVAL; | ||
486 | } | ||
487 | |||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | static struct i2c_driver i2c_driver_saa7191 = { | ||
492 | .owner = THIS_MODULE, | ||
493 | .name = "saa7191", | ||
494 | .id = I2C_DRIVERID_SAA7191, | ||
495 | .flags = I2C_DF_NOTIFY, | ||
496 | .attach_adapter = saa7191_probe, | ||
497 | .detach_client = saa7191_detach, | ||
498 | .command = saa7191_command | ||
499 | }; | ||
500 | |||
501 | static int saa7191_init(void) | ||
502 | { | ||
503 | return i2c_add_driver(&i2c_driver_saa7191); | ||
504 | } | ||
505 | |||
506 | static void saa7191_exit(void) | ||
507 | { | ||
508 | i2c_del_driver(&i2c_driver_saa7191); | ||
509 | } | ||
510 | |||
511 | module_init(saa7191_init); | ||
512 | module_exit(saa7191_exit); | ||
diff --git a/drivers/media/video/saa7191.h b/drivers/media/video/saa7191.h new file mode 100644 index 000000000000..272045031435 --- /dev/null +++ b/drivers/media/video/saa7191.h | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * saa7191.h - Philips SAA7191 video decoder driver | ||
3 | * | ||
4 | * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org> | ||
5 | * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi> | ||
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 version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef _SAA7191_H_ | ||
13 | #define _SAA7191_H_ | ||
14 | |||
15 | /* Philips SAA7191 DMSD I2C bus address */ | ||
16 | #define SAA7191_ADDR 0x8a | ||
17 | |||
18 | /* Register subaddresses. */ | ||
19 | #define SAA7191_REG_IDEL 0x00 | ||
20 | #define SAA7191_REG_HSYB 0x01 | ||
21 | #define SAA7191_REG_HSYS 0x02 | ||
22 | #define SAA7191_REG_HCLB 0x03 | ||
23 | #define SAA7191_REG_HCLS 0x04 | ||
24 | #define SAA7191_REG_HPHI 0x05 | ||
25 | #define SAA7191_REG_LUMA 0x06 | ||
26 | #define SAA7191_REG_HUEC 0x07 | ||
27 | #define SAA7191_REG_CKTQ 0x08 | ||
28 | #define SAA7191_REG_CKTS 0x09 | ||
29 | #define SAA7191_REG_PLSE 0x0a | ||
30 | #define SAA7191_REG_SESE 0x0b | ||
31 | #define SAA7191_REG_GAIN 0x0c | ||
32 | #define SAA7191_REG_STDC 0x0d | ||
33 | #define SAA7191_REG_IOCK 0x0e | ||
34 | #define SAA7191_REG_CTL3 0x0f | ||
35 | #define SAA7191_REG_CTL4 0x10 | ||
36 | #define SAA7191_REG_CHCV 0x11 | ||
37 | #define SAA7191_REG_HS6B 0x14 | ||
38 | #define SAA7191_REG_HS6S 0x15 | ||
39 | #define SAA7191_REG_HC6B 0x16 | ||
40 | #define SAA7191_REG_HC6S 0x17 | ||
41 | #define SAA7191_REG_HP6I 0x18 | ||
42 | #define SAA7191_REG_STATUS 0xff /* not really a subaddress */ | ||
43 | |||
44 | /* Status Register definitions */ | ||
45 | #define SAA7191_STATUS_CODE 0x01 /* color detected flag */ | ||
46 | #define SAA7191_STATUS_FIDT 0x20 /* format type NTSC/PAL */ | ||
47 | #define SAA7191_STATUS_HLCK 0x40 /* PLL unlocked/locked */ | ||
48 | #define SAA7191_STATUS_STTC 0x80 /* tv/vtr time constant */ | ||
49 | |||
50 | /* Luminance Control Register definitions */ | ||
51 | #define SAA7191_LUMA_BYPS 0x80 | ||
52 | |||
53 | /* Chroma Gain Control Settings Register definitions */ | ||
54 | /* 0=automatic colour-killer enabled, 1=forced colour on */ | ||
55 | #define SAA7191_GAIN_COLO 0x80 | ||
56 | |||
57 | /* Standard/Mode Control Register definitions */ | ||
58 | /* tv/vtr mode bit: 0=TV mode (slow time constant), | ||
59 | * 1=VTR mode (fast time constant) */ | ||
60 | #define SAA7191_STDC_VTRC 0x80 | ||
61 | /* SECAM mode bit: 0=other standards, 1=SECAM */ | ||
62 | #define SAA7191_STDC_SECS 0x01 | ||
63 | /* the bit fields above must be or'd with this value */ | ||
64 | #define SAA7191_STDC_VALUE 0x0c | ||
65 | |||
66 | /* I/O and Clock Control Register definitions */ | ||
67 | /* horizontal clock PLL: 0=PLL closed, | ||
68 | * 1=PLL circuit open and horizontal freq fixed */ | ||
69 | #define SAA7191_IOCK_HPLL 0x80 | ||
70 | /* S-VHS bit (chrominance from CVBS or from chrominance input): | ||
71 | * 0=controlled by BYPS-bit, 1=from chrominance input */ | ||
72 | #define SAA7191_IOCK_CHRS 0x04 | ||
73 | /* general purpose switch 2 | ||
74 | * VINO-specific: 0=used with CVBS, 1=used with S-Video */ | ||
75 | #define SAA7191_IOCK_GPSW2 0x02 | ||
76 | /* general purpose switch 1 */ | ||
77 | /* VINO-specific: 0=always, 1=not used!*/ | ||
78 | #define SAA7191_IOCK_GPSW1 0x01 | ||
79 | |||
80 | /* Miscellaneous Control #1 Register definitions */ | ||
81 | /* automatic field detection (50/60Hz standard) */ | ||
82 | #define SAA7191_CTL3_AUFD 0x80 | ||
83 | /* field select: (if AUFD=0) | ||
84 | * 0=50Hz (625 lines), 1=60Hz (525 lines) */ | ||
85 | #define SAA7191_CTL3_FSEL 0x40 | ||
86 | /* the bit fields above must be or'd with this value */ | ||
87 | #define SAA7191_CTL3_VALUE 0x19 | ||
88 | |||
89 | /* Chrominance Gain Control Register definitions | ||
90 | * (nominal value for UV CCIR level) */ | ||
91 | #define SAA7191_CHCV_NTSC 0x2c | ||
92 | #define SAA7191_CHCV_PAL 0x59 | ||
93 | |||
94 | /* Driver interface definitions */ | ||
95 | #define SAA7191_INPUT_COMPOSITE 0 | ||
96 | #define SAA7191_INPUT_SVIDEO 1 | ||
97 | |||
98 | #define SAA7191_NORM_AUTO 0 | ||
99 | #define SAA7191_NORM_PAL 1 | ||
100 | #define SAA7191_NORM_NTSC 2 | ||
101 | #define SAA7191_NORM_SECAM 3 | ||
102 | |||
103 | #define SAA7191_VALUE_ENABLED 1 | ||
104 | #define SAA7191_VALUE_DISABLED 0 | ||
105 | #define SAA7191_VALUE_UNCHANGED -1 | ||
106 | |||
107 | struct saa7191_status { | ||
108 | /* 0=no signal, 1=signal active*/ | ||
109 | int signal; | ||
110 | /* 0=50hz (pal) signal, 1=60hz (ntsc) signal */ | ||
111 | int ntsc; | ||
112 | /* 0=no color detected, 1=color detected */ | ||
113 | int color; | ||
114 | |||
115 | /* current SAA7191_INPUT_ */ | ||
116 | int input; | ||
117 | /* current SAA7191_NORM_ */ | ||
118 | int norm; | ||
119 | }; | ||
120 | |||
121 | #define SAA7191_HUE_MIN 0x00 | ||
122 | #define SAA7191_HUE_MAX 0xff | ||
123 | #define SAA7191_HUE_DEFAULT 0x80 | ||
124 | |||
125 | #define SAA7191_VTRC_MIN 0x00 | ||
126 | #define SAA7191_VTRC_MAX 0x01 | ||
127 | #define SAA7191_VTRC_DEFAULT 0x00 | ||
128 | |||
129 | struct saa7191_control { | ||
130 | int hue; | ||
131 | int vtrc; | ||
132 | }; | ||
133 | |||
134 | #define DECODER_SAA7191_GET_STATUS _IOR('d', 195, struct saa7191_status) | ||
135 | #define DECODER_SAA7191_SET_NORM _IOW('d', 196, int) | ||
136 | #define DECODER_SAA7191_GET_CONTROLS _IOR('d', 197, struct saa7191_control) | ||
137 | #define DECODER_SAA7191_SET_CONTROLS _IOW('d', 198, struct saa7191_control) | ||
138 | |||
139 | #endif | ||
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 76e8681d65c6..d8a0f763ca10 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c | |||
@@ -1,80 +1,606 @@ | |||
1 | /* | 1 | /* |
2 | * (incomplete) Driver for the VINO (Video In No Out) system found in SGI Indys. | 2 | * Driver for the VINO (Video In No Out) system found in SGI Indys. |
3 | * | 3 | * |
4 | * This file is subject to the terms and conditions of the GNU General Public | 4 | * 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. | 5 | * License version 2 as published by the Free Software Foundation. |
6 | * | 6 | * |
7 | * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi> | ||
8 | * | ||
9 | * Based on the previous version of the driver for 2.4 kernels by: | ||
7 | * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org> | 10 | * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org> |
8 | */ | 11 | */ |
9 | 12 | ||
10 | #include <linux/module.h> | 13 | /* |
14 | * TODO: | ||
15 | * - remove "hacks" from memory allocation code and implement nopage() | ||
16 | * - check decimation, calculating and reporting image size when | ||
17 | * using decimation | ||
18 | * - check vino_acquire_input(), vino_set_input() and channel | ||
19 | * ownership handling | ||
20 | * - report VINO error-interrupts via ioctls ? | ||
21 | * - implement picture controls (all implemented?) | ||
22 | * - use macros for boolean values (?) | ||
23 | * - implement user mode buffers and overlay (?) | ||
24 | */ | ||
25 | |||
11 | #include <linux/init.h> | 26 | #include <linux/init.h> |
12 | #include <linux/types.h> | 27 | #include <linux/module.h> |
13 | #include <linux/mm.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/wrapper.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
19 | #include <linux/videodev.h> | 29 | #include <linux/errno.h> |
30 | #include <linux/fs.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/mm.h> | ||
33 | #include <linux/interrupt.h> | ||
34 | #include <linux/dma-mapping.h> | ||
35 | #include <linux/time.h> | ||
36 | #include <linux/moduleparam.h> | ||
37 | |||
38 | #ifdef CONFIG_KMOD | ||
39 | #include <linux/kmod.h> | ||
40 | #endif | ||
41 | |||
20 | #include <linux/i2c.h> | 42 | #include <linux/i2c.h> |
21 | #include <linux/i2c-algo-sgi.h> | 43 | #include <linux/i2c-algo-sgi.h> |
22 | 44 | ||
23 | #include <asm/addrspace.h> | 45 | #include <linux/videodev.h> |
24 | #include <asm/system.h> | 46 | #include <linux/videodev2.h> |
25 | #include <asm/bootinfo.h> | 47 | #include <linux/video_decoder.h> |
26 | #include <asm/pgtable.h> | 48 | |
27 | #include <asm/paccess.h> | 49 | #include <asm/paccess.h> |
28 | #include <asm/io.h> | 50 | #include <asm/io.h> |
29 | #include <asm/sgi/ip22.h> | 51 | #include <asm/sgi/ip22.h> |
30 | #include <asm/sgi/hpc3.h> | ||
31 | #include <asm/sgi/mc.h> | 52 | #include <asm/sgi/mc.h> |
32 | 53 | ||
33 | #include "vino.h" | 54 | #include "vino.h" |
55 | #include "saa7191.h" | ||
56 | #include "indycam.h" | ||
57 | |||
58 | /* Uncomment the following line to get lots and lots of (mostly useless) | ||
59 | * debug info. | ||
60 | * Note that the debug output also slows down the driver significantly */ | ||
61 | // #define VINO_DEBUG | ||
62 | |||
63 | #define VINO_MODULE_VERSION "0.0.3" | ||
64 | #define VINO_VERSION_CODE KERNEL_VERSION(0, 0, 3) | ||
65 | |||
66 | MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver"); | ||
67 | MODULE_VERSION(VINO_MODULE_VERSION); | ||
68 | MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>"); | ||
69 | MODULE_LICENSE("GPL"); | ||
34 | 70 | ||
35 | /* debugging? */ | 71 | #define mem_map_reserve(p) set_bit(PG_reserved, &((p)->flags)) |
36 | #if 1 | 72 | #define mem_map_unreserve(p) clear_bit(PG_reserved, &((p)->flags)) |
37 | #define DEBUG(x...) printk(x); | 73 | |
74 | #ifdef VINO_DEBUG | ||
75 | #define dprintk(x...) printk("VINO: " x); | ||
38 | #else | 76 | #else |
39 | #define DEBUG(x...) | 77 | #define dprintk(x...) |
40 | #endif | 78 | #endif |
41 | 79 | ||
80 | #define VINO_NO_CHANNEL 0 | ||
81 | #define VINO_CHANNEL_A 1 | ||
82 | #define VINO_CHANNEL_B 2 | ||
83 | |||
84 | #define VINO_PAL_WIDTH 768 | ||
85 | #define VINO_PAL_HEIGHT 576 | ||
86 | #define VINO_NTSC_WIDTH 640 | ||
87 | #define VINO_NTSC_HEIGHT 480 | ||
88 | |||
89 | #define VINO_MIN_WIDTH 32 | ||
90 | #define VINO_MIN_HEIGHT 32 | ||
91 | |||
92 | #define VINO_CLIPPING_START_ODD_D1 1 | ||
93 | #define VINO_CLIPPING_START_ODD_PAL 1 | ||
94 | #define VINO_CLIPPING_START_ODD_NTSC 1 | ||
95 | |||
96 | #define VINO_CLIPPING_START_EVEN_D1 2 | ||
97 | #define VINO_CLIPPING_START_EVEN_PAL 2 | ||
98 | #define VINO_CLIPPING_START_EVEN_NTSC 2 | ||
99 | |||
100 | #define VINO_INPUT_CHANNEL_COUNT 3 | ||
101 | |||
102 | #define VINO_INPUT_NONE -1 | ||
103 | #define VINO_INPUT_COMPOSITE 0 | ||
104 | #define VINO_INPUT_SVIDEO 1 | ||
105 | #define VINO_INPUT_D1 2 | ||
106 | |||
107 | #define VINO_PAGE_RATIO (PAGE_SIZE / VINO_PAGE_SIZE) | ||
108 | |||
109 | #define VINO_FIFO_THRESHOLD_DEFAULT 512 | ||
110 | |||
111 | /*#define VINO_FRAMEBUFFER_SIZE (VINO_PAL_WIDTH * VINO_PAL_HEIGHT * 4 \ | ||
112 | + 2 * PAGE_SIZE)*/ | ||
113 | #define VINO_FRAMEBUFFER_SIZE ((VINO_PAL_WIDTH \ | ||
114 | * VINO_PAL_HEIGHT * 4 \ | ||
115 | + 3 * PAGE_SIZE) & ~(PAGE_SIZE - 1)) | ||
116 | |||
117 | #define VINO_FRAMEBUFFER_MAX_COUNT 8 | ||
118 | |||
119 | #define VINO_FRAMEBUFFER_UNUSED 0 | ||
120 | #define VINO_FRAMEBUFFER_IN_USE 1 | ||
121 | #define VINO_FRAMEBUFFER_READY 2 | ||
122 | |||
123 | #define VINO_QUEUE_ERROR -1 | ||
124 | #define VINO_QUEUE_MAGIC 0x20050125 | ||
125 | |||
126 | #define VINO_MEMORY_NONE 0 | ||
127 | #define VINO_MEMORY_MMAP 1 | ||
128 | #define VINO_MEMORY_USERPTR 2 | ||
129 | |||
130 | #define VINO_DUMMY_DESC_COUNT 4 | ||
131 | #define VINO_DESC_FETCH_DELAY 5 /* microseconds */ | ||
132 | |||
133 | /* the number is the index for vino_data_formats */ | ||
134 | #define VINO_DATA_FMT_NONE -1 | ||
135 | #define VINO_DATA_FMT_GREY 0 | ||
136 | #define VINO_DATA_FMT_RGB332 1 | ||
137 | #define VINO_DATA_FMT_RGB32 2 | ||
138 | #define VINO_DATA_FMT_YUV 3 | ||
139 | //#define VINO_DATA_FMT_RGB24 4 | ||
140 | |||
141 | #define VINO_DATA_FMT_COUNT 4 | ||
142 | |||
143 | #define VINO_DATA_NORM_NONE -1 | ||
144 | #define VINO_DATA_NORM_NTSC 0 | ||
145 | #define VINO_DATA_NORM_PAL 1 | ||
146 | #define VINO_DATA_NORM_SECAM 2 | ||
147 | #define VINO_DATA_NORM_D1 3 | ||
148 | /* The following is a special entry that can be used to | ||
149 | * autodetect the norm. */ | ||
150 | #define VINO_DATA_NORM_AUTO 0xff | ||
151 | |||
152 | #define VINO_DATA_NORM_COUNT 4 | ||
42 | 153 | ||
43 | /* VINO ASIC registers */ | 154 | /* Internal data structure definitions */ |
44 | struct sgi_vino *vino; | ||
45 | 155 | ||
46 | static const char *vinostr = "VINO IndyCam/TV"; | 156 | struct vino_input { |
47 | static int threshold_a = 512; | 157 | char *name; |
48 | static int threshold_b = 512; | 158 | v4l2_std_id std; |
159 | }; | ||
160 | |||
161 | struct vino_clipping { | ||
162 | unsigned int left, right, top, bottom; | ||
163 | }; | ||
164 | |||
165 | struct vino_data_format { | ||
166 | /* the description */ | ||
167 | char *description; | ||
168 | /* bytes per pixel */ | ||
169 | unsigned int bpp; | ||
170 | /* V4L2 fourcc code */ | ||
171 | __u32 pixelformat; | ||
172 | /* V4L2 colorspace (duh!) */ | ||
173 | enum v4l2_colorspace colorspace; | ||
174 | }; | ||
175 | |||
176 | struct vino_data_norm { | ||
177 | char *description; | ||
178 | unsigned int width, height; | ||
179 | struct vino_clipping odd; | ||
180 | struct vino_clipping even; | ||
181 | |||
182 | v4l2_std_id std; | ||
183 | unsigned int fps_min, fps_max; | ||
184 | __u32 framelines; | ||
185 | }; | ||
186 | |||
187 | struct vino_descriptor_table { | ||
188 | /* the number of PAGE_SIZE sized pages in the buffer */ | ||
189 | unsigned int page_count; | ||
190 | /* virtual (kmalloc'd) pointers to the actual data | ||
191 | * (in PAGE_SIZE chunks, used with mmap streaming) */ | ||
192 | unsigned long *virtual; | ||
193 | |||
194 | /* cpu address for the VINO descriptor table | ||
195 | * (contains DMA addresses, VINO_PAGE_SIZE chunks) */ | ||
196 | unsigned long *dma_cpu; | ||
197 | /* dma address for the VINO descriptor table | ||
198 | * (contains DMA addresses, VINO_PAGE_SIZE chunks) */ | ||
199 | dma_addr_t dma; | ||
200 | }; | ||
201 | |||
202 | struct vino_framebuffer { | ||
203 | /* identifier nubmer */ | ||
204 | unsigned int id; | ||
205 | /* the length of the whole buffer */ | ||
206 | unsigned int size; | ||
207 | /* the length of actual data in buffer */ | ||
208 | unsigned int data_size; | ||
209 | /* the data format */ | ||
210 | unsigned int data_format; | ||
211 | /* the state of buffer data */ | ||
212 | unsigned int state; | ||
213 | /* is the buffer mapped in user space? */ | ||
214 | unsigned int map_count; | ||
215 | /* memory offset for mmap() */ | ||
216 | unsigned int offset; | ||
217 | /* frame counter */ | ||
218 | unsigned int frame_counter; | ||
219 | /* timestamp (written when image capture finishes) */ | ||
220 | struct timeval timestamp; | ||
221 | |||
222 | struct vino_descriptor_table desc_table; | ||
223 | |||
224 | spinlock_t state_lock; | ||
225 | }; | ||
49 | 226 | ||
50 | struct vino_device { | 227 | struct vino_framebuffer_fifo { |
51 | struct video_device vdev; | 228 | unsigned int length; |
52 | #define VINO_CHAN_A 1 | 229 | |
53 | #define VINO_CHAN_B 2 | 230 | unsigned int used; |
54 | int chan; | 231 | unsigned int head; |
232 | unsigned int tail; | ||
233 | |||
234 | unsigned int data[VINO_FRAMEBUFFER_MAX_COUNT]; | ||
235 | }; | ||
236 | |||
237 | struct vino_framebuffer_queue { | ||
238 | unsigned int magic; | ||
239 | |||
240 | /* VINO_MEMORY_NONE, VINO_MEMORY_MMAP or VINO_MEMORY_USERPTR */ | ||
241 | unsigned int type; | ||
242 | unsigned int length; | ||
243 | |||
244 | /* data field of in and out contain index numbers for buffer */ | ||
245 | struct vino_framebuffer_fifo in; | ||
246 | struct vino_framebuffer_fifo out; | ||
247 | |||
248 | struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_MAX_COUNT]; | ||
249 | |||
250 | spinlock_t queue_lock; | ||
251 | struct semaphore queue_sem; | ||
252 | wait_queue_head_t frame_wait_queue; | ||
253 | }; | ||
254 | |||
255 | struct vino_channel_settings { | ||
256 | unsigned int channel; | ||
257 | |||
258 | int input; | ||
259 | unsigned int data_format; | ||
260 | unsigned int data_norm; | ||
261 | struct vino_clipping clipping; | ||
262 | unsigned int decimation; | ||
263 | unsigned int line_size; | ||
264 | unsigned int alpha; | ||
265 | unsigned int fps; | ||
266 | unsigned int framert_reg; | ||
267 | |||
268 | unsigned int fifo_threshold; | ||
269 | |||
270 | struct vino_framebuffer_queue fb_queue; | ||
271 | |||
272 | /* number of the current field */ | ||
273 | unsigned int field; | ||
274 | |||
275 | /* read in progress */ | ||
276 | int reading; | ||
277 | /* streaming is active */ | ||
278 | int streaming; | ||
279 | /* the driver is currently processing the queue */ | ||
280 | int capturing; | ||
281 | |||
282 | struct semaphore sem; | ||
283 | spinlock_t capture_lock; | ||
284 | |||
285 | unsigned int users; | ||
286 | |||
287 | /* V4L support */ | ||
288 | struct video_device *v4l_device; | ||
55 | }; | 289 | }; |
56 | 290 | ||
57 | struct vino_client { | 291 | struct vino_client { |
292 | /* the channel which owns this client: | ||
293 | * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */ | ||
294 | unsigned int owner; | ||
58 | struct i2c_client *driver; | 295 | struct i2c_client *driver; |
59 | int owner; | ||
60 | }; | 296 | }; |
61 | 297 | ||
62 | struct vino_video { | 298 | struct vino_settings { |
63 | struct vino_device chA; | 299 | struct vino_channel_settings a; |
64 | struct vino_device chB; | 300 | struct vino_channel_settings b; |
65 | 301 | ||
66 | struct vino_client decoder; | 302 | struct vino_client decoder; |
67 | struct vino_client camera; | 303 | struct vino_client camera; |
68 | 304 | ||
69 | struct semaphore input_lock; | 305 | /* a lock for vino register access */ |
306 | spinlock_t vino_lock; | ||
307 | /* a lock for channel input changes */ | ||
308 | spinlock_t input_lock; | ||
70 | 309 | ||
71 | /* Loaded into VINO descriptors to clear End Of Descriptors table | ||
72 | * interupt condition */ | ||
73 | unsigned long dummy_page; | 310 | unsigned long dummy_page; |
74 | unsigned int dummy_buf[4] __attribute__((aligned(8))); | 311 | struct vino_descriptor_table dummy_desc_table; |
75 | }; | 312 | }; |
76 | 313 | ||
77 | static struct vino_video *Vino; | 314 | /* Module parameters */ |
315 | |||
316 | /* | ||
317 | * Using vino_pixel_conversion the ARGB32-format pixels supplied | ||
318 | * by the VINO chip can be converted to more common formats | ||
319 | * like RGBA32 (or probably RGB24 in the future). This way we | ||
320 | * can give out data that can be specified correctly with | ||
321 | * the V4L2-definitions. | ||
322 | * | ||
323 | * The pixel format is specified as RGBA32 when no conversion | ||
324 | * is used. | ||
325 | * | ||
326 | * Note that this only affects the 32-bit bit depth. | ||
327 | * | ||
328 | * Use non-zero value to enable conversion. | ||
329 | */ | ||
330 | static int vino_pixel_conversion = 0; | ||
331 | module_param_named(pixelconv, vino_pixel_conversion, int, 0); | ||
332 | MODULE_PARM_DESC(pixelconv, | ||
333 | "enable pixel conversion (non-zero value enables)"); | ||
334 | |||
335 | /* Internal data structures */ | ||
336 | |||
337 | static struct sgi_vino *vino; | ||
338 | |||
339 | static struct vino_settings *vino_drvdata; | ||
340 | |||
341 | static const char *vino_driver_name = "vino"; | ||
342 | static const char *vino_driver_description = "SGI VINO"; | ||
343 | static const char *vino_bus_name = "GIO64 bus"; | ||
344 | static const char *vino_v4l_device_name_a = "SGI VINO Channel A"; | ||
345 | static const char *vino_v4l_device_name_b = "SGI VINO Channel B"; | ||
346 | |||
347 | static const struct vino_input vino_inputs[] = { | ||
348 | { | ||
349 | .name = "Composite", | ||
350 | .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, | ||
351 | },{ | ||
352 | .name = "S-Video", | ||
353 | .std = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM, | ||
354 | },{ | ||
355 | .name = "D1 (IndyCam)", | ||
356 | .std = V4L2_STD_NTSC, | ||
357 | } | ||
358 | }; | ||
359 | |||
360 | static const struct vino_data_format vino_data_formats[] = { | ||
361 | { | ||
362 | .description = "8-bit greyscale", | ||
363 | .bpp = 1, | ||
364 | .pixelformat = V4L2_PIX_FMT_GREY, | ||
365 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | ||
366 | },{ | ||
367 | .description = "8-bit dithered RGB 3-3-2", | ||
368 | .bpp = 1, | ||
369 | .pixelformat = V4L2_PIX_FMT_RGB332, | ||
370 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
371 | },{ | ||
372 | .description = "32-bit RGB", | ||
373 | .bpp = 4, | ||
374 | .pixelformat = V4L2_PIX_FMT_RGB32, | ||
375 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
376 | },{ | ||
377 | .description = "YUV 4:2:2", | ||
378 | .bpp = 4, | ||
379 | .pixelformat = V4L2_PIX_FMT_YUYV, // XXX: swapped? | ||
380 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | ||
381 | }/*,{ | ||
382 | .description = "24-bit RGB", | ||
383 | .bpp = 3, | ||
384 | .pixelformat = V4L2_PIX_FMT_RGB24, | ||
385 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
386 | }*/ | ||
387 | }; | ||
388 | |||
389 | static const struct vino_data_norm vino_data_norms[] = { | ||
390 | { | ||
391 | .description = "NTSC", | ||
392 | .std = V4L2_STD_NTSC, | ||
393 | .fps_min = 6, | ||
394 | .fps_max = 30, | ||
395 | .framelines = 525, | ||
396 | .width = VINO_NTSC_WIDTH, | ||
397 | .height = VINO_NTSC_HEIGHT, | ||
398 | .odd = { | ||
399 | .top = VINO_CLIPPING_START_ODD_NTSC, | ||
400 | .left = 0, | ||
401 | .bottom = VINO_CLIPPING_START_ODD_NTSC | ||
402 | + VINO_NTSC_HEIGHT / 2 - 1, | ||
403 | .right = VINO_NTSC_WIDTH, | ||
404 | }, | ||
405 | .even = { | ||
406 | .top = VINO_CLIPPING_START_EVEN_NTSC, | ||
407 | .left = 0, | ||
408 | .bottom = VINO_CLIPPING_START_EVEN_NTSC | ||
409 | + VINO_NTSC_HEIGHT / 2 - 1, | ||
410 | .right = VINO_NTSC_WIDTH, | ||
411 | }, | ||
412 | },{ | ||
413 | .description = "PAL", | ||
414 | .std = V4L2_STD_PAL, | ||
415 | .fps_min = 5, | ||
416 | .fps_max = 25, | ||
417 | .framelines = 625, | ||
418 | .width = VINO_PAL_WIDTH, | ||
419 | .height = VINO_PAL_HEIGHT, | ||
420 | .odd = { | ||
421 | .top = VINO_CLIPPING_START_ODD_PAL, | ||
422 | .left = 0, | ||
423 | .bottom = VINO_CLIPPING_START_ODD_PAL | ||
424 | + VINO_PAL_HEIGHT / 2 - 1, | ||
425 | .right = VINO_PAL_WIDTH, | ||
426 | }, | ||
427 | .even = { | ||
428 | .top = VINO_CLIPPING_START_EVEN_PAL, | ||
429 | .left = 0, | ||
430 | .bottom = VINO_CLIPPING_START_EVEN_PAL | ||
431 | + VINO_PAL_HEIGHT / 2 - 1, | ||
432 | .right = VINO_PAL_WIDTH, | ||
433 | }, | ||
434 | },{ | ||
435 | .description = "SECAM", | ||
436 | .std = V4L2_STD_SECAM, | ||
437 | .fps_min = 5, | ||
438 | .fps_max = 25, | ||
439 | .framelines = 625, | ||
440 | .width = VINO_PAL_WIDTH, | ||
441 | .height = VINO_PAL_HEIGHT, | ||
442 | .odd = { | ||
443 | .top = VINO_CLIPPING_START_ODD_PAL, | ||
444 | .left = 0, | ||
445 | .bottom = VINO_CLIPPING_START_ODD_PAL | ||
446 | + VINO_PAL_HEIGHT / 2 - 1, | ||
447 | .right = VINO_PAL_WIDTH, | ||
448 | }, | ||
449 | .even = { | ||
450 | .top = VINO_CLIPPING_START_EVEN_PAL, | ||
451 | .left = 0, | ||
452 | .bottom = VINO_CLIPPING_START_EVEN_PAL | ||
453 | + VINO_PAL_HEIGHT / 2 - 1, | ||
454 | .right = VINO_PAL_WIDTH, | ||
455 | }, | ||
456 | },{ | ||
457 | .description = "NTSC (D1 input)", | ||
458 | .std = V4L2_STD_NTSC, | ||
459 | .fps_min = 6, | ||
460 | .fps_max = 30, | ||
461 | .framelines = 525, | ||
462 | .width = VINO_NTSC_WIDTH, | ||
463 | .height = VINO_NTSC_HEIGHT, | ||
464 | .odd = { | ||
465 | .top = VINO_CLIPPING_START_ODD_D1, | ||
466 | .left = 0, | ||
467 | .bottom = VINO_CLIPPING_START_ODD_D1 | ||
468 | + VINO_NTSC_HEIGHT / 2 - 1, | ||
469 | .right = VINO_NTSC_WIDTH, | ||
470 | }, | ||
471 | .even = { | ||
472 | .top = VINO_CLIPPING_START_EVEN_D1, | ||
473 | .left = 0, | ||
474 | .bottom = VINO_CLIPPING_START_EVEN_D1 | ||
475 | + VINO_NTSC_HEIGHT / 2 - 1, | ||
476 | .right = VINO_NTSC_WIDTH, | ||
477 | }, | ||
478 | } | ||
479 | }; | ||
480 | |||
481 | #define VINO_INDYCAM_V4L2_CONTROL_COUNT 9 | ||
482 | |||
483 | struct v4l2_queryctrl vino_indycam_v4l2_controls[] = { | ||
484 | { | ||
485 | .id = V4L2_CID_AUTOGAIN, | ||
486 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
487 | .name = "Automatic Gain Control", | ||
488 | .minimum = 0, | ||
489 | .maximum = 1, | ||
490 | .step = 1, | ||
491 | .default_value = INDYCAM_AGC_DEFAULT, | ||
492 | .flags = 0, | ||
493 | .reserved = { 0, 0 }, | ||
494 | },{ | ||
495 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | ||
496 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
497 | .name = "Automatic White Balance", | ||
498 | .minimum = 0, | ||
499 | .maximum = 1, | ||
500 | .step = 1, | ||
501 | .default_value = INDYCAM_AWB_DEFAULT, | ||
502 | .flags = 0, | ||
503 | .reserved = { 0, 0 }, | ||
504 | },{ | ||
505 | .id = V4L2_CID_GAIN, | ||
506 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
507 | .name = "Gain", | ||
508 | .minimum = INDYCAM_GAIN_MIN, | ||
509 | .maximum = INDYCAM_GAIN_MAX, | ||
510 | .step = 1, | ||
511 | .default_value = INDYCAM_GAIN_DEFAULT, | ||
512 | .flags = 0, | ||
513 | .reserved = { 0, 0 }, | ||
514 | },{ | ||
515 | .id = V4L2_CID_PRIVATE_BASE, | ||
516 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
517 | .name = "Red Saturation", | ||
518 | .minimum = INDYCAM_RED_SATURATION_MIN, | ||
519 | .maximum = INDYCAM_RED_SATURATION_MAX, | ||
520 | .step = 1, | ||
521 | .default_value = INDYCAM_RED_SATURATION_DEFAULT, | ||
522 | .flags = 0, | ||
523 | .reserved = { 0, 0 }, | ||
524 | },{ | ||
525 | .id = V4L2_CID_PRIVATE_BASE + 1, | ||
526 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
527 | .name = "Blue Saturation", | ||
528 | .minimum = INDYCAM_BLUE_SATURATION_MIN, | ||
529 | .maximum = INDYCAM_BLUE_SATURATION_MAX, | ||
530 | .step = 1, | ||
531 | .default_value = INDYCAM_BLUE_SATURATION_DEFAULT, | ||
532 | .flags = 0, | ||
533 | .reserved = { 0, 0 }, | ||
534 | },{ | ||
535 | .id = V4L2_CID_RED_BALANCE, | ||
536 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
537 | .name = "Red Balance", | ||
538 | .minimum = INDYCAM_RED_BALANCE_MIN, | ||
539 | .maximum = INDYCAM_RED_BALANCE_MAX, | ||
540 | .step = 1, | ||
541 | .default_value = INDYCAM_RED_BALANCE_DEFAULT, | ||
542 | .flags = 0, | ||
543 | .reserved = { 0, 0 }, | ||
544 | },{ | ||
545 | .id = V4L2_CID_BLUE_BALANCE, | ||
546 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
547 | .name = "Blue Balance", | ||
548 | .minimum = INDYCAM_BLUE_BALANCE_MIN, | ||
549 | .maximum = INDYCAM_BLUE_BALANCE_MAX, | ||
550 | .step = 1, | ||
551 | .default_value = INDYCAM_BLUE_BALANCE_DEFAULT, | ||
552 | .flags = 0, | ||
553 | .reserved = { 0, 0 }, | ||
554 | },{ | ||
555 | .id = V4L2_CID_EXPOSURE, | ||
556 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
557 | .name = "Shutter Control", | ||
558 | .minimum = INDYCAM_SHUTTER_MIN, | ||
559 | .maximum = INDYCAM_SHUTTER_MAX, | ||
560 | .step = 1, | ||
561 | .default_value = INDYCAM_SHUTTER_DEFAULT, | ||
562 | .flags = 0, | ||
563 | .reserved = { 0, 0 }, | ||
564 | },{ | ||
565 | .id = V4L2_CID_GAMMA, | ||
566 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
567 | .name = "Gamma", | ||
568 | .minimum = INDYCAM_GAMMA_MIN, | ||
569 | .maximum = INDYCAM_GAMMA_MAX, | ||
570 | .step = 1, | ||
571 | .default_value = INDYCAM_GAMMA_DEFAULT, | ||
572 | .flags = 0, | ||
573 | .reserved = { 0, 0 }, | ||
574 | } | ||
575 | }; | ||
576 | |||
577 | #define VINO_SAA7191_V4L2_CONTROL_COUNT 2 | ||
578 | |||
579 | struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = { | ||
580 | { | ||
581 | .id = V4L2_CID_HUE, | ||
582 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
583 | .name = "Hue", | ||
584 | .minimum = SAA7191_HUE_MIN, | ||
585 | .maximum = SAA7191_HUE_MAX, | ||
586 | .step = 1, | ||
587 | .default_value = SAA7191_HUE_DEFAULT, | ||
588 | .flags = 0, | ||
589 | .reserved = { 0, 0 }, | ||
590 | },{ | ||
591 | .id = V4L2_CID_PRIVATE_BASE, | ||
592 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
593 | .name = "VTR Time Constant", | ||
594 | .minimum = SAA7191_VTRC_MIN, | ||
595 | .maximum = SAA7191_VTRC_MAX, | ||
596 | .step = 1, | ||
597 | .default_value = SAA7191_VTRC_DEFAULT, | ||
598 | .flags = 0, | ||
599 | .reserved = { 0, 0 }, | ||
600 | } | ||
601 | }; | ||
602 | |||
603 | /* VINO I2C bus functions */ | ||
78 | 604 | ||
79 | unsigned i2c_vino_getctrl(void *data) | 605 | unsigned i2c_vino_getctrl(void *data) |
80 | { | 606 | { |
@@ -112,49 +638,49 @@ static struct i2c_algo_sgi_data i2c_sgi_vino_data = | |||
112 | */ | 638 | */ |
113 | static int i2c_vino_client_reg(struct i2c_client *client) | 639 | static int i2c_vino_client_reg(struct i2c_client *client) |
114 | { | 640 | { |
115 | int res = 0; | 641 | int ret = 0; |
116 | 642 | ||
117 | down(&Vino->input_lock); | 643 | spin_lock(&vino_drvdata->input_lock); |
118 | switch (client->driver->id) { | 644 | switch (client->driver->id) { |
119 | case I2C_DRIVERID_SAA7191: | 645 | case I2C_DRIVERID_SAA7191: |
120 | if (Vino->decoder.driver) | 646 | if (vino_drvdata->decoder.driver) |
121 | res = -EBUSY; | 647 | ret = -EBUSY; |
122 | else | 648 | else |
123 | Vino->decoder.driver = client; | 649 | vino_drvdata->decoder.driver = client; |
124 | break; | 650 | break; |
125 | case I2C_DRIVERID_INDYCAM: | 651 | case I2C_DRIVERID_INDYCAM: |
126 | if (Vino->camera.driver) | 652 | if (vino_drvdata->camera.driver) |
127 | res = -EBUSY; | 653 | ret = -EBUSY; |
128 | else | 654 | else |
129 | Vino->camera.driver = client; | 655 | vino_drvdata->camera.driver = client; |
130 | break; | 656 | break; |
131 | default: | 657 | default: |
132 | res = -ENODEV; | 658 | ret = -ENODEV; |
133 | } | 659 | } |
134 | up(&Vino->input_lock); | 660 | spin_unlock(&vino_drvdata->input_lock); |
135 | 661 | ||
136 | return res; | 662 | return ret; |
137 | } | 663 | } |
138 | 664 | ||
139 | static int i2c_vino_client_unreg(struct i2c_client *client) | 665 | static int i2c_vino_client_unreg(struct i2c_client *client) |
140 | { | 666 | { |
141 | int res = 0; | 667 | int ret = 0; |
142 | 668 | ||
143 | down(&Vino->input_lock); | 669 | spin_lock(&vino_drvdata->input_lock); |
144 | if (client == Vino->decoder.driver) { | 670 | if (client == vino_drvdata->decoder.driver) { |
145 | if (Vino->decoder.owner) | 671 | if (vino_drvdata->decoder.owner != VINO_NO_CHANNEL) |
146 | res = -EBUSY; | 672 | ret = -EBUSY; |
147 | else | 673 | else |
148 | Vino->decoder.driver = NULL; | 674 | vino_drvdata->decoder.driver = NULL; |
149 | } else if (client == Vino->camera.driver) { | 675 | } else if (client == vino_drvdata->camera.driver) { |
150 | if (Vino->camera.owner) | 676 | if (vino_drvdata->camera.owner != VINO_NO_CHANNEL) |
151 | res = -EBUSY; | 677 | ret = -EBUSY; |
152 | else | 678 | else |
153 | Vino->camera.driver = NULL; | 679 | vino_drvdata->camera.driver = NULL; |
154 | } | 680 | } |
155 | up(&Vino->input_lock); | 681 | spin_unlock(&vino_drvdata->input_lock); |
156 | 682 | ||
157 | return res; | 683 | return ret; |
158 | } | 684 | } |
159 | 685 | ||
160 | static struct i2c_adapter vino_i2c_adapter = | 686 | static struct i2c_adapter vino_i2c_adapter = |
@@ -176,172 +702,3591 @@ static int vino_i2c_del_bus(void) | |||
176 | return i2c_sgi_del_bus(&vino_i2c_adapter); | 702 | return i2c_sgi_del_bus(&vino_i2c_adapter); |
177 | } | 703 | } |
178 | 704 | ||
705 | static int i2c_camera_command(unsigned int cmd, void *arg) | ||
706 | { | ||
707 | return vino_drvdata->camera.driver-> | ||
708 | driver->command(vino_drvdata->camera.driver, | ||
709 | cmd, arg); | ||
710 | } | ||
711 | |||
712 | static int i2c_decoder_command(unsigned int cmd, void *arg) | ||
713 | { | ||
714 | return vino_drvdata->decoder.driver-> | ||
715 | driver->command(vino_drvdata->decoder.driver, | ||
716 | cmd, arg); | ||
717 | } | ||
718 | |||
719 | /* VINO framebuffer/DMA descriptor management */ | ||
720 | |||
721 | static void vino_free_buffer_with_count(struct vino_framebuffer *fb, | ||
722 | unsigned int count) | ||
723 | { | ||
724 | unsigned int i; | ||
725 | |||
726 | dprintk("vino_free_buffer_with_count(): count = %d\n", count); | ||
727 | |||
728 | for (i = 0; i < count; i++) { | ||
729 | mem_map_unreserve(virt_to_page(fb->desc_table.virtual[i])); | ||
730 | dma_unmap_single(NULL, | ||
731 | fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i], | ||
732 | PAGE_SIZE, DMA_FROM_DEVICE); | ||
733 | free_page(fb->desc_table.virtual[i]); | ||
734 | } | ||
735 | |||
736 | dma_free_coherent(NULL, | ||
737 | VINO_PAGE_RATIO * (fb->desc_table.page_count + 4) * | ||
738 | sizeof(dma_addr_t), (void *)fb->desc_table.dma_cpu, | ||
739 | fb->desc_table.dma); | ||
740 | kfree(fb->desc_table.virtual); | ||
741 | |||
742 | memset(fb, 0, sizeof(struct vino_framebuffer)); | ||
743 | } | ||
744 | |||
745 | static void vino_free_buffer(struct vino_framebuffer *fb) | ||
746 | { | ||
747 | vino_free_buffer_with_count(fb, fb->desc_table.page_count); | ||
748 | } | ||
749 | |||
750 | static int vino_allocate_buffer(struct vino_framebuffer *fb, | ||
751 | unsigned int size) | ||
752 | { | ||
753 | unsigned int count, i, j; | ||
754 | int ret = 0; | ||
755 | |||
756 | dprintk("vino_allocate_buffer():\n"); | ||
757 | |||
758 | if (size < 1) | ||
759 | return -EINVAL; | ||
760 | |||
761 | memset(fb, 0, sizeof(struct vino_framebuffer)); | ||
762 | |||
763 | count = ((size / PAGE_SIZE) + 4) & ~3; | ||
764 | |||
765 | dprintk("vino_allocate_buffer(): size = %d, count = %d\n", | ||
766 | size, count); | ||
767 | |||
768 | /* allocate memory for table with virtual (page) addresses */ | ||
769 | fb->desc_table.virtual = (unsigned long *) | ||
770 | kmalloc(count * sizeof(unsigned long), GFP_KERNEL); | ||
771 | if (!fb->desc_table.virtual) | ||
772 | return -ENOMEM; | ||
773 | |||
774 | /* allocate memory for table with dma addresses | ||
775 | * (has space for four extra descriptors) */ | ||
776 | fb->desc_table.dma_cpu = | ||
777 | dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) * | ||
778 | sizeof(dma_addr_t), &fb->desc_table.dma, | ||
779 | GFP_KERNEL | GFP_DMA); | ||
780 | if (!fb->desc_table.dma_cpu) { | ||
781 | ret = -ENOMEM; | ||
782 | goto out_free_virtual; | ||
783 | } | ||
784 | |||
785 | /* allocate pages for the buffer and acquire the according | ||
786 | * dma addresses */ | ||
787 | for (i = 0; i < count; i++) { | ||
788 | dma_addr_t dma_data_addr; | ||
789 | |||
790 | fb->desc_table.virtual[i] = | ||
791 | get_zeroed_page(GFP_KERNEL | GFP_DMA); | ||
792 | if (!fb->desc_table.virtual[i]) { | ||
793 | ret = -ENOBUFS; | ||
794 | break; | ||
795 | } | ||
796 | |||
797 | dma_data_addr = | ||
798 | dma_map_single(NULL, | ||
799 | (void *)fb->desc_table.virtual[i], | ||
800 | PAGE_SIZE, DMA_FROM_DEVICE); | ||
801 | |||
802 | for (j = 0; j < VINO_PAGE_RATIO; j++) { | ||
803 | fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] = | ||
804 | dma_data_addr + VINO_PAGE_SIZE * j; | ||
805 | } | ||
806 | |||
807 | mem_map_reserve(virt_to_page(fb->desc_table.virtual[i])); | ||
808 | } | ||
809 | |||
810 | /* page_count needs to be set anyway, because the descriptor table has | ||
811 | * been allocated according to this number */ | ||
812 | fb->desc_table.page_count = count; | ||
813 | |||
814 | if (ret) { | ||
815 | /* the descriptor with index i doesn't contain | ||
816 | * a valid address yet */ | ||
817 | vino_free_buffer_with_count(fb, i); | ||
818 | return ret; | ||
819 | } | ||
820 | |||
821 | //fb->size = size; | ||
822 | fb->size = count * PAGE_SIZE; | ||
823 | fb->data_format = VINO_DATA_FMT_NONE; | ||
824 | |||
825 | /* set the dma stop-bit for the last (count+1)th descriptor */ | ||
826 | fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP; | ||
827 | return 0; | ||
828 | |||
829 | out_free_virtual: | ||
830 | kfree(fb->desc_table.virtual); | ||
831 | return ret; | ||
832 | } | ||
833 | |||
834 | #if 0 | ||
835 | /* user buffers not fully implemented yet */ | ||
836 | static int vino_prepare_user_buffer(struct vino_framebuffer *fb, | ||
837 | void *user, | ||
838 | unsigned int size) | ||
839 | { | ||
840 | unsigned int count, i, j; | ||
841 | int ret = 0; | ||
842 | |||
843 | dprintk("vino_prepare_user_buffer():\n"); | ||
844 | |||
845 | if (size < 1) | ||
846 | return -EINVAL; | ||
847 | |||
848 | memset(fb, 0, sizeof(struct vino_framebuffer)); | ||
849 | |||
850 | count = ((size / PAGE_SIZE)) & ~3; | ||
851 | |||
852 | dprintk("vino_prepare_user_buffer(): size = %d, count = %d\n", | ||
853 | size, count); | ||
854 | |||
855 | /* allocate memory for table with virtual (page) addresses */ | ||
856 | fb->desc_table.virtual = (unsigned long *) | ||
857 | kmalloc(count * sizeof(unsigned long), GFP_KERNEL); | ||
858 | if (!fb->desc_table.virtual) | ||
859 | return -ENOMEM; | ||
860 | |||
861 | /* allocate memory for table with dma addresses | ||
862 | * (has space for four extra descriptors) */ | ||
863 | fb->desc_table.dma_cpu = | ||
864 | dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) * | ||
865 | sizeof(dma_addr_t), &fb->desc_table.dma, | ||
866 | GFP_KERNEL | GFP_DMA); | ||
867 | if (!fb->desc_table.dma_cpu) { | ||
868 | ret = -ENOMEM; | ||
869 | goto out_free_virtual; | ||
870 | } | ||
871 | |||
872 | /* allocate pages for the buffer and acquire the according | ||
873 | * dma addresses */ | ||
874 | for (i = 0; i < count; i++) { | ||
875 | dma_addr_t dma_data_addr; | ||
876 | |||
877 | fb->desc_table.virtual[i] = | ||
878 | get_zeroed_page(GFP_KERNEL | GFP_DMA); | ||
879 | if (!fb->desc_table.virtual[i]) { | ||
880 | ret = -ENOBUFS; | ||
881 | break; | ||
882 | } | ||
883 | |||
884 | dma_data_addr = | ||
885 | dma_map_single(NULL, | ||
886 | (void *)fb->desc_table.virtual[i], | ||
887 | PAGE_SIZE, DMA_FROM_DEVICE); | ||
888 | |||
889 | for (j = 0; j < VINO_PAGE_RATIO; j++) { | ||
890 | fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] = | ||
891 | dma_data_addr + VINO_PAGE_SIZE * j; | ||
892 | } | ||
893 | |||
894 | mem_map_reserve(virt_to_page(fb->desc_table.virtual[i])); | ||
895 | } | ||
896 | |||
897 | /* page_count needs to be set anyway, because the descriptor table has | ||
898 | * been allocated according to this number */ | ||
899 | fb->desc_table.page_count = count; | ||
900 | |||
901 | if (ret) { | ||
902 | /* the descriptor with index i doesn't contain | ||
903 | * a valid address yet */ | ||
904 | vino_free_buffer_with_count(fb, i); | ||
905 | return ret; | ||
906 | } | ||
907 | |||
908 | //fb->size = size; | ||
909 | fb->size = count * PAGE_SIZE; | ||
910 | |||
911 | /* set the dma stop-bit for the last (count+1)th descriptor */ | ||
912 | fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP; | ||
913 | return 0; | ||
914 | |||
915 | out_free_virtual: | ||
916 | kfree(fb->desc_table.virtual); | ||
917 | return ret; | ||
918 | } | ||
919 | #endif | ||
920 | |||
921 | static void vino_sync_buffer(struct vino_framebuffer *fb) | ||
922 | { | ||
923 | int i; | ||
924 | |||
925 | dprintk("vino_sync_buffer():\n"); | ||
926 | |||
927 | for (i = 0; i < fb->desc_table.page_count; i++) | ||
928 | dma_sync_single(NULL, | ||
929 | fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i], | ||
930 | PAGE_SIZE, DMA_FROM_DEVICE); | ||
931 | } | ||
932 | |||
933 | /* Framebuffer fifo functions (need to be locked externally) */ | ||
934 | |||
935 | static void vino_fifo_init(struct vino_framebuffer_fifo *f, | ||
936 | unsigned int length) | ||
937 | { | ||
938 | f->length = 0; | ||
939 | f->used = 0; | ||
940 | f->head = 0; | ||
941 | f->tail = 0; | ||
942 | |||
943 | if (length > VINO_FRAMEBUFFER_MAX_COUNT) | ||
944 | length = VINO_FRAMEBUFFER_MAX_COUNT; | ||
945 | |||
946 | f->length = length; | ||
947 | } | ||
948 | |||
949 | /* returns true/false */ | ||
950 | static int vino_fifo_has_id(struct vino_framebuffer_fifo *f, unsigned int id) | ||
951 | { | ||
952 | unsigned int i; | ||
953 | for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) { | ||
954 | if (f->data[i] == id) | ||
955 | return 1; | ||
956 | } | ||
957 | |||
958 | return 0; | ||
959 | } | ||
960 | |||
961 | /* returns true/false */ | ||
962 | static int vino_fifo_full(struct vino_framebuffer_fifo *f) | ||
963 | { | ||
964 | return (f->used == f->length); | ||
965 | } | ||
966 | |||
967 | static unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f) | ||
968 | { | ||
969 | return f->used; | ||
970 | } | ||
179 | 971 | ||
180 | static void vino_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 972 | static int vino_fifo_enqueue(struct vino_framebuffer_fifo *f, unsigned int id) |
181 | { | 973 | { |
974 | if (id >= f->length) { | ||
975 | return VINO_QUEUE_ERROR; | ||
976 | } | ||
977 | |||
978 | if (vino_fifo_has_id(f, id)) { | ||
979 | return VINO_QUEUE_ERROR; | ||
980 | } | ||
981 | |||
982 | if (f->used < f->length) { | ||
983 | f->data[f->tail] = id; | ||
984 | f->tail = (f->tail + 1) % f->length; | ||
985 | f->used++; | ||
986 | } else { | ||
987 | return VINO_QUEUE_ERROR; | ||
988 | } | ||
989 | |||
990 | return 0; | ||
182 | } | 991 | } |
183 | 992 | ||
184 | static int vino_open(struct video_device *dev, int flags) | 993 | static int vino_fifo_peek(struct vino_framebuffer_fifo *f, unsigned int *id) |
185 | { | 994 | { |
186 | struct vino_device *videv = (struct vino_device *)dev; | 995 | if (f->used > 0) { |
996 | *id = f->data[f->head]; | ||
997 | } else { | ||
998 | return VINO_QUEUE_ERROR; | ||
999 | } | ||
187 | 1000 | ||
188 | return 0; | 1001 | return 0; |
189 | } | 1002 | } |
190 | 1003 | ||
191 | static void vino_close(struct video_device *dev) | 1004 | static int vino_fifo_dequeue(struct vino_framebuffer_fifo *f, unsigned int *id) |
192 | { | 1005 | { |
193 | struct vino_device *videv = (struct vino_device *)dev; | 1006 | if (f->used > 0) { |
1007 | *id = f->data[f->head]; | ||
1008 | f->head = (f->head + 1) % f->length; | ||
1009 | f->used--; | ||
1010 | } else { | ||
1011 | return VINO_QUEUE_ERROR; | ||
1012 | } | ||
1013 | |||
1014 | return 0; | ||
194 | } | 1015 | } |
195 | 1016 | ||
196 | static int vino_mmap(struct video_device *dev, const char *adr, | 1017 | /* Framebuffer queue functions */ |
197 | unsigned long size) | 1018 | |
1019 | /* execute with queue_lock locked */ | ||
1020 | static void vino_queue_free_with_count(struct vino_framebuffer_queue *q, | ||
1021 | unsigned int length) | ||
198 | { | 1022 | { |
199 | struct vino_device *videv = (struct vino_device *)dev; | 1023 | unsigned int i; |
200 | 1024 | ||
201 | return -EINVAL; | 1025 | q->length = 0; |
1026 | memset(&q->in, 0, sizeof(struct vino_framebuffer_fifo)); | ||
1027 | memset(&q->out, 0, sizeof(struct vino_framebuffer_fifo)); | ||
1028 | for (i = 0; i < length; i++) { | ||
1029 | dprintk("vino_queue_free_with_count(): freeing buffer %d\n", | ||
1030 | i); | ||
1031 | vino_free_buffer(q->buffer[i]); | ||
1032 | kfree(q->buffer[i]); | ||
1033 | } | ||
1034 | |||
1035 | q->type = VINO_MEMORY_NONE; | ||
1036 | q->magic = 0; | ||
202 | } | 1037 | } |
203 | 1038 | ||
204 | static int vino_ioctl(struct video_device *dev, unsigned int cmd, void *arg) | 1039 | static void vino_queue_free(struct vino_framebuffer_queue *q) |
205 | { | 1040 | { |
206 | struct vino_device *videv = (struct vino_device *)dev; | 1041 | dprintk("vino_queue_free():\n"); |
1042 | |||
1043 | if (q->magic != VINO_QUEUE_MAGIC) | ||
1044 | return; | ||
1045 | if (q->type != VINO_MEMORY_MMAP) | ||
1046 | return; | ||
1047 | |||
1048 | down(&q->queue_sem); | ||
1049 | |||
1050 | vino_queue_free_with_count(q, q->length); | ||
1051 | |||
1052 | up(&q->queue_sem); | ||
1053 | } | ||
1054 | |||
1055 | static int vino_queue_init(struct vino_framebuffer_queue *q, | ||
1056 | unsigned int *length) | ||
1057 | { | ||
1058 | unsigned int i; | ||
1059 | int ret = 0; | ||
1060 | |||
1061 | dprintk("vino_queue_init(): length = %d\n", *length); | ||
1062 | |||
1063 | if (q->magic == VINO_QUEUE_MAGIC) { | ||
1064 | dprintk("vino_queue_init(): queue already initialized!\n"); | ||
1065 | return -EINVAL; | ||
1066 | } | ||
1067 | |||
1068 | if (q->type != VINO_MEMORY_NONE) { | ||
1069 | dprintk("vino_queue_init(): queue already initialized!\n"); | ||
1070 | return -EINVAL; | ||
1071 | } | ||
1072 | |||
1073 | if (*length < 1) | ||
1074 | return -EINVAL; | ||
1075 | |||
1076 | down(&q->queue_sem); | ||
1077 | |||
1078 | if (*length > VINO_FRAMEBUFFER_MAX_COUNT) | ||
1079 | *length = VINO_FRAMEBUFFER_MAX_COUNT; | ||
1080 | |||
1081 | q->length = 0; | ||
1082 | |||
1083 | for (i = 0; i < *length; i++) { | ||
1084 | dprintk("vino_queue_init(): allocating buffer %d\n", i); | ||
1085 | q->buffer[i] = kmalloc(sizeof(struct vino_framebuffer), | ||
1086 | GFP_KERNEL); | ||
1087 | if (!q->buffer[i]) { | ||
1088 | dprintk("vino_queue_init(): kmalloc() failed\n"); | ||
1089 | ret = -ENOMEM; | ||
1090 | break; | ||
1091 | } | ||
1092 | |||
1093 | ret = vino_allocate_buffer(q->buffer[i], | ||
1094 | VINO_FRAMEBUFFER_SIZE); | ||
1095 | if (ret) { | ||
1096 | kfree(q->buffer[i]); | ||
1097 | dprintk("vino_queue_init(): " | ||
1098 | "vino_allocate_buffer() failed\n"); | ||
1099 | break; | ||
1100 | } | ||
1101 | |||
1102 | q->buffer[i]->id = i; | ||
1103 | if (i > 0) { | ||
1104 | q->buffer[i]->offset = q->buffer[i - 1]->offset + | ||
1105 | q->buffer[i - 1]->size; | ||
1106 | } else { | ||
1107 | q->buffer[i]->offset = 0; | ||
1108 | } | ||
1109 | |||
1110 | spin_lock_init(&q->buffer[i]->state_lock); | ||
1111 | |||
1112 | dprintk("vino_queue_init(): buffer = %d, offset = %d, " | ||
1113 | "size = %d\n", i, q->buffer[i]->offset, | ||
1114 | q->buffer[i]->size); | ||
1115 | } | ||
1116 | |||
1117 | if (ret) { | ||
1118 | vino_queue_free_with_count(q, i); | ||
1119 | *length = 0; | ||
1120 | } else { | ||
1121 | q->length = *length; | ||
1122 | vino_fifo_init(&q->in, q->length); | ||
1123 | vino_fifo_init(&q->out, q->length); | ||
1124 | q->type = VINO_MEMORY_MMAP; | ||
1125 | q->magic = VINO_QUEUE_MAGIC; | ||
1126 | } | ||
1127 | |||
1128 | up(&q->queue_sem); | ||
1129 | |||
1130 | return ret; | ||
1131 | } | ||
1132 | |||
1133 | static struct vino_framebuffer *vino_queue_add(struct | ||
1134 | vino_framebuffer_queue *q, | ||
1135 | unsigned int id) | ||
1136 | { | ||
1137 | struct vino_framebuffer *ret = NULL; | ||
1138 | unsigned int total; | ||
1139 | unsigned long flags; | ||
1140 | |||
1141 | dprintk("vino_queue_add(): id = %d\n", id); | ||
1142 | |||
1143 | if (q->magic != VINO_QUEUE_MAGIC) { | ||
1144 | return ret; | ||
1145 | } | ||
1146 | |||
1147 | spin_lock_irqsave(&q->queue_lock, flags); | ||
1148 | |||
1149 | if (q->length == 0) | ||
1150 | goto out; | ||
1151 | |||
1152 | if (id >= q->length) | ||
1153 | goto out; | ||
1154 | |||
1155 | /* not needed?: if (vino_fifo_full(&q->out)) { | ||
1156 | goto out; | ||
1157 | }*/ | ||
1158 | /* check that outgoing queue isn't already full | ||
1159 | * (or that it won't become full) */ | ||
1160 | total = vino_fifo_get_used(&q->in) + | ||
1161 | vino_fifo_get_used(&q->out); | ||
1162 | if (total >= q->length) | ||
1163 | goto out; | ||
1164 | |||
1165 | if (vino_fifo_enqueue(&q->in, id)) | ||
1166 | goto out; | ||
1167 | |||
1168 | ret = q->buffer[id]; | ||
1169 | |||
1170 | out: | ||
1171 | spin_unlock_irqrestore(&q->queue_lock, flags); | ||
1172 | |||
1173 | return ret; | ||
1174 | } | ||
1175 | |||
1176 | static struct vino_framebuffer *vino_queue_transfer(struct | ||
1177 | vino_framebuffer_queue *q) | ||
1178 | { | ||
1179 | struct vino_framebuffer *ret = NULL; | ||
1180 | struct vino_framebuffer *fb; | ||
1181 | int id; | ||
1182 | unsigned long flags; | ||
1183 | |||
1184 | dprintk("vino_queue_transfer():\n"); | ||
1185 | |||
1186 | if (q->magic != VINO_QUEUE_MAGIC) { | ||
1187 | return ret; | ||
1188 | } | ||
1189 | |||
1190 | spin_lock_irqsave(&q->queue_lock, flags); | ||
1191 | |||
1192 | if (q->length == 0) | ||
1193 | goto out; | ||
1194 | |||
1195 | // now this actually removes an entry from the incoming queue | ||
1196 | if (vino_fifo_dequeue(&q->in, &id)) { | ||
1197 | goto out; | ||
1198 | } | ||
1199 | |||
1200 | dprintk("vino_queue_transfer(): id = %d\n", id); | ||
1201 | fb = q->buffer[id]; | ||
1202 | |||
1203 | // we have already checked that the outgoing queue is not full, but... | ||
1204 | if (vino_fifo_enqueue(&q->out, id)) { | ||
1205 | printk(KERN_ERR "vino_queue_transfer(): " | ||
1206 | "outgoing queue is full, this shouldn't happen!\n"); | ||
1207 | goto out; | ||
1208 | } | ||
1209 | |||
1210 | ret = fb; | ||
1211 | out: | ||
1212 | spin_unlock_irqrestore(&q->queue_lock, flags); | ||
1213 | |||
1214 | return ret; | ||
1215 | } | ||
1216 | |||
1217 | /* returns true/false */ | ||
1218 | static int vino_queue_incoming_contains(struct vino_framebuffer_queue *q, | ||
1219 | unsigned int id) | ||
1220 | { | ||
1221 | int ret = 0; | ||
1222 | unsigned long flags; | ||
1223 | |||
1224 | if (q->magic != VINO_QUEUE_MAGIC) { | ||
1225 | return ret; | ||
1226 | } | ||
1227 | |||
1228 | spin_lock_irqsave(&q->queue_lock, flags); | ||
1229 | |||
1230 | if (q->length == 0) | ||
1231 | goto out; | ||
1232 | |||
1233 | ret = vino_fifo_has_id(&q->in, id); | ||
1234 | |||
1235 | out: | ||
1236 | spin_unlock_irqrestore(&q->queue_lock, flags); | ||
1237 | |||
1238 | return ret; | ||
1239 | } | ||
1240 | |||
1241 | /* returns true/false */ | ||
1242 | static int vino_queue_outgoing_contains(struct vino_framebuffer_queue *q, | ||
1243 | unsigned int id) | ||
1244 | { | ||
1245 | int ret = 0; | ||
1246 | unsigned long flags; | ||
1247 | |||
1248 | if (q->magic != VINO_QUEUE_MAGIC) { | ||
1249 | return ret; | ||
1250 | } | ||
1251 | |||
1252 | spin_lock_irqsave(&q->queue_lock, flags); | ||
1253 | |||
1254 | if (q->length == 0) | ||
1255 | goto out; | ||
1256 | |||
1257 | ret = vino_fifo_has_id(&q->out, id); | ||
1258 | |||
1259 | out: | ||
1260 | spin_unlock_irqrestore(&q->queue_lock, flags); | ||
1261 | |||
1262 | return ret; | ||
1263 | } | ||
1264 | |||
1265 | static int vino_queue_get_incoming(struct vino_framebuffer_queue *q, | ||
1266 | unsigned int *used) | ||
1267 | { | ||
1268 | int ret = 0; | ||
1269 | unsigned long flags; | ||
1270 | |||
1271 | if (q->magic != VINO_QUEUE_MAGIC) { | ||
1272 | return VINO_QUEUE_ERROR; | ||
1273 | } | ||
1274 | |||
1275 | spin_lock_irqsave(&q->queue_lock, flags); | ||
1276 | |||
1277 | if (q->length == 0) { | ||
1278 | ret = VINO_QUEUE_ERROR; | ||
1279 | goto out; | ||
1280 | } | ||
1281 | |||
1282 | *used = vino_fifo_get_used(&q->in); | ||
1283 | |||
1284 | out: | ||
1285 | spin_unlock_irqrestore(&q->queue_lock, flags); | ||
1286 | |||
1287 | return ret; | ||
1288 | } | ||
1289 | |||
1290 | static int vino_queue_get_outgoing(struct vino_framebuffer_queue *q, | ||
1291 | unsigned int *used) | ||
1292 | { | ||
1293 | int ret = 0; | ||
1294 | unsigned long flags; | ||
1295 | |||
1296 | if (q->magic != VINO_QUEUE_MAGIC) { | ||
1297 | return VINO_QUEUE_ERROR; | ||
1298 | } | ||
1299 | |||
1300 | spin_lock_irqsave(&q->queue_lock, flags); | ||
1301 | |||
1302 | if (q->length == 0) { | ||
1303 | ret = VINO_QUEUE_ERROR; | ||
1304 | goto out; | ||
1305 | } | ||
1306 | |||
1307 | *used = vino_fifo_get_used(&q->out); | ||
1308 | |||
1309 | out: | ||
1310 | spin_unlock_irqrestore(&q->queue_lock, flags); | ||
1311 | |||
1312 | return ret; | ||
1313 | } | ||
1314 | |||
1315 | static int vino_queue_get_total(struct vino_framebuffer_queue *q, | ||
1316 | unsigned int *total) | ||
1317 | { | ||
1318 | int ret = 0; | ||
1319 | unsigned long flags; | ||
1320 | |||
1321 | if (q->magic != VINO_QUEUE_MAGIC) { | ||
1322 | return VINO_QUEUE_ERROR; | ||
1323 | } | ||
1324 | |||
1325 | spin_lock_irqsave(&q->queue_lock, flags); | ||
1326 | |||
1327 | if (q->length == 0) { | ||
1328 | ret = VINO_QUEUE_ERROR; | ||
1329 | goto out; | ||
1330 | } | ||
1331 | |||
1332 | *total = vino_fifo_get_used(&q->in) + | ||
1333 | vino_fifo_get_used(&q->out); | ||
1334 | |||
1335 | out: | ||
1336 | spin_unlock_irqrestore(&q->queue_lock, flags); | ||
1337 | |||
1338 | return ret; | ||
1339 | } | ||
1340 | |||
1341 | static struct vino_framebuffer *vino_queue_peek(struct | ||
1342 | vino_framebuffer_queue *q, | ||
1343 | unsigned int *id) | ||
1344 | { | ||
1345 | struct vino_framebuffer *ret = NULL; | ||
1346 | unsigned long flags; | ||
1347 | |||
1348 | if (q->magic != VINO_QUEUE_MAGIC) { | ||
1349 | return ret; | ||
1350 | } | ||
1351 | |||
1352 | spin_lock_irqsave(&q->queue_lock, flags); | ||
1353 | |||
1354 | if (q->length == 0) | ||
1355 | goto out; | ||
1356 | |||
1357 | if (vino_fifo_peek(&q->in, id)) { | ||
1358 | goto out; | ||
1359 | } | ||
1360 | |||
1361 | ret = q->buffer[*id]; | ||
1362 | out: | ||
1363 | spin_unlock_irqrestore(&q->queue_lock, flags); | ||
1364 | |||
1365 | return ret; | ||
1366 | } | ||
1367 | |||
1368 | static struct vino_framebuffer *vino_queue_remove(struct | ||
1369 | vino_framebuffer_queue *q, | ||
1370 | unsigned int *id) | ||
1371 | { | ||
1372 | struct vino_framebuffer *ret = NULL; | ||
1373 | unsigned long flags; | ||
1374 | dprintk("vino_queue_remove():\n"); | ||
1375 | |||
1376 | if (q->magic != VINO_QUEUE_MAGIC) { | ||
1377 | return ret; | ||
1378 | } | ||
1379 | |||
1380 | spin_lock_irqsave(&q->queue_lock, flags); | ||
1381 | |||
1382 | if (q->length == 0) | ||
1383 | goto out; | ||
1384 | |||
1385 | if (vino_fifo_dequeue(&q->out, id)) { | ||
1386 | goto out; | ||
1387 | } | ||
1388 | |||
1389 | dprintk("vino_queue_remove(): id = %d\n", *id); | ||
1390 | ret = q->buffer[*id]; | ||
1391 | out: | ||
1392 | spin_unlock_irqrestore(&q->queue_lock, flags); | ||
1393 | |||
1394 | return ret; | ||
1395 | } | ||
1396 | |||
1397 | static struct | ||
1398 | vino_framebuffer *vino_queue_get_buffer(struct vino_framebuffer_queue *q, | ||
1399 | unsigned int id) | ||
1400 | { | ||
1401 | struct vino_framebuffer *ret = NULL; | ||
1402 | unsigned long flags; | ||
1403 | |||
1404 | if (q->magic != VINO_QUEUE_MAGIC) { | ||
1405 | return ret; | ||
1406 | } | ||
1407 | |||
1408 | spin_lock_irqsave(&q->queue_lock, flags); | ||
1409 | |||
1410 | if (q->length == 0) | ||
1411 | goto out; | ||
1412 | |||
1413 | if (id >= q->length) | ||
1414 | goto out; | ||
1415 | |||
1416 | ret = q->buffer[id]; | ||
1417 | out: | ||
1418 | spin_unlock_irqrestore(&q->queue_lock, flags); | ||
1419 | |||
1420 | return ret; | ||
1421 | } | ||
1422 | |||
1423 | static unsigned int vino_queue_get_length(struct vino_framebuffer_queue *q) | ||
1424 | { | ||
1425 | unsigned int length = 0; | ||
1426 | unsigned long flags; | ||
1427 | |||
1428 | if (q->magic != VINO_QUEUE_MAGIC) { | ||
1429 | return length; | ||
1430 | } | ||
1431 | |||
1432 | spin_lock_irqsave(&q->queue_lock, flags); | ||
1433 | length = q->length; | ||
1434 | spin_unlock_irqrestore(&q->queue_lock, flags); | ||
1435 | |||
1436 | return length; | ||
1437 | } | ||
1438 | |||
1439 | static int vino_queue_has_mapped_buffers(struct vino_framebuffer_queue *q) | ||
1440 | { | ||
1441 | unsigned int i; | ||
1442 | int ret = 0; | ||
1443 | unsigned long flags; | ||
1444 | |||
1445 | if (q->magic != VINO_QUEUE_MAGIC) { | ||
1446 | return ret; | ||
1447 | } | ||
1448 | |||
1449 | spin_lock_irqsave(&q->queue_lock, flags); | ||
1450 | for (i = 0; i < q->length; i++) { | ||
1451 | if (q->buffer[i]->map_count > 0) { | ||
1452 | ret = 1; | ||
1453 | break; | ||
1454 | } | ||
1455 | } | ||
1456 | spin_unlock_irqrestore(&q->queue_lock, flags); | ||
1457 | |||
1458 | return ret; | ||
1459 | } | ||
1460 | |||
1461 | /* VINO functions */ | ||
1462 | |||
1463 | /* execute with input_lock locked */ | ||
1464 | static void vino_update_line_size(struct vino_channel_settings *vcs) | ||
1465 | { | ||
1466 | unsigned int w = vcs->clipping.right - vcs->clipping.left; | ||
1467 | unsigned int d = vcs->decimation; | ||
1468 | unsigned int bpp = vino_data_formats[vcs->data_format].bpp; | ||
1469 | unsigned int lsize; | ||
1470 | |||
1471 | dprintk("update_line_size(): before: w = %d, d = %d, " | ||
1472 | "line_size = %d\n", w, d, vcs->line_size); | ||
1473 | /* line size must be multiple of 8 bytes */ | ||
1474 | lsize = (bpp * (w / d)) & ~7; | ||
1475 | w = (lsize / bpp) * d; | ||
1476 | |||
1477 | vcs->clipping.right = vcs->clipping.left + w; | ||
1478 | vcs->line_size = lsize; | ||
1479 | dprintk("update_line_size(): after: w = %d, d = %d, " | ||
1480 | "line_size = %d\n", w, d, vcs->line_size); | ||
1481 | } | ||
1482 | |||
1483 | /* execute with input_lock locked */ | ||
1484 | static void vino_set_clipping(struct vino_channel_settings *vcs, | ||
1485 | unsigned int x, unsigned int y, | ||
1486 | unsigned int w, unsigned int h) | ||
1487 | { | ||
1488 | unsigned int maxwidth, maxheight; | ||
1489 | unsigned int d; | ||
1490 | |||
1491 | maxwidth = vino_data_norms[vcs->data_norm].width; | ||
1492 | maxheight = vino_data_norms[vcs->data_norm].height; | ||
1493 | d = vcs->decimation; | ||
1494 | |||
1495 | y &= ~1; /* odd/even fields */ | ||
1496 | |||
1497 | if (x > maxwidth) { | ||
1498 | x = 0; | ||
1499 | } | ||
1500 | if (y > maxheight) { | ||
1501 | y = 0; | ||
1502 | } | ||
1503 | |||
1504 | if (((w / d) < VINO_MIN_WIDTH) | ||
1505 | || ((h / d) < VINO_MIN_HEIGHT)) { | ||
1506 | w = VINO_MIN_WIDTH * d; | ||
1507 | h = VINO_MIN_HEIGHT * d; | ||
1508 | } | ||
1509 | |||
1510 | if ((x + w) > maxwidth) { | ||
1511 | w = maxwidth - x; | ||
1512 | if ((w / d) < VINO_MIN_WIDTH) | ||
1513 | x = maxwidth - VINO_MIN_WIDTH * d; | ||
1514 | } | ||
1515 | if ((y + h) > maxheight) { | ||
1516 | h = maxheight - y; | ||
1517 | if ((h / d) < VINO_MIN_HEIGHT) | ||
1518 | y = maxheight - VINO_MIN_HEIGHT * d; | ||
1519 | } | ||
1520 | |||
1521 | vcs->clipping.left = x; | ||
1522 | vcs->clipping.top = y; | ||
1523 | vcs->clipping.right = x + w; | ||
1524 | vcs->clipping.bottom = y + h; | ||
1525 | |||
1526 | vino_update_line_size(vcs); | ||
1527 | |||
1528 | dprintk("clipping %d, %d, %d, %d / %d - %d\n", | ||
1529 | vcs->clipping.left, vcs->clipping.top, vcs->clipping.right, | ||
1530 | vcs->clipping.bottom, vcs->decimation, vcs->line_size); | ||
1531 | } | ||
1532 | |||
1533 | /* execute with input_lock locked */ | ||
1534 | static void vino_set_default_clipping(struct vino_channel_settings *vcs) | ||
1535 | { | ||
1536 | vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width, | ||
1537 | vino_data_norms[vcs->data_norm].height); | ||
1538 | } | ||
1539 | |||
1540 | /* execute with input_lock locked */ | ||
1541 | static void vino_set_scaling(struct vino_channel_settings *vcs, | ||
1542 | unsigned int w, unsigned int h) | ||
1543 | { | ||
1544 | unsigned int x, y, curw, curh, d; | ||
1545 | |||
1546 | x = vcs->clipping.left; | ||
1547 | y = vcs->clipping.top; | ||
1548 | curw = vcs->clipping.right - vcs->clipping.left; | ||
1549 | curh = vcs->clipping.bottom - vcs->clipping.top; | ||
1550 | |||
1551 | d = max(curw / w, curh / h); | ||
1552 | |||
1553 | dprintk("scaling w: %d, h: %d, curw: %d, curh: %d, d: %d\n", | ||
1554 | w, h, curw, curh, d); | ||
1555 | |||
1556 | if (d < 1) { | ||
1557 | d = 1; | ||
1558 | } | ||
1559 | if (d > 8) { | ||
1560 | d = 8; | ||
1561 | } | ||
1562 | |||
1563 | vcs->decimation = d; | ||
1564 | vino_set_clipping(vcs, x, y, w * d, h * d); | ||
1565 | |||
1566 | dprintk("scaling %d, %d, %d, %d / %d - %d\n", vcs->clipping.left, | ||
1567 | vcs->clipping.top, vcs->clipping.right, vcs->clipping.bottom, | ||
1568 | vcs->decimation, vcs->line_size); | ||
1569 | } | ||
1570 | |||
1571 | /* execute with input_lock locked */ | ||
1572 | static void vino_reset_scaling(struct vino_channel_settings *vcs) | ||
1573 | { | ||
1574 | vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left, | ||
1575 | vcs->clipping.bottom - vcs->clipping.top); | ||
1576 | } | ||
1577 | |||
1578 | /* execute with input_lock locked */ | ||
1579 | static void vino_set_framerate(struct vino_channel_settings *vcs, | ||
1580 | unsigned int fps) | ||
1581 | { | ||
1582 | unsigned int mask; | ||
1583 | |||
1584 | switch (vcs->data_norm) { | ||
1585 | case VINO_DATA_NORM_NTSC: | ||
1586 | case VINO_DATA_NORM_D1: | ||
1587 | fps = (unsigned int)(fps / 6) * 6; // FIXME: round! | ||
1588 | |||
1589 | if (fps < vino_data_norms[vcs->data_norm].fps_min) | ||
1590 | fps = vino_data_norms[vcs->data_norm].fps_min; | ||
1591 | if (fps > vino_data_norms[vcs->data_norm].fps_max) | ||
1592 | fps = vino_data_norms[vcs->data_norm].fps_max; | ||
1593 | |||
1594 | switch (fps) { | ||
1595 | case 6: | ||
1596 | mask = 0x003; | ||
1597 | break; | ||
1598 | case 12: | ||
1599 | mask = 0x0c3; | ||
1600 | break; | ||
1601 | case 18: | ||
1602 | mask = 0x333; | ||
1603 | break; | ||
1604 | case 24: | ||
1605 | mask = 0x3ff; | ||
1606 | break; | ||
1607 | case 30: | ||
1608 | mask = 0xfff; | ||
1609 | break; | ||
1610 | default: | ||
1611 | mask = VINO_FRAMERT_FULL; | ||
1612 | } | ||
1613 | vcs->framert_reg = VINO_FRAMERT_RT(mask); | ||
1614 | break; | ||
1615 | case VINO_DATA_NORM_PAL: | ||
1616 | case VINO_DATA_NORM_SECAM: | ||
1617 | fps = (unsigned int)(fps / 5) * 5; // FIXME: round! | ||
1618 | |||
1619 | if (fps < vino_data_norms[vcs->data_norm].fps_min) | ||
1620 | fps = vino_data_norms[vcs->data_norm].fps_min; | ||
1621 | if (fps > vino_data_norms[vcs->data_norm].fps_max) | ||
1622 | fps = vino_data_norms[vcs->data_norm].fps_max; | ||
1623 | |||
1624 | switch (fps) { | ||
1625 | case 5: | ||
1626 | mask = 0x003; | ||
1627 | break; | ||
1628 | case 10: | ||
1629 | mask = 0x0c3; | ||
1630 | break; | ||
1631 | case 15: | ||
1632 | mask = 0x333; | ||
1633 | break; | ||
1634 | case 20: | ||
1635 | mask = 0x0ff; | ||
1636 | break; | ||
1637 | case 25: | ||
1638 | mask = 0x3ff; | ||
1639 | break; | ||
1640 | default: | ||
1641 | mask = VINO_FRAMERT_FULL; | ||
1642 | } | ||
1643 | vcs->framert_reg = VINO_FRAMERT_RT(mask) | VINO_FRAMERT_PAL; | ||
1644 | break; | ||
1645 | } | ||
1646 | |||
1647 | vcs->fps = fps; | ||
1648 | } | ||
1649 | |||
1650 | /* execute with input_lock locked */ | ||
1651 | static void vino_set_default_framerate(struct vino_channel_settings *vcs) | ||
1652 | { | ||
1653 | vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max); | ||
1654 | } | ||
1655 | |||
1656 | /* | ||
1657 | * Prepare VINO for DMA transfer... | ||
1658 | * (execute only with vino_lock and input_lock locked) | ||
1659 | */ | ||
1660 | static int vino_dma_setup(struct vino_channel_settings *vcs, | ||
1661 | struct vino_framebuffer *fb) | ||
1662 | { | ||
1663 | u32 ctrl, intr; | ||
1664 | struct sgi_vino_channel *ch; | ||
1665 | const struct vino_data_norm *norm; | ||
1666 | |||
1667 | dprintk("vino_dma_setup():\n"); | ||
1668 | |||
1669 | vcs->field = 0; | ||
1670 | fb->frame_counter = 0; | ||
1671 | |||
1672 | ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b; | ||
1673 | norm = &vino_data_norms[vcs->data_norm]; | ||
1674 | |||
1675 | ch->page_index = 0; | ||
1676 | ch->line_count = 0; | ||
1677 | |||
1678 | /* VINO line size register is set 8 bytes less than actual */ | ||
1679 | ch->line_size = vcs->line_size - 8; | ||
1680 | |||
1681 | /* let VINO know where to transfer data */ | ||
1682 | ch->start_desc_tbl = fb->desc_table.dma; | ||
1683 | ch->next_4_desc = fb->desc_table.dma; | ||
1684 | |||
1685 | /* give vino time to fetch the first four descriptors, 5 usec | ||
1686 | * should be more than enough time */ | ||
1687 | udelay(VINO_DESC_FETCH_DELAY); | ||
1688 | |||
1689 | /* set the alpha register */ | ||
1690 | ch->alpha = vcs->alpha; | ||
1691 | |||
1692 | /* set clipping registers */ | ||
1693 | ch->clip_start = VINO_CLIP_ODD(norm->odd.top + vcs->clipping.top / 2) | | ||
1694 | VINO_CLIP_EVEN(norm->even.top + | ||
1695 | vcs->clipping.top / 2) | | ||
1696 | VINO_CLIP_X(vcs->clipping.left); | ||
1697 | ch->clip_end = VINO_CLIP_ODD(norm->odd.top + | ||
1698 | vcs->clipping.bottom / 2 - 1) | | ||
1699 | VINO_CLIP_EVEN(norm->even.top + | ||
1700 | vcs->clipping.bottom / 2 - 1) | | ||
1701 | VINO_CLIP_X(vcs->clipping.right); | ||
1702 | /* FIXME: end-of-field bug workaround | ||
1703 | VINO_CLIP_X(VINO_PAL_WIDTH); | ||
1704 | */ | ||
1705 | |||
1706 | /* set the size of actual content in the buffer (DECIMATION !) */ | ||
1707 | fb->data_size = ((vcs->clipping.right - vcs->clipping.left) / | ||
1708 | vcs->decimation) * | ||
1709 | ((vcs->clipping.bottom - vcs->clipping.top) / | ||
1710 | vcs->decimation) * | ||
1711 | vino_data_formats[vcs->data_format].bpp; | ||
1712 | |||
1713 | ch->frame_rate = vcs->framert_reg; | ||
1714 | |||
1715 | ctrl = vino->control; | ||
1716 | intr = vino->intr_status; | ||
1717 | |||
1718 | if (vcs->channel == VINO_CHANNEL_A) { | ||
1719 | /* All interrupt conditions for this channel was cleared | ||
1720 | * so clear the interrupt status register and enable | ||
1721 | * interrupts */ | ||
1722 | intr &= ~VINO_INTSTAT_A; | ||
1723 | ctrl |= VINO_CTRL_A_INT; | ||
1724 | |||
1725 | /* enable synchronization */ | ||
1726 | ctrl |= VINO_CTRL_A_SYNC_ENBL; | ||
1727 | |||
1728 | /* enable frame assembly */ | ||
1729 | ctrl |= VINO_CTRL_A_INTERLEAVE_ENBL; | ||
1730 | |||
1731 | /* set decimation used */ | ||
1732 | if (vcs->decimation < 2) | ||
1733 | ctrl &= ~VINO_CTRL_A_DEC_ENBL; | ||
1734 | else { | ||
1735 | ctrl |= VINO_CTRL_A_DEC_ENBL; | ||
1736 | ctrl &= ~VINO_CTRL_A_DEC_SCALE_MASK; | ||
1737 | ctrl |= (vcs->decimation - 1) << | ||
1738 | VINO_CTRL_A_DEC_SCALE_SHIFT; | ||
1739 | } | ||
1740 | |||
1741 | /* select input interface */ | ||
1742 | if (vcs->input == VINO_INPUT_D1) | ||
1743 | ctrl |= VINO_CTRL_A_SELECT; | ||
1744 | else | ||
1745 | ctrl &= ~VINO_CTRL_A_SELECT; | ||
1746 | |||
1747 | /* palette */ | ||
1748 | ctrl &= ~(VINO_CTRL_A_LUMA_ONLY | VINO_CTRL_A_RGB | | ||
1749 | VINO_CTRL_A_DITHER); | ||
1750 | } else { | ||
1751 | intr &= ~VINO_INTSTAT_B; | ||
1752 | ctrl |= VINO_CTRL_B_INT; | ||
1753 | |||
1754 | ctrl |= VINO_CTRL_B_SYNC_ENBL; | ||
1755 | ctrl |= VINO_CTRL_B_INTERLEAVE_ENBL; | ||
1756 | |||
1757 | if (vcs->decimation < 2) | ||
1758 | ctrl &= ~VINO_CTRL_B_DEC_ENBL; | ||
1759 | else { | ||
1760 | ctrl |= VINO_CTRL_B_DEC_ENBL; | ||
1761 | ctrl &= ~VINO_CTRL_B_DEC_SCALE_MASK; | ||
1762 | ctrl |= (vcs->decimation - 1) << | ||
1763 | VINO_CTRL_B_DEC_SCALE_SHIFT; | ||
1764 | |||
1765 | } | ||
1766 | if (vcs->input == VINO_INPUT_D1) | ||
1767 | ctrl |= VINO_CTRL_B_SELECT; | ||
1768 | else | ||
1769 | ctrl &= ~VINO_CTRL_B_SELECT; | ||
1770 | |||
1771 | ctrl &= ~(VINO_CTRL_B_LUMA_ONLY | VINO_CTRL_B_RGB | | ||
1772 | VINO_CTRL_B_DITHER); | ||
1773 | } | ||
1774 | |||
1775 | /* set palette */ | ||
1776 | fb->data_format = vcs->data_format; | ||
1777 | |||
1778 | switch (vcs->data_format) { | ||
1779 | case VINO_DATA_FMT_GREY: | ||
1780 | ctrl |= (vcs->channel == VINO_CHANNEL_A) ? | ||
1781 | VINO_CTRL_A_LUMA_ONLY : VINO_CTRL_B_LUMA_ONLY; | ||
1782 | break; | ||
1783 | case VINO_DATA_FMT_RGB32: | ||
1784 | ctrl |= (vcs->channel == VINO_CHANNEL_A) ? | ||
1785 | VINO_CTRL_A_RGB : VINO_CTRL_B_RGB; | ||
1786 | break; | ||
1787 | case VINO_DATA_FMT_YUV: | ||
1788 | /* nothing needs to be done */ | ||
1789 | break; | ||
1790 | case VINO_DATA_FMT_RGB332: | ||
1791 | ctrl |= (vcs->channel == VINO_CHANNEL_A) ? | ||
1792 | VINO_CTRL_A_RGB | VINO_CTRL_A_DITHER : | ||
1793 | VINO_CTRL_B_RGB | VINO_CTRL_B_DITHER; | ||
1794 | break; | ||
1795 | } | ||
1796 | |||
1797 | vino->intr_status = intr; | ||
1798 | vino->control = ctrl; | ||
1799 | |||
1800 | return 0; | ||
1801 | } | ||
1802 | |||
1803 | /* (execute only with vino_lock locked) */ | ||
1804 | static void vino_dma_start(struct vino_channel_settings *vcs) | ||
1805 | { | ||
1806 | u32 ctrl = vino->control; | ||
1807 | |||
1808 | dprintk("vino_dma_start():\n"); | ||
1809 | ctrl |= (vcs->channel == VINO_CHANNEL_A) ? | ||
1810 | VINO_CTRL_A_DMA_ENBL : VINO_CTRL_B_DMA_ENBL; | ||
1811 | vino->control = ctrl; | ||
1812 | } | ||
1813 | |||
1814 | /* (execute only with vino_lock locked) */ | ||
1815 | static void vino_dma_stop(struct vino_channel_settings *vcs) | ||
1816 | { | ||
1817 | u32 ctrl = vino->control; | ||
1818 | |||
1819 | ctrl &= (vcs->channel == VINO_CHANNEL_A) ? | ||
1820 | ~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL; | ||
1821 | vino->control = ctrl; | ||
1822 | dprintk("vino_dma_stop():\n"); | ||
1823 | } | ||
1824 | |||
1825 | /* | ||
1826 | * Load dummy page to descriptor registers. This prevents generating of | ||
1827 | * spurious interrupts. (execute only with vino_lock locked) | ||
1828 | */ | ||
1829 | static void vino_clear_interrupt(struct vino_channel_settings *vcs) | ||
1830 | { | ||
1831 | struct sgi_vino_channel *ch; | ||
1832 | |||
1833 | ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b; | ||
1834 | |||
1835 | ch->page_index = 0; | ||
1836 | ch->line_count = 0; | ||
1837 | |||
1838 | ch->start_desc_tbl = vino_drvdata->dummy_desc_table.dma; | ||
1839 | ch->next_4_desc = vino_drvdata->dummy_desc_table.dma; | ||
1840 | |||
1841 | udelay(VINO_DESC_FETCH_DELAY); | ||
1842 | dprintk("channel %c clear interrupt condition\n", | ||
1843 | (vcs->channel == VINO_CHANNEL_A) ? 'A':'B'); | ||
1844 | } | ||
1845 | |||
1846 | static int vino_capture(struct vino_channel_settings *vcs, | ||
1847 | struct vino_framebuffer *fb) | ||
1848 | { | ||
1849 | int err = 0; | ||
1850 | unsigned long flags, flags2; | ||
1851 | |||
1852 | spin_lock_irqsave(&fb->state_lock, flags); | ||
1853 | |||
1854 | if (fb->state == VINO_FRAMEBUFFER_IN_USE) | ||
1855 | err = -EBUSY; | ||
1856 | fb->state = VINO_FRAMEBUFFER_IN_USE; | ||
1857 | |||
1858 | spin_unlock_irqrestore(&fb->state_lock, flags); | ||
1859 | |||
1860 | if (err) | ||
1861 | return err; | ||
1862 | |||
1863 | spin_lock_irqsave(&vino_drvdata->vino_lock, flags); | ||
1864 | spin_lock_irqsave(&vino_drvdata->input_lock, flags2); | ||
1865 | |||
1866 | vino_dma_setup(vcs, fb); | ||
1867 | vino_dma_start(vcs); | ||
1868 | |||
1869 | spin_unlock_irqrestore(&vino_drvdata->input_lock, flags2); | ||
1870 | spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags); | ||
1871 | |||
1872 | return err; | ||
1873 | } | ||
1874 | |||
1875 | static | ||
1876 | struct vino_framebuffer *vino_capture_enqueue(struct | ||
1877 | vino_channel_settings *vcs, | ||
1878 | unsigned int index) | ||
1879 | { | ||
1880 | struct vino_framebuffer *fb; | ||
1881 | unsigned long flags; | ||
1882 | |||
1883 | dprintk("vino_capture_enqueue():\n"); | ||
1884 | |||
1885 | spin_lock_irqsave(&vcs->capture_lock, flags); | ||
1886 | |||
1887 | fb = vino_queue_add(&vcs->fb_queue, index); | ||
1888 | if (fb == NULL) { | ||
1889 | dprintk("vino_capture_enqueue(): vino_queue_add() failed, " | ||
1890 | "queue full?\n"); | ||
1891 | goto out; | ||
1892 | } | ||
1893 | out: | ||
1894 | spin_unlock_irqrestore(&vcs->capture_lock, flags); | ||
1895 | |||
1896 | return fb; | ||
1897 | } | ||
1898 | |||
1899 | static int vino_capture_next(struct vino_channel_settings *vcs, int start) | ||
1900 | { | ||
1901 | struct vino_framebuffer *fb; | ||
1902 | unsigned int incoming, id; | ||
1903 | int err = 0; | ||
1904 | unsigned long flags, flags2; | ||
1905 | |||
1906 | dprintk("vino_capture_next():\n"); | ||
1907 | |||
1908 | spin_lock_irqsave(&vcs->capture_lock, flags); | ||
1909 | |||
1910 | if (start) { | ||
1911 | /* start capture only if capture isn't in progress already */ | ||
1912 | if (vcs->capturing) { | ||
1913 | spin_unlock_irqrestore(&vcs->capture_lock, flags); | ||
1914 | return 0; | ||
1915 | } | ||
1916 | |||
1917 | } else { | ||
1918 | /* capture next frame: | ||
1919 | * stop capture if capturing is not set */ | ||
1920 | if (!vcs->capturing) { | ||
1921 | spin_unlock_irqrestore(&vcs->capture_lock, flags); | ||
1922 | return 0; | ||
1923 | } | ||
1924 | } | ||
1925 | |||
1926 | err = vino_queue_get_incoming(&vcs->fb_queue, &incoming); | ||
1927 | if (err) { | ||
1928 | dprintk("vino_capture_next(): vino_queue_get_incoming() " | ||
1929 | "failed\n"); | ||
1930 | err = -EINVAL; | ||
1931 | goto out; | ||
1932 | } | ||
1933 | if (incoming == 0) { | ||
1934 | dprintk("vino_capture_next(): no buffers available\n"); | ||
1935 | goto out; | ||
1936 | } | ||
1937 | |||
1938 | fb = vino_queue_peek(&vcs->fb_queue, &id); | ||
1939 | if (fb == NULL) { | ||
1940 | dprintk("vino_capture_next(): vino_queue_peek() failed\n"); | ||
1941 | err = -EINVAL; | ||
1942 | goto out; | ||
1943 | } | ||
1944 | |||
1945 | spin_lock_irqsave(&fb->state_lock, flags2); | ||
1946 | fb->state = VINO_FRAMEBUFFER_UNUSED; | ||
1947 | spin_unlock_irqrestore(&fb->state_lock, flags2); | ||
1948 | |||
1949 | if (start) { | ||
1950 | vcs->capturing = 1; | ||
1951 | } | ||
1952 | |||
1953 | spin_unlock_irqrestore(&vcs->capture_lock, flags); | ||
1954 | |||
1955 | err = vino_capture(vcs, fb); | ||
1956 | |||
1957 | return err; | ||
1958 | |||
1959 | out: | ||
1960 | vcs->capturing = 0; | ||
1961 | spin_unlock_irqrestore(&vcs->capture_lock, flags); | ||
1962 | |||
1963 | return err; | ||
1964 | } | ||
1965 | |||
1966 | static int vino_is_capturing(struct vino_channel_settings *vcs) | ||
1967 | { | ||
1968 | int ret; | ||
1969 | unsigned long flags; | ||
1970 | |||
1971 | spin_lock_irqsave(&vcs->capture_lock, flags); | ||
1972 | |||
1973 | ret = vcs->capturing; | ||
1974 | |||
1975 | spin_unlock_irqrestore(&vcs->capture_lock, flags); | ||
1976 | |||
1977 | return ret; | ||
1978 | } | ||
1979 | |||
1980 | /* waits until a frame is captured */ | ||
1981 | static int vino_wait_for_frame(struct vino_channel_settings *vcs) | ||
1982 | { | ||
1983 | wait_queue_t wait; | ||
1984 | int err = 0; | ||
1985 | |||
1986 | dprintk("vino_wait_for_frame():\n"); | ||
1987 | |||
1988 | init_waitqueue_entry(&wait, current); | ||
1989 | /* add ourselves into wait queue */ | ||
1990 | add_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait); | ||
1991 | /* and set current state */ | ||
1992 | set_current_state(TASK_INTERRUPTIBLE); | ||
1993 | |||
1994 | /* to ensure that schedule_timeout will return immediately | ||
1995 | * if VINO interrupt was triggred meanwhile */ | ||
1996 | schedule_timeout(HZ / 10); | ||
1997 | |||
1998 | if (signal_pending(current)) | ||
1999 | err = -EINTR; | ||
2000 | |||
2001 | remove_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait); | ||
2002 | |||
2003 | dprintk("vino_wait_for_frame(): waiting for frame %s\n", | ||
2004 | err ? "failed" : "ok"); | ||
2005 | |||
2006 | return err; | ||
2007 | } | ||
2008 | |||
2009 | /* the function assumes that PAGE_SIZE % 4 == 0 */ | ||
2010 | static void vino_convert_to_rgba(struct vino_framebuffer *fb) { | ||
2011 | unsigned char *pageptr; | ||
2012 | unsigned int page, i; | ||
2013 | unsigned char a; | ||
2014 | |||
2015 | for (page = 0; page < fb->desc_table.page_count; page++) { | ||
2016 | pageptr = (unsigned char *)fb->desc_table.virtual[page]; | ||
2017 | |||
2018 | for (i = 0; i < PAGE_SIZE; i += 4) { | ||
2019 | a = pageptr[0]; | ||
2020 | pageptr[0] = pageptr[3]; | ||
2021 | pageptr[1] = pageptr[2]; | ||
2022 | pageptr[2] = pageptr[1]; | ||
2023 | pageptr[3] = a; | ||
2024 | pageptr += 4; | ||
2025 | } | ||
2026 | } | ||
2027 | } | ||
2028 | |||
2029 | /* checks if the buffer is in correct state and syncs data */ | ||
2030 | static int vino_check_buffer(struct vino_channel_settings *vcs, | ||
2031 | struct vino_framebuffer *fb) | ||
2032 | { | ||
2033 | int err = 0; | ||
2034 | unsigned long flags; | ||
2035 | |||
2036 | dprintk("vino_check_buffer():\n"); | ||
2037 | |||
2038 | spin_lock_irqsave(&fb->state_lock, flags); | ||
2039 | switch (fb->state) { | ||
2040 | case VINO_FRAMEBUFFER_IN_USE: | ||
2041 | err = -EIO; | ||
2042 | break; | ||
2043 | case VINO_FRAMEBUFFER_READY: | ||
2044 | vino_sync_buffer(fb); | ||
2045 | fb->state = VINO_FRAMEBUFFER_UNUSED; | ||
2046 | break; | ||
2047 | default: | ||
2048 | err = -EINVAL; | ||
2049 | } | ||
2050 | spin_unlock_irqrestore(&fb->state_lock, flags); | ||
2051 | |||
2052 | if (!err) { | ||
2053 | if (vino_pixel_conversion | ||
2054 | && (fb->data_format == VINO_DATA_FMT_RGB32)) { | ||
2055 | vino_convert_to_rgba(fb); | ||
2056 | } | ||
2057 | } else if (err && (err != -EINVAL)) { | ||
2058 | dprintk("vino_check_buffer(): buffer not ready\n"); | ||
2059 | |||
2060 | spin_lock_irqsave(&vino_drvdata->vino_lock, flags); | ||
2061 | vino_dma_stop(vcs); | ||
2062 | vino_clear_interrupt(vcs); | ||
2063 | spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags); | ||
2064 | } | ||
2065 | |||
2066 | return err; | ||
2067 | } | ||
2068 | |||
2069 | /* forcefully terminates capture */ | ||
2070 | static void vino_capture_stop(struct vino_channel_settings *vcs) | ||
2071 | { | ||
2072 | unsigned int incoming = 0, outgoing = 0, id; | ||
2073 | unsigned long flags, flags2; | ||
2074 | |||
2075 | dprintk("vino_capture_stop():\n"); | ||
2076 | |||
2077 | spin_lock_irqsave(&vcs->capture_lock, flags); | ||
2078 | /* unset capturing to stop queue processing */ | ||
2079 | vcs->capturing = 0; | ||
2080 | |||
2081 | spin_lock_irqsave(&vino_drvdata->vino_lock, flags2); | ||
2082 | |||
2083 | vino_dma_stop(vcs); | ||
2084 | vino_clear_interrupt(vcs); | ||
2085 | |||
2086 | spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags2); | ||
2087 | |||
2088 | /* remove all items from the queue */ | ||
2089 | if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) { | ||
2090 | dprintk("vino_capture_stop(): " | ||
2091 | "vino_queue_get_incoming() failed\n"); | ||
2092 | goto out; | ||
2093 | } | ||
2094 | while (incoming > 0) { | ||
2095 | vino_queue_transfer(&vcs->fb_queue); | ||
2096 | |||
2097 | if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) { | ||
2098 | dprintk("vino_capture_stop(): " | ||
2099 | "vino_queue_get_incoming() failed\n"); | ||
2100 | goto out; | ||
2101 | } | ||
2102 | } | ||
2103 | |||
2104 | if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) { | ||
2105 | dprintk("vino_capture_stop(): " | ||
2106 | "vino_queue_get_outgoing() failed\n"); | ||
2107 | goto out; | ||
2108 | } | ||
2109 | while (outgoing > 0) { | ||
2110 | vino_queue_remove(&vcs->fb_queue, &id); | ||
2111 | |||
2112 | if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) { | ||
2113 | dprintk("vino_capture_stop(): " | ||
2114 | "vino_queue_get_outgoing() failed\n"); | ||
2115 | goto out; | ||
2116 | } | ||
2117 | } | ||
2118 | |||
2119 | out: | ||
2120 | spin_unlock_irqrestore(&vcs->capture_lock, flags); | ||
2121 | } | ||
2122 | |||
2123 | static int vino_capture_failed(struct vino_channel_settings *vcs) | ||
2124 | { | ||
2125 | struct vino_framebuffer *fb; | ||
2126 | unsigned long flags; | ||
2127 | unsigned int i; | ||
2128 | int ret; | ||
2129 | |||
2130 | dprintk("vino_capture_failed():\n"); | ||
2131 | |||
2132 | spin_lock_irqsave(&vino_drvdata->vino_lock, flags); | ||
2133 | |||
2134 | vino_dma_stop(vcs); | ||
2135 | vino_clear_interrupt(vcs); | ||
2136 | |||
2137 | spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags); | ||
2138 | |||
2139 | ret = vino_queue_get_incoming(&vcs->fb_queue, &i); | ||
2140 | if (ret == VINO_QUEUE_ERROR) { | ||
2141 | dprintk("vino_queue_get_incoming() failed\n"); | ||
2142 | return -EINVAL; | ||
2143 | } | ||
2144 | if (i == 0) { | ||
2145 | /* no buffers to process */ | ||
2146 | return 0; | ||
2147 | } | ||
2148 | |||
2149 | fb = vino_queue_peek(&vcs->fb_queue, &i); | ||
2150 | if (fb == NULL) { | ||
2151 | dprintk("vino_queue_peek() failed\n"); | ||
2152 | return -EINVAL; | ||
2153 | } | ||
2154 | |||
2155 | spin_lock_irqsave(&fb->state_lock, flags); | ||
2156 | if (fb->state == VINO_FRAMEBUFFER_IN_USE) { | ||
2157 | fb->state = VINO_FRAMEBUFFER_UNUSED; | ||
2158 | vino_queue_transfer(&vcs->fb_queue); | ||
2159 | vino_queue_remove(&vcs->fb_queue, &i); | ||
2160 | /* we should actually discard the newest frame, | ||
2161 | * but who cares ... */ | ||
2162 | } | ||
2163 | spin_unlock_irqrestore(&fb->state_lock, flags); | ||
2164 | |||
2165 | return 0; | ||
2166 | } | ||
2167 | |||
2168 | static void vino_frame_done(struct vino_channel_settings *vcs, | ||
2169 | unsigned int fc) | ||
2170 | { | ||
2171 | struct vino_framebuffer *fb; | ||
2172 | unsigned long flags; | ||
2173 | |||
2174 | spin_lock_irqsave(&vcs->capture_lock, flags); | ||
2175 | fb = vino_queue_transfer(&vcs->fb_queue); | ||
2176 | if (!fb) { | ||
2177 | spin_unlock_irqrestore(&vcs->capture_lock, flags); | ||
2178 | dprintk("vino_frame_done(): vino_queue_transfer() failed!\n"); | ||
2179 | return; | ||
2180 | } | ||
2181 | spin_unlock_irqrestore(&vcs->capture_lock, flags); | ||
2182 | |||
2183 | fb->frame_counter = fc; | ||
2184 | do_gettimeofday(&fb->timestamp); | ||
2185 | |||
2186 | spin_lock_irqsave(&fb->state_lock, flags); | ||
2187 | if (fb->state == VINO_FRAMEBUFFER_IN_USE) | ||
2188 | fb->state = VINO_FRAMEBUFFER_READY; | ||
2189 | spin_unlock_irqrestore(&fb->state_lock, flags); | ||
2190 | |||
2191 | wake_up(&vcs->fb_queue.frame_wait_queue); | ||
2192 | |||
2193 | vino_capture_next(vcs, 0); | ||
2194 | } | ||
2195 | |||
2196 | static irqreturn_t vino_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
2197 | { | ||
2198 | u32 intr; | ||
2199 | unsigned int fc_a, fc_b; | ||
2200 | int done_a = 0; | ||
2201 | int done_b = 0; | ||
2202 | |||
2203 | spin_lock(&vino_drvdata->vino_lock); | ||
2204 | |||
2205 | intr = vino->intr_status; | ||
2206 | fc_a = vino->a.field_counter / 2; | ||
2207 | fc_b = vino->b.field_counter / 2; | ||
2208 | |||
2209 | // TODO: handle error-interrupts in some special way ? | ||
2210 | |||
2211 | if (intr & VINO_INTSTAT_A) { | ||
2212 | if (intr & VINO_INTSTAT_A_EOF) { | ||
2213 | vino_drvdata->a.field++; | ||
2214 | if (vino_drvdata->a.field > 1) { | ||
2215 | vino_dma_stop(&vino_drvdata->a); | ||
2216 | vino_clear_interrupt(&vino_drvdata->a); | ||
2217 | vino_drvdata->a.field = 0; | ||
2218 | done_a = 1; | ||
2219 | } | ||
2220 | dprintk("intr: channel A end-of-field interrupt: " | ||
2221 | "%04x\n", intr); | ||
2222 | } else { | ||
2223 | vino_dma_stop(&vino_drvdata->a); | ||
2224 | vino_clear_interrupt(&vino_drvdata->a); | ||
2225 | done_a = 1; | ||
2226 | dprintk("channel A error interrupt: %04x\n", intr); | ||
2227 | } | ||
2228 | } | ||
2229 | if (intr & VINO_INTSTAT_B) { | ||
2230 | if (intr & VINO_INTSTAT_B_EOF) { | ||
2231 | vino_drvdata->b.field++; | ||
2232 | if (vino_drvdata->b.field > 1) { | ||
2233 | vino_dma_stop(&vino_drvdata->b); | ||
2234 | vino_clear_interrupt(&vino_drvdata->b); | ||
2235 | vino_drvdata->b.field = 0; | ||
2236 | done_b = 1; | ||
2237 | } | ||
2238 | dprintk("intr: channel B end-of-field interrupt: " | ||
2239 | "%04x\n", intr); | ||
2240 | } else { | ||
2241 | vino_dma_stop(&vino_drvdata->b); | ||
2242 | vino_clear_interrupt(&vino_drvdata->b); | ||
2243 | done_b = 1; | ||
2244 | dprintk("channel B error interrupt: %04x\n", intr); | ||
2245 | } | ||
2246 | } | ||
2247 | |||
2248 | /* always remember to clear interrupt status */ | ||
2249 | vino->intr_status = ~intr; | ||
2250 | |||
2251 | spin_unlock(&vino_drvdata->vino_lock); | ||
2252 | |||
2253 | if (done_a) { | ||
2254 | vino_frame_done(&vino_drvdata->a, fc_a); | ||
2255 | dprintk("channel A frame done, interrupt: %d\n", intr); | ||
2256 | } | ||
2257 | if (done_b) { | ||
2258 | vino_frame_done(&vino_drvdata->b, fc_b); | ||
2259 | dprintk("channel B frame done, interrupt: %d\n", intr); | ||
2260 | } | ||
207 | 2261 | ||
208 | return -EINVAL; | 2262 | return IRQ_HANDLED; |
209 | } | 2263 | } |
210 | 2264 | ||
211 | static const struct video_device vino_device = { | 2265 | /* VINO video input management */ |
2266 | |||
2267 | static int vino_get_saa7191_input(int input) | ||
2268 | { | ||
2269 | switch (input) { | ||
2270 | case VINO_INPUT_COMPOSITE: | ||
2271 | return SAA7191_INPUT_COMPOSITE; | ||
2272 | case VINO_INPUT_SVIDEO: | ||
2273 | return SAA7191_INPUT_SVIDEO; | ||
2274 | default: | ||
2275 | printk(KERN_ERR "VINO: vino_get_saa7191_input(): " | ||
2276 | "invalid input!\n"); | ||
2277 | return -1; | ||
2278 | } | ||
2279 | } | ||
2280 | |||
2281 | static int vino_get_saa7191_norm(int norm) | ||
2282 | { | ||
2283 | switch (norm) { | ||
2284 | case VINO_DATA_NORM_AUTO: | ||
2285 | return SAA7191_NORM_AUTO; | ||
2286 | case VINO_DATA_NORM_PAL: | ||
2287 | return SAA7191_NORM_PAL; | ||
2288 | case VINO_DATA_NORM_NTSC: | ||
2289 | return SAA7191_NORM_NTSC; | ||
2290 | case VINO_DATA_NORM_SECAM: | ||
2291 | return SAA7191_NORM_SECAM; | ||
2292 | default: | ||
2293 | printk(KERN_ERR "VINO: vino_get_saa7191_norm(): " | ||
2294 | "invalid norm!\n"); | ||
2295 | return -1; | ||
2296 | } | ||
2297 | } | ||
2298 | |||
2299 | /* execute with input_lock locked */ | ||
2300 | static int vino_is_input_owner(struct vino_channel_settings *vcs) | ||
2301 | { | ||
2302 | switch(vcs->input) { | ||
2303 | case VINO_INPUT_COMPOSITE: | ||
2304 | case VINO_INPUT_SVIDEO: | ||
2305 | return (vino_drvdata->decoder.owner == vcs->channel); | ||
2306 | case VINO_INPUT_D1: | ||
2307 | return (vino_drvdata->camera.owner == vcs->channel); | ||
2308 | default: | ||
2309 | return 0; | ||
2310 | } | ||
2311 | } | ||
2312 | |||
2313 | static int vino_acquire_input(struct vino_channel_settings *vcs) | ||
2314 | { | ||
2315 | int ret = 0; | ||
2316 | |||
2317 | dprintk("vino_acquire_input():\n"); | ||
2318 | |||
2319 | spin_lock(&vino_drvdata->input_lock); | ||
2320 | |||
2321 | /* First try D1 and then SAA7191 */ | ||
2322 | if (vino_drvdata->camera.driver | ||
2323 | && (vino_drvdata->camera.owner == VINO_NO_CHANNEL)) { | ||
2324 | if (i2c_use_client(vino_drvdata->camera.driver)) { | ||
2325 | ret = -ENODEV; | ||
2326 | goto out; | ||
2327 | } | ||
2328 | |||
2329 | vino_drvdata->camera.owner = vcs->channel; | ||
2330 | vcs->input = VINO_INPUT_D1; | ||
2331 | vcs->data_norm = VINO_DATA_NORM_D1; | ||
2332 | } else if (vino_drvdata->decoder.driver | ||
2333 | && (vino_drvdata->decoder.owner == VINO_NO_CHANNEL)) { | ||
2334 | int saa7191_input; | ||
2335 | int saa7191_norm; | ||
2336 | |||
2337 | if (i2c_use_client(vino_drvdata->decoder.driver)) { | ||
2338 | ret = -ENODEV; | ||
2339 | goto out; | ||
2340 | } | ||
2341 | |||
2342 | vino_drvdata->decoder.owner = vcs->channel; | ||
2343 | vcs->input = VINO_INPUT_COMPOSITE; | ||
2344 | vcs->data_norm = VINO_DATA_NORM_PAL; | ||
2345 | |||
2346 | saa7191_input = vino_get_saa7191_input(vcs->input); | ||
2347 | i2c_decoder_command(DECODER_SET_INPUT, &saa7191_input); | ||
2348 | |||
2349 | saa7191_norm = vino_get_saa7191_norm(vcs->data_norm); | ||
2350 | i2c_decoder_command(DECODER_SAA7191_SET_NORM, &saa7191_norm); | ||
2351 | } else { | ||
2352 | vcs->input = (vcs->channel == VINO_CHANNEL_A) ? | ||
2353 | vino_drvdata->b.input : vino_drvdata->a.input; | ||
2354 | vcs->data_norm = (vcs->channel == VINO_CHANNEL_A) ? | ||
2355 | vino_drvdata->b.data_norm : vino_drvdata->a.data_norm; | ||
2356 | } | ||
2357 | |||
2358 | if (vcs->input == VINO_INPUT_NONE) { | ||
2359 | ret = -ENODEV; | ||
2360 | goto out; | ||
2361 | } | ||
2362 | |||
2363 | if (vino_is_input_owner(vcs)) { | ||
2364 | vino_set_default_clipping(vcs); | ||
2365 | vino_set_default_framerate(vcs); | ||
2366 | } | ||
2367 | |||
2368 | dprintk("vino_acquire_input(): %s\n", vino_inputs[vcs->input].name); | ||
2369 | |||
2370 | out: | ||
2371 | spin_unlock(&vino_drvdata->input_lock); | ||
2372 | |||
2373 | return ret; | ||
2374 | } | ||
2375 | |||
2376 | static int vino_set_input(struct vino_channel_settings *vcs, int input) | ||
2377 | { | ||
2378 | struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ? | ||
2379 | &vino_drvdata->b : &vino_drvdata->a; | ||
2380 | int ret = 0; | ||
2381 | |||
2382 | dprintk("vino_set_input():\n"); | ||
2383 | |||
2384 | spin_lock(&vino_drvdata->input_lock); | ||
2385 | |||
2386 | if (vcs->input == input) | ||
2387 | goto out; | ||
2388 | |||
2389 | switch(input) { | ||
2390 | case VINO_INPUT_COMPOSITE: | ||
2391 | case VINO_INPUT_SVIDEO: | ||
2392 | if (!vino_drvdata->decoder.driver) { | ||
2393 | ret = -EINVAL; | ||
2394 | goto out; | ||
2395 | } | ||
2396 | |||
2397 | if (vino_drvdata->decoder.owner == VINO_NO_CHANNEL) { | ||
2398 | if (i2c_use_client(vino_drvdata->decoder.driver)) { | ||
2399 | ret = -ENODEV; | ||
2400 | goto out; | ||
2401 | } | ||
2402 | vino_drvdata->decoder.owner = vcs->channel; | ||
2403 | } | ||
2404 | |||
2405 | if (vino_drvdata->decoder.owner == vcs->channel) { | ||
2406 | int saa7191_input; | ||
2407 | int saa7191_norm; | ||
2408 | |||
2409 | vcs->input = input; | ||
2410 | vcs->data_norm = VINO_DATA_NORM_PAL; | ||
2411 | |||
2412 | saa7191_input = vino_get_saa7191_input(vcs->input); | ||
2413 | i2c_decoder_command(DECODER_SET_INPUT, &saa7191_input); | ||
2414 | saa7191_norm = vino_get_saa7191_norm(vcs->data_norm); | ||
2415 | i2c_decoder_command(DECODER_SAA7191_SET_NORM, | ||
2416 | &saa7191_norm); | ||
2417 | } else { | ||
2418 | if (vcs2->input != input) { | ||
2419 | ret = -EBUSY; | ||
2420 | goto out; | ||
2421 | } | ||
2422 | |||
2423 | vcs->input = input; | ||
2424 | vcs->data_norm = vcs2->data_norm; | ||
2425 | } | ||
2426 | |||
2427 | if (vino_drvdata->camera.owner == vcs->channel) { | ||
2428 | /* Transfer the ownership or release the input */ | ||
2429 | if (vcs2->input == VINO_INPUT_D1) { | ||
2430 | vino_drvdata->camera.owner = vcs2->channel; | ||
2431 | } else { | ||
2432 | i2c_release_client(vino_drvdata-> | ||
2433 | camera.driver); | ||
2434 | vino_drvdata->camera.owner = VINO_NO_CHANNEL; | ||
2435 | } | ||
2436 | } | ||
2437 | break; | ||
2438 | case VINO_INPUT_D1: | ||
2439 | if (!vino_drvdata->camera.driver) { | ||
2440 | ret = -EINVAL; | ||
2441 | goto out; | ||
2442 | } | ||
2443 | |||
2444 | if (vino_drvdata->camera.owner == VINO_NO_CHANNEL) { | ||
2445 | if (i2c_use_client(vino_drvdata->camera.driver)) { | ||
2446 | ret = -ENODEV; | ||
2447 | goto out; | ||
2448 | } | ||
2449 | vino_drvdata->camera.owner = vcs->channel; | ||
2450 | } | ||
2451 | |||
2452 | if (vino_drvdata->decoder.owner == vcs->channel) { | ||
2453 | /* Transfer the ownership or release the input */ | ||
2454 | if ((vcs2->input == VINO_INPUT_COMPOSITE) || | ||
2455 | (vcs2->input == VINO_INPUT_SVIDEO)) { | ||
2456 | vino_drvdata->decoder.owner = vcs2->channel; | ||
2457 | } else { | ||
2458 | i2c_release_client(vino_drvdata-> | ||
2459 | decoder.driver); | ||
2460 | vino_drvdata->decoder.owner = VINO_NO_CHANNEL; | ||
2461 | } | ||
2462 | } | ||
2463 | |||
2464 | vcs->input = input; | ||
2465 | vcs->data_norm = VINO_DATA_NORM_D1; | ||
2466 | break; | ||
2467 | default: | ||
2468 | ret = -EINVAL; | ||
2469 | goto out; | ||
2470 | } | ||
2471 | |||
2472 | vino_set_default_clipping(vcs); | ||
2473 | vino_set_default_framerate(vcs); | ||
2474 | |||
2475 | dprintk("vino_set_input(): %s\n", vino_inputs[vcs->input].name); | ||
2476 | |||
2477 | out: | ||
2478 | spin_unlock(&vino_drvdata->input_lock); | ||
2479 | |||
2480 | return ret; | ||
2481 | } | ||
2482 | |||
2483 | static void vino_release_input(struct vino_channel_settings *vcs) | ||
2484 | { | ||
2485 | struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ? | ||
2486 | &vino_drvdata->b : &vino_drvdata->a; | ||
2487 | |||
2488 | dprintk("vino_release_input():\n"); | ||
2489 | |||
2490 | spin_lock(&vino_drvdata->input_lock); | ||
2491 | |||
2492 | /* Release ownership of the channel | ||
2493 | * and if the other channel takes input from | ||
2494 | * the same source, transfer the ownership */ | ||
2495 | if (vino_drvdata->camera.owner == vcs->channel) { | ||
2496 | if (vcs2->input == VINO_INPUT_D1) { | ||
2497 | vino_drvdata->camera.owner = vcs2->channel; | ||
2498 | } else { | ||
2499 | i2c_release_client(vino_drvdata->camera.driver); | ||
2500 | vino_drvdata->camera.owner = VINO_NO_CHANNEL; | ||
2501 | } | ||
2502 | } else if (vino_drvdata->decoder.owner == vcs->channel) { | ||
2503 | if ((vcs2->input == VINO_INPUT_COMPOSITE) || | ||
2504 | (vcs2->input == VINO_INPUT_SVIDEO)) { | ||
2505 | vino_drvdata->decoder.owner = vcs2->channel; | ||
2506 | } else { | ||
2507 | i2c_release_client(vino_drvdata->decoder.driver); | ||
2508 | vino_drvdata->decoder.owner = VINO_NO_CHANNEL; | ||
2509 | } | ||
2510 | } | ||
2511 | vcs->input = VINO_INPUT_NONE; | ||
2512 | |||
2513 | spin_unlock(&vino_drvdata->input_lock); | ||
2514 | } | ||
2515 | |||
2516 | /* execute with input_lock locked */ | ||
2517 | static int vino_set_data_norm(struct vino_channel_settings *vcs, | ||
2518 | unsigned int data_norm) | ||
2519 | { | ||
2520 | int saa7191_norm; | ||
2521 | |||
2522 | switch (vcs->input) { | ||
2523 | case VINO_INPUT_D1: | ||
2524 | /* only one "norm" supported */ | ||
2525 | if (data_norm != VINO_DATA_NORM_D1) | ||
2526 | return -EINVAL; | ||
2527 | break; | ||
2528 | case VINO_INPUT_COMPOSITE: | ||
2529 | case VINO_INPUT_SVIDEO: | ||
2530 | |||
2531 | saa7191_norm = vino_get_saa7191_norm(data_norm); | ||
2532 | |||
2533 | i2c_decoder_command(DECODER_SAA7191_SET_NORM, &saa7191_norm); | ||
2534 | vcs->data_norm = data_norm; | ||
2535 | break; | ||
2536 | default: | ||
2537 | return -EINVAL; | ||
2538 | } | ||
2539 | |||
2540 | return 0; | ||
2541 | } | ||
2542 | |||
2543 | /* V4L2 helper functions */ | ||
2544 | |||
2545 | static int vino_find_data_format(__u32 pixelformat) | ||
2546 | { | ||
2547 | int i; | ||
2548 | |||
2549 | for (i = 0; i < VINO_DATA_FMT_COUNT; i++) { | ||
2550 | if (vino_data_formats[i].pixelformat == pixelformat) | ||
2551 | return i; | ||
2552 | } | ||
2553 | |||
2554 | return VINO_DATA_FMT_NONE; | ||
2555 | } | ||
2556 | |||
2557 | static int vino_enum_data_norm(struct vino_channel_settings *vcs, __u32 index) | ||
2558 | { | ||
2559 | int data_norm = VINO_DATA_NORM_NONE; | ||
2560 | |||
2561 | spin_lock(&vino_drvdata->input_lock); | ||
2562 | switch(vcs->input) { | ||
2563 | case VINO_INPUT_COMPOSITE: | ||
2564 | case VINO_INPUT_SVIDEO: | ||
2565 | if (index == 0) { | ||
2566 | data_norm = VINO_DATA_NORM_PAL; | ||
2567 | } else if (index == 1) { | ||
2568 | data_norm = VINO_DATA_NORM_NTSC; | ||
2569 | } else if (index == 2) { | ||
2570 | data_norm = VINO_DATA_NORM_SECAM; | ||
2571 | } | ||
2572 | break; | ||
2573 | case VINO_INPUT_D1: | ||
2574 | if (index == 0) { | ||
2575 | data_norm = VINO_DATA_NORM_D1; | ||
2576 | } | ||
2577 | break; | ||
2578 | } | ||
2579 | spin_unlock(&vino_drvdata->input_lock); | ||
2580 | |||
2581 | return data_norm; | ||
2582 | } | ||
2583 | |||
2584 | static int vino_enum_input(struct vino_channel_settings *vcs, __u32 index) | ||
2585 | { | ||
2586 | int input = VINO_INPUT_NONE; | ||
2587 | |||
2588 | spin_lock(&vino_drvdata->input_lock); | ||
2589 | if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) { | ||
2590 | switch (index) { | ||
2591 | case 0: | ||
2592 | input = VINO_INPUT_COMPOSITE; | ||
2593 | break; | ||
2594 | case 1: | ||
2595 | input = VINO_INPUT_SVIDEO; | ||
2596 | break; | ||
2597 | case 2: | ||
2598 | input = VINO_INPUT_D1; | ||
2599 | break; | ||
2600 | } | ||
2601 | } else if (vino_drvdata->decoder.driver) { | ||
2602 | switch (index) { | ||
2603 | case 0: | ||
2604 | input = VINO_INPUT_COMPOSITE; | ||
2605 | break; | ||
2606 | case 1: | ||
2607 | input = VINO_INPUT_SVIDEO; | ||
2608 | break; | ||
2609 | } | ||
2610 | } else if (vino_drvdata->camera.driver) { | ||
2611 | switch (index) { | ||
2612 | case 0: | ||
2613 | input = VINO_INPUT_D1; | ||
2614 | break; | ||
2615 | } | ||
2616 | } | ||
2617 | spin_unlock(&vino_drvdata->input_lock); | ||
2618 | |||
2619 | return input; | ||
2620 | } | ||
2621 | |||
2622 | /* execute with input_lock locked */ | ||
2623 | static __u32 vino_find_input_index(struct vino_channel_settings *vcs) | ||
2624 | { | ||
2625 | __u32 index = 0; | ||
2626 | // FIXME: detect when no inputs available | ||
2627 | |||
2628 | if (vino_drvdata->decoder.driver && vino_drvdata->camera.driver) { | ||
2629 | switch (vcs->input) { | ||
2630 | case VINO_INPUT_COMPOSITE: | ||
2631 | index = 0; | ||
2632 | break; | ||
2633 | case VINO_INPUT_SVIDEO: | ||
2634 | index = 1; | ||
2635 | break; | ||
2636 | case VINO_INPUT_D1: | ||
2637 | index = 2; | ||
2638 | break; | ||
2639 | } | ||
2640 | } else if (vino_drvdata->decoder.driver) { | ||
2641 | switch (vcs->input) { | ||
2642 | case VINO_INPUT_COMPOSITE: | ||
2643 | index = 0; | ||
2644 | break; | ||
2645 | case VINO_INPUT_SVIDEO: | ||
2646 | index = 1; | ||
2647 | break; | ||
2648 | } | ||
2649 | } else if (vino_drvdata->camera.driver) { | ||
2650 | switch (vcs->input) { | ||
2651 | case VINO_INPUT_D1: | ||
2652 | index = 0; | ||
2653 | break; | ||
2654 | } | ||
2655 | } | ||
2656 | |||
2657 | return index; | ||
2658 | } | ||
2659 | |||
2660 | /* V4L2 ioctls */ | ||
2661 | |||
2662 | static void vino_v4l2_querycap(struct v4l2_capability *cap) | ||
2663 | { | ||
2664 | memset(cap, 0, sizeof(struct v4l2_capability)); | ||
2665 | |||
2666 | strcpy(cap->driver, vino_driver_name); | ||
2667 | strcpy(cap->card, vino_driver_description); | ||
2668 | strcpy(cap->bus_info, vino_bus_name); | ||
2669 | cap->version = VINO_VERSION_CODE; | ||
2670 | cap->capabilities = | ||
2671 | V4L2_CAP_VIDEO_CAPTURE | | ||
2672 | V4L2_CAP_STREAMING; | ||
2673 | // V4L2_CAP_OVERLAY, V4L2_CAP_READWRITE | ||
2674 | } | ||
2675 | |||
2676 | static int vino_v4l2_enuminput(struct vino_channel_settings *vcs, | ||
2677 | struct v4l2_input *i) | ||
2678 | { | ||
2679 | __u32 index = i->index; | ||
2680 | int input; | ||
2681 | dprintk("requested index = %d\n", index); | ||
2682 | |||
2683 | input = vino_enum_input(vcs, index); | ||
2684 | if (input == VINO_INPUT_NONE) | ||
2685 | return -EINVAL; | ||
2686 | |||
2687 | memset(i, 0, sizeof(struct v4l2_input)); | ||
2688 | |||
2689 | i->index = index; | ||
2690 | i->type = V4L2_INPUT_TYPE_CAMERA; | ||
2691 | i->std = vino_inputs[input].std; | ||
2692 | strcpy(i->name, vino_inputs[input].name); | ||
2693 | |||
2694 | if ((input == VINO_INPUT_COMPOSITE) | ||
2695 | || (input == VINO_INPUT_SVIDEO)) { | ||
2696 | struct saa7191_status status; | ||
2697 | i2c_decoder_command(DECODER_SAA7191_GET_STATUS, &status); | ||
2698 | i->status |= status.signal ? 0 : V4L2_IN_ST_NO_SIGNAL; | ||
2699 | i->status |= status.color ? 0 : V4L2_IN_ST_NO_COLOR; | ||
2700 | } | ||
2701 | |||
2702 | return 0; | ||
2703 | } | ||
2704 | |||
2705 | static int vino_v4l2_g_input(struct vino_channel_settings *vcs, | ||
2706 | struct v4l2_input *i) | ||
2707 | { | ||
2708 | __u32 index; | ||
2709 | int input; | ||
2710 | |||
2711 | spin_lock(&vino_drvdata->input_lock); | ||
2712 | input = vcs->input; | ||
2713 | index = vino_find_input_index(vcs); | ||
2714 | spin_unlock(&vino_drvdata->input_lock); | ||
2715 | |||
2716 | dprintk("input = %d\n", input); | ||
2717 | |||
2718 | if (input == VINO_INPUT_NONE) { | ||
2719 | return -EINVAL; | ||
2720 | } | ||
2721 | |||
2722 | memset(i, 0, sizeof(struct v4l2_input)); | ||
2723 | |||
2724 | i->index = index; | ||
2725 | i->type = V4L2_INPUT_TYPE_CAMERA; | ||
2726 | i->std = vino_inputs[input].std; | ||
2727 | strcpy(i->name, vino_inputs[input].name); | ||
2728 | |||
2729 | return 0; | ||
2730 | } | ||
2731 | |||
2732 | static int vino_v4l2_s_input(struct vino_channel_settings *vcs, | ||
2733 | struct v4l2_input *i) | ||
2734 | { | ||
2735 | int input; | ||
2736 | dprintk("requested input = %d\n", i->index); | ||
2737 | |||
2738 | input = vino_enum_input(vcs, i->index); | ||
2739 | if (input == VINO_INPUT_NONE) | ||
2740 | return -EINVAL; | ||
2741 | |||
2742 | return vino_set_input(vcs, input); | ||
2743 | } | ||
2744 | |||
2745 | static int vino_v4l2_enumstd(struct vino_channel_settings *vcs, | ||
2746 | struct v4l2_standard *s) | ||
2747 | { | ||
2748 | int index = s->index; | ||
2749 | int data_norm = vino_enum_data_norm(vcs, index); | ||
2750 | dprintk("standard index = %d\n", index); | ||
2751 | |||
2752 | if (data_norm == VINO_DATA_NORM_NONE) | ||
2753 | return -EINVAL; | ||
2754 | |||
2755 | dprintk("standard name = %s\n", | ||
2756 | vino_data_norms[data_norm].description); | ||
2757 | |||
2758 | memset(s, 0, sizeof(struct v4l2_standard)); | ||
2759 | s->index = index; | ||
2760 | |||
2761 | s->id = vino_data_norms[data_norm].std; | ||
2762 | s->frameperiod.numerator = 1; | ||
2763 | s->frameperiod.denominator = | ||
2764 | vino_data_norms[data_norm].fps_max; | ||
2765 | s->framelines = | ||
2766 | vino_data_norms[data_norm].framelines; | ||
2767 | strcpy(s->name, | ||
2768 | vino_data_norms[data_norm].description); | ||
2769 | |||
2770 | return 0; | ||
2771 | } | ||
2772 | |||
2773 | static int vino_v4l2_g_std(struct vino_channel_settings *vcs, | ||
2774 | v4l2_std_id *std) | ||
2775 | { | ||
2776 | spin_lock(&vino_drvdata->input_lock); | ||
2777 | dprintk("current standard = %d\n", vcs->data_norm); | ||
2778 | *std = vino_data_norms[vcs->data_norm].std; | ||
2779 | spin_unlock(&vino_drvdata->input_lock); | ||
2780 | |||
2781 | return 0; | ||
2782 | } | ||
2783 | |||
2784 | static int vino_v4l2_s_std(struct vino_channel_settings *vcs, | ||
2785 | v4l2_std_id *std) | ||
2786 | { | ||
2787 | int ret = 0; | ||
2788 | |||
2789 | spin_lock(&vino_drvdata->input_lock); | ||
2790 | |||
2791 | /* check if the standard is valid for the current input */ | ||
2792 | if (vino_is_input_owner(vcs) | ||
2793 | && (vino_inputs[vcs->input].std & (*std))) { | ||
2794 | dprintk("standard accepted\n"); | ||
2795 | |||
2796 | /* change the video norm for SAA7191 | ||
2797 | * and accept NTSC for D1 (do nothing) */ | ||
2798 | |||
2799 | if (vcs->input == VINO_INPUT_D1) | ||
2800 | goto out; | ||
2801 | |||
2802 | if ((*std) & V4L2_STD_PAL) { | ||
2803 | vino_set_data_norm(vcs, VINO_DATA_NORM_PAL); | ||
2804 | vcs->data_norm = VINO_DATA_NORM_PAL; | ||
2805 | } else if ((*std) & V4L2_STD_NTSC) { | ||
2806 | vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC); | ||
2807 | vcs->data_norm = VINO_DATA_NORM_NTSC; | ||
2808 | } else if ((*std) & V4L2_STD_SECAM) { | ||
2809 | vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM); | ||
2810 | vcs->data_norm = VINO_DATA_NORM_SECAM; | ||
2811 | } else { | ||
2812 | ret = -EINVAL; | ||
2813 | } | ||
2814 | } else { | ||
2815 | ret = -EINVAL; | ||
2816 | } | ||
2817 | |||
2818 | out: | ||
2819 | spin_unlock(&vino_drvdata->input_lock); | ||
2820 | |||
2821 | return ret; | ||
2822 | } | ||
2823 | |||
2824 | static int vino_v4l2_enum_fmt(struct vino_channel_settings *vcs, | ||
2825 | struct v4l2_fmtdesc *fd) | ||
2826 | { | ||
2827 | enum v4l2_buf_type type = fd->type; | ||
2828 | int index = fd->index; | ||
2829 | dprintk("format index = %d\n", index); | ||
2830 | |||
2831 | switch (fd->type) { | ||
2832 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
2833 | if ((fd->index < 0) || | ||
2834 | (fd->index >= VINO_DATA_FMT_COUNT)) | ||
2835 | return -EINVAL; | ||
2836 | dprintk("format name = %s\n", | ||
2837 | vino_data_formats[index].description); | ||
2838 | |||
2839 | memset(fd, 0, sizeof(struct v4l2_fmtdesc)); | ||
2840 | fd->index = index; | ||
2841 | fd->type = type; | ||
2842 | fd->pixelformat = vino_data_formats[index].pixelformat; | ||
2843 | strcpy(fd->description, vino_data_formats[index].description); | ||
2844 | break; | ||
2845 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
2846 | default: | ||
2847 | return -EINVAL; | ||
2848 | } | ||
2849 | |||
2850 | return 0; | ||
2851 | } | ||
2852 | |||
2853 | static int vino_v4l2_try_fmt(struct vino_channel_settings *vcs, | ||
2854 | struct v4l2_format *f) | ||
2855 | { | ||
2856 | struct vino_channel_settings tempvcs; | ||
2857 | |||
2858 | switch (f->type) { | ||
2859 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | ||
2860 | struct v4l2_pix_format *pf = &f->fmt.pix; | ||
2861 | |||
2862 | dprintk("requested: w = %d, h = %d\n", | ||
2863 | pf->width, pf->height); | ||
2864 | |||
2865 | spin_lock(&vino_drvdata->input_lock); | ||
2866 | memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings)); | ||
2867 | spin_unlock(&vino_drvdata->input_lock); | ||
2868 | |||
2869 | tempvcs.data_format = vino_find_data_format(pf->pixelformat); | ||
2870 | if (tempvcs.data_format == VINO_DATA_FMT_NONE) { | ||
2871 | tempvcs.data_format = VINO_DATA_FMT_RGB32; | ||
2872 | pf->pixelformat = | ||
2873 | vino_data_formats[tempvcs.data_format]. | ||
2874 | pixelformat; | ||
2875 | } | ||
2876 | |||
2877 | /* data format must be set before clipping/scaling */ | ||
2878 | vino_set_scaling(&tempvcs, pf->width, pf->height); | ||
2879 | |||
2880 | dprintk("data format = %s\n", | ||
2881 | vino_data_formats[tempvcs.data_format].description); | ||
2882 | |||
2883 | pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) / | ||
2884 | tempvcs.decimation; | ||
2885 | pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) / | ||
2886 | tempvcs.decimation; | ||
2887 | |||
2888 | pf->field = V4L2_FIELD_INTERLACED; | ||
2889 | pf->bytesperline = tempvcs.line_size; | ||
2890 | pf->sizeimage = tempvcs.line_size * | ||
2891 | (tempvcs.clipping.bottom - tempvcs.clipping.top) / | ||
2892 | tempvcs.decimation; | ||
2893 | pf->colorspace = | ||
2894 | vino_data_formats[tempvcs.data_format].colorspace; | ||
2895 | |||
2896 | pf->priv = 0; | ||
2897 | break; | ||
2898 | } | ||
2899 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
2900 | default: | ||
2901 | return -EINVAL; | ||
2902 | } | ||
2903 | |||
2904 | return 0; | ||
2905 | } | ||
2906 | |||
2907 | static int vino_v4l2_g_fmt(struct vino_channel_settings *vcs, | ||
2908 | struct v4l2_format *f) | ||
2909 | { | ||
2910 | switch (f->type) { | ||
2911 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | ||
2912 | struct v4l2_pix_format *pf = &f->fmt.pix; | ||
2913 | spin_lock(&vino_drvdata->input_lock); | ||
2914 | |||
2915 | pf->width = (vcs->clipping.right - vcs->clipping.left) / | ||
2916 | vcs->decimation; | ||
2917 | pf->height = (vcs->clipping.bottom - vcs->clipping.top) / | ||
2918 | vcs->decimation; | ||
2919 | pf->pixelformat = | ||
2920 | vino_data_formats[vcs->data_format].pixelformat; | ||
2921 | |||
2922 | pf->field = V4L2_FIELD_INTERLACED; | ||
2923 | pf->bytesperline = vcs->line_size; | ||
2924 | pf->sizeimage = vcs->line_size * | ||
2925 | (vcs->clipping.bottom - vcs->clipping.top) / | ||
2926 | vcs->decimation; | ||
2927 | pf->colorspace = | ||
2928 | vino_data_formats[vcs->data_format].colorspace; | ||
2929 | |||
2930 | pf->priv = 0; | ||
2931 | |||
2932 | spin_unlock(&vino_drvdata->input_lock); | ||
2933 | break; | ||
2934 | } | ||
2935 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
2936 | default: | ||
2937 | return -EINVAL; | ||
2938 | } | ||
2939 | |||
2940 | return 0; | ||
2941 | } | ||
2942 | |||
2943 | static int vino_v4l2_s_fmt(struct vino_channel_settings *vcs, | ||
2944 | struct v4l2_format *f) | ||
2945 | { | ||
2946 | int data_format; | ||
2947 | |||
2948 | switch (f->type) { | ||
2949 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | ||
2950 | struct v4l2_pix_format *pf = &f->fmt.pix; | ||
2951 | spin_lock(&vino_drvdata->input_lock); | ||
2952 | |||
2953 | if (!vino_is_input_owner(vcs)) { | ||
2954 | spin_unlock(&vino_drvdata->input_lock); | ||
2955 | return -EINVAL; | ||
2956 | } | ||
2957 | |||
2958 | data_format = vino_find_data_format(pf->pixelformat); | ||
2959 | if (data_format == VINO_DATA_FMT_NONE) { | ||
2960 | vcs->data_format = VINO_DATA_FMT_RGB32; | ||
2961 | pf->pixelformat = | ||
2962 | vino_data_formats[vcs->data_format]. | ||
2963 | pixelformat; | ||
2964 | } else { | ||
2965 | vcs->data_format = data_format; | ||
2966 | } | ||
2967 | |||
2968 | /* data format must be set before clipping/scaling */ | ||
2969 | vino_set_scaling(vcs, pf->width, pf->height); | ||
2970 | |||
2971 | dprintk("data format = %s\n", | ||
2972 | vino_data_formats[vcs->data_format].description); | ||
2973 | |||
2974 | pf->width = vcs->clipping.right - vcs->clipping.left; | ||
2975 | pf->height = vcs->clipping.bottom - vcs->clipping.top; | ||
2976 | |||
2977 | pf->field = V4L2_FIELD_INTERLACED; | ||
2978 | pf->bytesperline = vcs->line_size; | ||
2979 | pf->sizeimage = vcs->line_size * | ||
2980 | (vcs->clipping.bottom - vcs->clipping.top) / | ||
2981 | vcs->decimation; | ||
2982 | pf->colorspace = | ||
2983 | vino_data_formats[vcs->data_format].colorspace; | ||
2984 | |||
2985 | pf->priv = 0; | ||
2986 | |||
2987 | spin_unlock(&vino_drvdata->input_lock); | ||
2988 | break; | ||
2989 | } | ||
2990 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
2991 | default: | ||
2992 | return -EINVAL; | ||
2993 | } | ||
2994 | |||
2995 | return 0; | ||
2996 | } | ||
2997 | |||
2998 | static int vino_v4l2_cropcap(struct vino_channel_settings *vcs, | ||
2999 | struct v4l2_cropcap *ccap) | ||
3000 | { | ||
3001 | const struct vino_data_norm *norm; | ||
3002 | |||
3003 | switch (ccap->type) { | ||
3004 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
3005 | spin_lock(&vino_drvdata->input_lock); | ||
3006 | norm = &vino_data_norms[vcs->data_norm]; | ||
3007 | spin_unlock(&vino_drvdata->input_lock); | ||
3008 | |||
3009 | ccap->bounds.left = 0; | ||
3010 | ccap->bounds.top = 0; | ||
3011 | ccap->bounds.width = norm->width; | ||
3012 | ccap->bounds.height = norm->height; | ||
3013 | memcpy(&ccap->defrect, &ccap->bounds, | ||
3014 | sizeof(struct v4l2_rect)); | ||
3015 | |||
3016 | ccap->pixelaspect.numerator = 1; | ||
3017 | ccap->pixelaspect.denominator = 1; | ||
3018 | break; | ||
3019 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
3020 | default: | ||
3021 | return -EINVAL; | ||
3022 | } | ||
3023 | |||
3024 | return 0; | ||
3025 | } | ||
3026 | |||
3027 | static int vino_v4l2_g_crop(struct vino_channel_settings *vcs, | ||
3028 | struct v4l2_crop *c) | ||
3029 | { | ||
3030 | switch (c->type) { | ||
3031 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
3032 | spin_lock(&vino_drvdata->input_lock); | ||
3033 | |||
3034 | c->c.left = vcs->clipping.left; | ||
3035 | c->c.top = vcs->clipping.top; | ||
3036 | c->c.width = vcs->clipping.right - vcs->clipping.left; | ||
3037 | c->c.height = vcs->clipping.bottom - vcs->clipping.top; | ||
3038 | |||
3039 | spin_unlock(&vino_drvdata->input_lock); | ||
3040 | break; | ||
3041 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
3042 | default: | ||
3043 | return -EINVAL; | ||
3044 | } | ||
3045 | |||
3046 | return 0; | ||
3047 | } | ||
3048 | |||
3049 | static int vino_v4l2_s_crop(struct vino_channel_settings *vcs, | ||
3050 | struct v4l2_crop *c) | ||
3051 | { | ||
3052 | switch (c->type) { | ||
3053 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
3054 | spin_lock(&vino_drvdata->input_lock); | ||
3055 | |||
3056 | if (!vino_is_input_owner(vcs)) { | ||
3057 | spin_unlock(&vino_drvdata->input_lock); | ||
3058 | return -EINVAL; | ||
3059 | } | ||
3060 | vino_set_clipping(vcs, c->c.left, c->c.top, | ||
3061 | c->c.width, c->c.height); | ||
3062 | |||
3063 | spin_unlock(&vino_drvdata->input_lock); | ||
3064 | break; | ||
3065 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
3066 | default: | ||
3067 | return -EINVAL; | ||
3068 | } | ||
3069 | |||
3070 | return 0; | ||
3071 | } | ||
3072 | |||
3073 | static int vino_v4l2_g_parm(struct vino_channel_settings *vcs, | ||
3074 | struct v4l2_streamparm *sp) | ||
3075 | { | ||
3076 | switch (sp->type) { | ||
3077 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | ||
3078 | struct v4l2_captureparm *cp = &sp->parm.capture; | ||
3079 | memset(cp, 0, sizeof(struct v4l2_captureparm)); | ||
3080 | |||
3081 | cp->capability = V4L2_CAP_TIMEPERFRAME; | ||
3082 | cp->timeperframe.numerator = 1; | ||
3083 | |||
3084 | spin_lock(&vino_drvdata->input_lock); | ||
3085 | cp->timeperframe.denominator = vcs->fps; | ||
3086 | spin_unlock(&vino_drvdata->input_lock); | ||
3087 | |||
3088 | // TODO: cp->readbuffers = xxx; | ||
3089 | break; | ||
3090 | } | ||
3091 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
3092 | default: | ||
3093 | return -EINVAL; | ||
3094 | } | ||
3095 | |||
3096 | return 0; | ||
3097 | } | ||
3098 | |||
3099 | static int vino_v4l2_s_parm(struct vino_channel_settings *vcs, | ||
3100 | struct v4l2_streamparm *sp) | ||
3101 | { | ||
3102 | switch (sp->type) { | ||
3103 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | ||
3104 | struct v4l2_captureparm *cp = &sp->parm.capture; | ||
3105 | |||
3106 | spin_lock(&vino_drvdata->input_lock); | ||
3107 | if (!vino_is_input_owner(vcs)) { | ||
3108 | spin_unlock(&vino_drvdata->input_lock); | ||
3109 | return -EINVAL; | ||
3110 | } | ||
3111 | |||
3112 | if ((cp->timeperframe.numerator == 0) || | ||
3113 | (cp->timeperframe.denominator == 0)) { | ||
3114 | /* reset framerate */ | ||
3115 | vino_set_default_framerate(vcs); | ||
3116 | } else { | ||
3117 | vino_set_framerate(vcs, cp->timeperframe.denominator / | ||
3118 | cp->timeperframe.numerator); | ||
3119 | } | ||
3120 | spin_unlock(&vino_drvdata->input_lock); | ||
3121 | |||
3122 | // TODO: set buffers according to cp->readbuffers | ||
3123 | break; | ||
3124 | } | ||
3125 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
3126 | default: | ||
3127 | return -EINVAL; | ||
3128 | } | ||
3129 | |||
3130 | return 0; | ||
3131 | } | ||
3132 | |||
3133 | static int vino_v4l2_reqbufs(struct vino_channel_settings *vcs, | ||
3134 | struct v4l2_requestbuffers *rb) | ||
3135 | { | ||
3136 | if (vcs->reading) | ||
3137 | return -EBUSY; | ||
3138 | |||
3139 | switch (rb->type) { | ||
3140 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | ||
3141 | // TODO: check queue type | ||
3142 | if (rb->memory != V4L2_MEMORY_MMAP) { | ||
3143 | dprintk("type not mmap\n"); | ||
3144 | return -EINVAL; | ||
3145 | } | ||
3146 | |||
3147 | if (vino_is_capturing(vcs)) { | ||
3148 | dprintk("busy, capturing\n"); | ||
3149 | return -EBUSY; | ||
3150 | } | ||
3151 | |||
3152 | dprintk("count = %d\n", rb->count); | ||
3153 | if (rb->count > 0) { | ||
3154 | if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) { | ||
3155 | dprintk("busy, buffers still mapped\n"); | ||
3156 | return -EBUSY; | ||
3157 | } else { | ||
3158 | vino_queue_free(&vcs->fb_queue); | ||
3159 | vino_queue_init(&vcs->fb_queue, &rb->count); | ||
3160 | } | ||
3161 | } else { | ||
3162 | vino_capture_stop(vcs); | ||
3163 | vino_queue_free(&vcs->fb_queue); | ||
3164 | } | ||
3165 | break; | ||
3166 | } | ||
3167 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
3168 | default: | ||
3169 | return -EINVAL; | ||
3170 | } | ||
3171 | |||
3172 | return 0; | ||
3173 | } | ||
3174 | |||
3175 | static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs, | ||
3176 | struct vino_framebuffer *fb, | ||
3177 | struct v4l2_buffer *b) | ||
3178 | { | ||
3179 | if (vino_queue_outgoing_contains(&vcs->fb_queue, | ||
3180 | fb->id)) { | ||
3181 | b->flags &= ~V4L2_BUF_FLAG_QUEUED; | ||
3182 | b->flags |= V4L2_BUF_FLAG_DONE; | ||
3183 | } else if (vino_queue_incoming_contains(&vcs->fb_queue, | ||
3184 | fb->id)) { | ||
3185 | b->flags &= ~V4L2_BUF_FLAG_DONE; | ||
3186 | b->flags |= V4L2_BUF_FLAG_QUEUED; | ||
3187 | } else { | ||
3188 | b->flags &= ~(V4L2_BUF_FLAG_DONE | | ||
3189 | V4L2_BUF_FLAG_QUEUED); | ||
3190 | } | ||
3191 | |||
3192 | b->flags &= ~(V4L2_BUF_FLAG_TIMECODE); | ||
3193 | |||
3194 | if (fb->map_count > 0) | ||
3195 | b->flags |= V4L2_BUF_FLAG_MAPPED; | ||
3196 | |||
3197 | b->index = fb->id; | ||
3198 | b->memory = (vcs->fb_queue.type == VINO_MEMORY_MMAP) ? | ||
3199 | V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR; | ||
3200 | b->m.offset = fb->offset; | ||
3201 | b->bytesused = fb->data_size; | ||
3202 | b->length = fb->size; | ||
3203 | b->field = V4L2_FIELD_INTERLACED; | ||
3204 | b->sequence = fb->frame_counter; | ||
3205 | memcpy(&b->timestamp, &fb->timestamp, | ||
3206 | sizeof(struct timeval)); | ||
3207 | // b->input ? | ||
3208 | |||
3209 | dprintk("buffer %d: length = %d, bytesused = %d, offset = %d\n", | ||
3210 | fb->id, fb->size, fb->data_size, fb->offset); | ||
3211 | } | ||
3212 | |||
3213 | static int vino_v4l2_querybuf(struct vino_channel_settings *vcs, | ||
3214 | struct v4l2_buffer *b) | ||
3215 | { | ||
3216 | if (vcs->reading) | ||
3217 | return -EBUSY; | ||
3218 | |||
3219 | switch (b->type) { | ||
3220 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | ||
3221 | struct vino_framebuffer *fb; | ||
3222 | |||
3223 | // TODO: check queue type | ||
3224 | if (b->index >= vino_queue_get_length(&vcs->fb_queue)) { | ||
3225 | dprintk("invalid index = %d\n", | ||
3226 | b->index); | ||
3227 | return -EINVAL; | ||
3228 | } | ||
3229 | |||
3230 | fb = vino_queue_get_buffer(&vcs->fb_queue, | ||
3231 | b->index); | ||
3232 | if (fb == NULL) { | ||
3233 | dprintk("vino_queue_get_buffer() failed"); | ||
3234 | return -EINVAL; | ||
3235 | } | ||
3236 | |||
3237 | vino_v4l2_get_buffer_status(vcs, fb, b); | ||
3238 | break; | ||
3239 | } | ||
3240 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
3241 | default: | ||
3242 | return -EINVAL; | ||
3243 | } | ||
3244 | |||
3245 | return 0; | ||
3246 | } | ||
3247 | |||
3248 | static int vino_v4l2_qbuf(struct vino_channel_settings *vcs, | ||
3249 | struct v4l2_buffer *b) | ||
3250 | { | ||
3251 | if (vcs->reading) | ||
3252 | return -EBUSY; | ||
3253 | |||
3254 | switch (b->type) { | ||
3255 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | ||
3256 | struct vino_framebuffer *fb; | ||
3257 | int ret; | ||
3258 | |||
3259 | // TODO: check queue type | ||
3260 | if (b->memory != V4L2_MEMORY_MMAP) { | ||
3261 | dprintk("type not mmap\n"); | ||
3262 | return -EINVAL; | ||
3263 | } | ||
3264 | |||
3265 | fb = vino_capture_enqueue(vcs, b->index); | ||
3266 | if (fb == NULL) | ||
3267 | return -EINVAL; | ||
3268 | |||
3269 | vino_v4l2_get_buffer_status(vcs, fb, b); | ||
3270 | |||
3271 | if (vcs->streaming) { | ||
3272 | ret = vino_capture_next(vcs, 1); | ||
3273 | if (ret) | ||
3274 | return ret; | ||
3275 | } | ||
3276 | break; | ||
3277 | } | ||
3278 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
3279 | default: | ||
3280 | return -EINVAL; | ||
3281 | } | ||
3282 | |||
3283 | return 0; | ||
3284 | } | ||
3285 | |||
3286 | static int vino_v4l2_dqbuf(struct vino_channel_settings *vcs, | ||
3287 | struct v4l2_buffer *b, | ||
3288 | unsigned int nonblocking) | ||
3289 | { | ||
3290 | if (vcs->reading) | ||
3291 | return -EBUSY; | ||
3292 | |||
3293 | switch (b->type) { | ||
3294 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: { | ||
3295 | struct vino_framebuffer *fb; | ||
3296 | unsigned int incoming, outgoing; | ||
3297 | int err; | ||
3298 | |||
3299 | // TODO: check queue type | ||
3300 | |||
3301 | err = vino_queue_get_incoming(&vcs->fb_queue, &incoming); | ||
3302 | if (err) { | ||
3303 | dprintk("vino_queue_get_incoming() failed\n"); | ||
3304 | return -EIO; | ||
3305 | } | ||
3306 | err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing); | ||
3307 | if (err) { | ||
3308 | dprintk("vino_queue_get_outgoing() failed\n"); | ||
3309 | return -EIO; | ||
3310 | } | ||
3311 | |||
3312 | dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing); | ||
3313 | |||
3314 | if (outgoing == 0) { | ||
3315 | if (incoming == 0) { | ||
3316 | dprintk("no incoming or outgoing buffers\n"); | ||
3317 | return -EINVAL; | ||
3318 | } | ||
3319 | if (nonblocking) { | ||
3320 | dprintk("non-blocking I/O was selected and " | ||
3321 | "there are no buffers to dequeue\n"); | ||
3322 | return -EAGAIN; | ||
3323 | } | ||
3324 | |||
3325 | err = vino_wait_for_frame(vcs); | ||
3326 | if (err) { | ||
3327 | err = vino_wait_for_frame(vcs); | ||
3328 | if (err) { | ||
3329 | /* interrupted */ | ||
3330 | vino_capture_failed(vcs); | ||
3331 | return -EIO; | ||
3332 | } | ||
3333 | } | ||
3334 | } | ||
3335 | |||
3336 | fb = vino_queue_remove(&vcs->fb_queue, &b->index); | ||
3337 | if (fb == NULL) { | ||
3338 | dprintk("vino_queue_remove() failed\n"); | ||
3339 | return -EINVAL; | ||
3340 | } | ||
3341 | |||
3342 | err = vino_check_buffer(vcs, fb); | ||
3343 | if (err) | ||
3344 | return -EIO; | ||
3345 | |||
3346 | vino_v4l2_get_buffer_status(vcs, fb, b); | ||
3347 | break; | ||
3348 | } | ||
3349 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
3350 | default: | ||
3351 | return -EINVAL; | ||
3352 | } | ||
3353 | |||
3354 | return 0; | ||
3355 | } | ||
3356 | |||
3357 | static int vino_v4l2_streamon(struct vino_channel_settings *vcs) | ||
3358 | { | ||
3359 | unsigned int incoming; | ||
3360 | int ret; | ||
3361 | if (vcs->reading) | ||
3362 | return -EBUSY; | ||
3363 | |||
3364 | if (vcs->streaming) | ||
3365 | return 0; | ||
3366 | |||
3367 | // TODO: check queue type | ||
3368 | |||
3369 | if (vino_queue_get_length(&vcs->fb_queue) < 1) { | ||
3370 | dprintk("no buffers allocated\n"); | ||
3371 | return -EINVAL; | ||
3372 | } | ||
3373 | |||
3374 | ret = vino_queue_get_incoming(&vcs->fb_queue, &incoming); | ||
3375 | if (ret) { | ||
3376 | dprintk("vino_queue_get_incoming() failed\n"); | ||
3377 | return -EINVAL; | ||
3378 | } | ||
3379 | |||
3380 | vcs->streaming = 1; | ||
3381 | |||
3382 | if (incoming > 0) { | ||
3383 | ret = vino_capture_next(vcs, 1); | ||
3384 | if (ret) { | ||
3385 | vcs->streaming = 0; | ||
3386 | |||
3387 | dprintk("couldn't start capture\n"); | ||
3388 | return -EINVAL; | ||
3389 | } | ||
3390 | } | ||
3391 | |||
3392 | return 0; | ||
3393 | } | ||
3394 | |||
3395 | static int vino_v4l2_streamoff(struct vino_channel_settings *vcs) | ||
3396 | { | ||
3397 | if (vcs->reading) | ||
3398 | return -EBUSY; | ||
3399 | |||
3400 | if (!vcs->streaming) | ||
3401 | return 0; | ||
3402 | |||
3403 | vino_capture_stop(vcs); | ||
3404 | vcs->streaming = 0; | ||
3405 | |||
3406 | return 0; | ||
3407 | } | ||
3408 | |||
3409 | static int vino_v4l2_queryctrl(struct vino_channel_settings *vcs, | ||
3410 | struct v4l2_queryctrl *queryctrl) | ||
3411 | { | ||
3412 | int i; | ||
3413 | int err = 0; | ||
3414 | |||
3415 | spin_lock(&vino_drvdata->input_lock); | ||
3416 | |||
3417 | switch (vcs->input) { | ||
3418 | case VINO_INPUT_D1: | ||
3419 | for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { | ||
3420 | if (vino_indycam_v4l2_controls[i].id == | ||
3421 | queryctrl->id) { | ||
3422 | memcpy(queryctrl, | ||
3423 | &vino_indycam_v4l2_controls[i], | ||
3424 | sizeof(struct v4l2_queryctrl)); | ||
3425 | goto found; | ||
3426 | } | ||
3427 | } | ||
3428 | |||
3429 | err = -EINVAL; | ||
3430 | break; | ||
3431 | case VINO_INPUT_COMPOSITE: | ||
3432 | case VINO_INPUT_SVIDEO: | ||
3433 | for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { | ||
3434 | if (vino_saa7191_v4l2_controls[i].id == | ||
3435 | queryctrl->id) { | ||
3436 | memcpy(queryctrl, | ||
3437 | &vino_saa7191_v4l2_controls[i], | ||
3438 | sizeof(struct v4l2_queryctrl)); | ||
3439 | goto found; | ||
3440 | } | ||
3441 | } | ||
3442 | |||
3443 | err = -EINVAL; | ||
3444 | break; | ||
3445 | default: | ||
3446 | err = -EINVAL; | ||
3447 | } | ||
3448 | |||
3449 | found: | ||
3450 | spin_unlock(&vino_drvdata->input_lock); | ||
3451 | |||
3452 | return err; | ||
3453 | } | ||
3454 | |||
3455 | static int vino_v4l2_g_ctrl(struct vino_channel_settings *vcs, | ||
3456 | struct v4l2_control *control) | ||
3457 | { | ||
3458 | struct indycam_control indycam_ctrl; | ||
3459 | struct saa7191_control saa7191_ctrl; | ||
3460 | int err = 0; | ||
3461 | |||
3462 | spin_lock(&vino_drvdata->input_lock); | ||
3463 | |||
3464 | switch (vcs->input) { | ||
3465 | case VINO_INPUT_D1: | ||
3466 | i2c_camera_command(DECODER_INDYCAM_GET_CONTROLS, | ||
3467 | &indycam_ctrl); | ||
3468 | |||
3469 | switch(control->id) { | ||
3470 | case V4L2_CID_AUTOGAIN: | ||
3471 | control->value = indycam_ctrl.agc; | ||
3472 | break; | ||
3473 | case V4L2_CID_AUTO_WHITE_BALANCE: | ||
3474 | control->value = indycam_ctrl.awb; | ||
3475 | break; | ||
3476 | case V4L2_CID_GAIN: | ||
3477 | control->value = indycam_ctrl.gain; | ||
3478 | break; | ||
3479 | case V4L2_CID_PRIVATE_BASE: | ||
3480 | control->value = indycam_ctrl.red_saturation; | ||
3481 | break; | ||
3482 | case V4L2_CID_PRIVATE_BASE + 1: | ||
3483 | control->value = indycam_ctrl.blue_saturation; | ||
3484 | break; | ||
3485 | case V4L2_CID_RED_BALANCE: | ||
3486 | control->value = indycam_ctrl.red_balance; | ||
3487 | break; | ||
3488 | case V4L2_CID_BLUE_BALANCE: | ||
3489 | control->value = indycam_ctrl.blue_balance; | ||
3490 | break; | ||
3491 | case V4L2_CID_EXPOSURE: | ||
3492 | control->value = indycam_ctrl.shutter; | ||
3493 | break; | ||
3494 | case V4L2_CID_GAMMA: | ||
3495 | control->value = indycam_ctrl.gamma; | ||
3496 | break; | ||
3497 | default: | ||
3498 | err = -EINVAL; | ||
3499 | } | ||
3500 | break; | ||
3501 | case VINO_INPUT_COMPOSITE: | ||
3502 | case VINO_INPUT_SVIDEO: | ||
3503 | i2c_decoder_command(DECODER_SAA7191_GET_CONTROLS, | ||
3504 | &saa7191_ctrl); | ||
3505 | |||
3506 | switch(control->id) { | ||
3507 | case V4L2_CID_HUE: | ||
3508 | control->value = saa7191_ctrl.hue; | ||
3509 | break; | ||
3510 | case V4L2_CID_PRIVATE_BASE: | ||
3511 | control->value = saa7191_ctrl.vtrc; | ||
3512 | break; | ||
3513 | default: | ||
3514 | err = -EINVAL; | ||
3515 | } | ||
3516 | break; | ||
3517 | default: | ||
3518 | err = -EINVAL; | ||
3519 | } | ||
3520 | |||
3521 | spin_unlock(&vino_drvdata->input_lock); | ||
3522 | |||
3523 | return err; | ||
3524 | } | ||
3525 | |||
3526 | static int vino_v4l2_s_ctrl(struct vino_channel_settings *vcs, | ||
3527 | struct v4l2_control *control) | ||
3528 | { | ||
3529 | struct indycam_control indycam_ctrl; | ||
3530 | struct saa7191_control saa7191_ctrl; | ||
3531 | int i; | ||
3532 | int err = 0; | ||
3533 | |||
3534 | spin_lock(&vino_drvdata->input_lock); | ||
3535 | |||
3536 | switch (vcs->input) { | ||
3537 | case VINO_INPUT_D1: | ||
3538 | for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) { | ||
3539 | if (vino_indycam_v4l2_controls[i].id == | ||
3540 | control->id) { | ||
3541 | if ((control->value >= | ||
3542 | vino_indycam_v4l2_controls[i].minimum) | ||
3543 | && (control->value <= | ||
3544 | vino_indycam_v4l2_controls[i]. | ||
3545 | maximum)) { | ||
3546 | goto ok1; | ||
3547 | } else { | ||
3548 | err = -ERANGE; | ||
3549 | goto error; | ||
3550 | } | ||
3551 | } | ||
3552 | } | ||
3553 | err = -EINVAL; | ||
3554 | goto error; | ||
3555 | |||
3556 | ok1: | ||
3557 | indycam_ctrl.agc = INDYCAM_VALUE_UNCHANGED; | ||
3558 | indycam_ctrl.awb = INDYCAM_VALUE_UNCHANGED; | ||
3559 | indycam_ctrl.shutter = INDYCAM_VALUE_UNCHANGED; | ||
3560 | indycam_ctrl.gain = INDYCAM_VALUE_UNCHANGED; | ||
3561 | indycam_ctrl.red_balance = INDYCAM_VALUE_UNCHANGED; | ||
3562 | indycam_ctrl.blue_balance = INDYCAM_VALUE_UNCHANGED; | ||
3563 | indycam_ctrl.red_saturation = INDYCAM_VALUE_UNCHANGED; | ||
3564 | indycam_ctrl.blue_saturation = INDYCAM_VALUE_UNCHANGED; | ||
3565 | indycam_ctrl.gamma = INDYCAM_VALUE_UNCHANGED; | ||
3566 | |||
3567 | switch(control->id) { | ||
3568 | case V4L2_CID_AUTOGAIN: | ||
3569 | indycam_ctrl.agc = control->value; | ||
3570 | break; | ||
3571 | case V4L2_CID_AUTO_WHITE_BALANCE: | ||
3572 | indycam_ctrl.awb = control->value; | ||
3573 | break; | ||
3574 | case V4L2_CID_GAIN: | ||
3575 | indycam_ctrl.gain = control->value; | ||
3576 | break; | ||
3577 | case V4L2_CID_PRIVATE_BASE: | ||
3578 | indycam_ctrl.red_saturation = control->value; | ||
3579 | break; | ||
3580 | case V4L2_CID_PRIVATE_BASE + 1: | ||
3581 | indycam_ctrl.blue_saturation = control->value; | ||
3582 | break; | ||
3583 | case V4L2_CID_RED_BALANCE: | ||
3584 | indycam_ctrl.red_balance = control->value; | ||
3585 | break; | ||
3586 | case V4L2_CID_BLUE_BALANCE: | ||
3587 | indycam_ctrl.blue_balance = control->value; | ||
3588 | break; | ||
3589 | case V4L2_CID_EXPOSURE: | ||
3590 | indycam_ctrl.shutter = control->value; | ||
3591 | break; | ||
3592 | case V4L2_CID_GAMMA: | ||
3593 | indycam_ctrl.gamma = control->value; | ||
3594 | break; | ||
3595 | default: | ||
3596 | err = -EINVAL; | ||
3597 | } | ||
3598 | |||
3599 | if (!err) | ||
3600 | i2c_camera_command(DECODER_INDYCAM_SET_CONTROLS, | ||
3601 | &indycam_ctrl); | ||
3602 | break; | ||
3603 | case VINO_INPUT_COMPOSITE: | ||
3604 | case VINO_INPUT_SVIDEO: | ||
3605 | for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) { | ||
3606 | if (vino_saa7191_v4l2_controls[i].id == | ||
3607 | control->id) { | ||
3608 | if ((control->value >= | ||
3609 | vino_saa7191_v4l2_controls[i].minimum) | ||
3610 | && (control->value <= | ||
3611 | vino_saa7191_v4l2_controls[i]. | ||
3612 | maximum)) { | ||
3613 | goto ok2; | ||
3614 | } else { | ||
3615 | err = -ERANGE; | ||
3616 | goto error; | ||
3617 | } | ||
3618 | } | ||
3619 | } | ||
3620 | err = -EINVAL; | ||
3621 | goto error; | ||
3622 | |||
3623 | ok2: | ||
3624 | saa7191_ctrl.hue = SAA7191_VALUE_UNCHANGED; | ||
3625 | saa7191_ctrl.vtrc = SAA7191_VALUE_UNCHANGED; | ||
3626 | |||
3627 | switch(control->id) { | ||
3628 | case V4L2_CID_HUE: | ||
3629 | saa7191_ctrl.hue = control->value; | ||
3630 | break; | ||
3631 | case V4L2_CID_PRIVATE_BASE: | ||
3632 | saa7191_ctrl.vtrc = control->value; | ||
3633 | break; | ||
3634 | default: | ||
3635 | err = -EINVAL; | ||
3636 | } | ||
3637 | |||
3638 | if (!err) | ||
3639 | i2c_decoder_command(DECODER_SAA7191_SET_CONTROLS, | ||
3640 | &saa7191_ctrl); | ||
3641 | break; | ||
3642 | default: | ||
3643 | err = -EINVAL; | ||
3644 | } | ||
3645 | |||
3646 | error: | ||
3647 | spin_unlock(&vino_drvdata->input_lock); | ||
3648 | |||
3649 | return err; | ||
3650 | } | ||
3651 | |||
3652 | /* File operations */ | ||
3653 | |||
3654 | static int vino_open(struct inode *inode, struct file *file) | ||
3655 | { | ||
3656 | struct video_device *dev = video_devdata(file); | ||
3657 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
3658 | int ret = 0; | ||
3659 | dprintk("open(): channel = %c\n", | ||
3660 | (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B'); | ||
3661 | |||
3662 | down(&vcs->sem); | ||
3663 | |||
3664 | if (vcs->users) { | ||
3665 | dprintk("open(): driver busy\n"); | ||
3666 | ret = -EBUSY; | ||
3667 | goto out; | ||
3668 | } | ||
3669 | |||
3670 | ret = vino_acquire_input(vcs); | ||
3671 | if (ret) { | ||
3672 | dprintk("open(): vino_acquire_input() failed\n"); | ||
3673 | goto out; | ||
3674 | } | ||
3675 | |||
3676 | vcs->users++; | ||
3677 | |||
3678 | out: | ||
3679 | up(&vcs->sem); | ||
3680 | |||
3681 | dprintk("open(): %s!\n", ret ? "failed" : "complete"); | ||
3682 | |||
3683 | return ret; | ||
3684 | } | ||
3685 | |||
3686 | static int vino_close(struct inode *inode, struct file *file) | ||
3687 | { | ||
3688 | struct video_device *dev = video_devdata(file); | ||
3689 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
3690 | dprintk("close():\n"); | ||
3691 | |||
3692 | down(&vcs->sem); | ||
3693 | |||
3694 | vcs->users--; | ||
3695 | |||
3696 | if (!vcs->users) { | ||
3697 | vino_release_input(vcs); | ||
3698 | |||
3699 | /* stop DMA and free buffers */ | ||
3700 | vino_capture_stop(vcs); | ||
3701 | vino_queue_free(&vcs->fb_queue); | ||
3702 | } | ||
3703 | |||
3704 | up(&vcs->sem); | ||
3705 | |||
3706 | return 0; | ||
3707 | } | ||
3708 | |||
3709 | static void vino_vm_open(struct vm_area_struct *vma) | ||
3710 | { | ||
3711 | struct vino_framebuffer *fb = vma->vm_private_data; | ||
3712 | |||
3713 | fb->map_count++; | ||
3714 | dprintk("vino_vm_open(): count = %d\n", fb->map_count); | ||
3715 | } | ||
3716 | |||
3717 | static void vino_vm_close(struct vm_area_struct *vma) | ||
3718 | { | ||
3719 | struct vino_framebuffer *fb = vma->vm_private_data; | ||
3720 | |||
3721 | fb->map_count--; | ||
3722 | dprintk("vino_vm_close(): count = %d\n", fb->map_count); | ||
3723 | } | ||
3724 | |||
3725 | static struct vm_operations_struct vino_vm_ops = { | ||
3726 | .open = vino_vm_open, | ||
3727 | .close = vino_vm_close, | ||
3728 | }; | ||
3729 | |||
3730 | static int vino_mmap(struct file *file, struct vm_area_struct *vma) | ||
3731 | { | ||
3732 | struct video_device *dev = video_devdata(file); | ||
3733 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
3734 | |||
3735 | unsigned long start = vma->vm_start; | ||
3736 | unsigned long size = vma->vm_end - vma->vm_start; | ||
3737 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | ||
3738 | |||
3739 | struct vino_framebuffer *fb = NULL; | ||
3740 | unsigned int i, length; | ||
3741 | int ret = 0; | ||
3742 | |||
3743 | dprintk("mmap():\n"); | ||
3744 | |||
3745 | // TODO: reject mmap if already mapped | ||
3746 | |||
3747 | if (down_interruptible(&vcs->sem)) | ||
3748 | return -EINTR; | ||
3749 | |||
3750 | if (vcs->reading) { | ||
3751 | ret = -EBUSY; | ||
3752 | goto out; | ||
3753 | } | ||
3754 | |||
3755 | // TODO: check queue type | ||
3756 | |||
3757 | if (!(vma->vm_flags & VM_WRITE)) { | ||
3758 | dprintk("mmap(): app bug: PROT_WRITE please\n"); | ||
3759 | ret = -EINVAL; | ||
3760 | goto out; | ||
3761 | } | ||
3762 | if (!(vma->vm_flags & VM_SHARED)) { | ||
3763 | dprintk("mmap(): app bug: MAP_SHARED please\n"); | ||
3764 | ret = -EINVAL; | ||
3765 | goto out; | ||
3766 | } | ||
3767 | |||
3768 | /* find the correct buffer using offset */ | ||
3769 | length = vino_queue_get_length(&vcs->fb_queue); | ||
3770 | if (length == 0) { | ||
3771 | dprintk("mmap(): queue not initialized\n"); | ||
3772 | ret = -EINVAL; | ||
3773 | goto out; | ||
3774 | } | ||
3775 | |||
3776 | for (i = 0; i < length; i++) { | ||
3777 | fb = vino_queue_get_buffer(&vcs->fb_queue, i); | ||
3778 | if (fb == NULL) { | ||
3779 | dprintk("mmap(): vino_queue_get_buffer() failed\n"); | ||
3780 | ret = -EINVAL; | ||
3781 | goto out; | ||
3782 | } | ||
3783 | |||
3784 | if (fb->offset == offset) | ||
3785 | goto found; | ||
3786 | } | ||
3787 | |||
3788 | dprintk("mmap(): invalid offset = %lu\n", offset); | ||
3789 | ret = -EINVAL; | ||
3790 | goto out; | ||
3791 | |||
3792 | found: | ||
3793 | dprintk("mmap(): buffer = %d\n", i); | ||
3794 | |||
3795 | if (size > (fb->desc_table.page_count * PAGE_SIZE)) { | ||
3796 | dprintk("mmap(): failed: size = %lu > %lu\n", | ||
3797 | size, fb->desc_table.page_count * PAGE_SIZE); | ||
3798 | ret = -EINVAL; | ||
3799 | goto out; | ||
3800 | } | ||
3801 | |||
3802 | for (i = 0; i < fb->desc_table.page_count; i++) { | ||
3803 | unsigned long pfn = | ||
3804 | virt_to_phys((void *)fb->desc_table.virtual[i]) >> | ||
3805 | PAGE_SHIFT; | ||
3806 | |||
3807 | if (size < PAGE_SIZE) | ||
3808 | break; | ||
3809 | |||
3810 | // protection was: PAGE_READONLY | ||
3811 | if (remap_pfn_range(vma, start, pfn, PAGE_SIZE, | ||
3812 | vma->vm_page_prot)) { | ||
3813 | dprintk("mmap(): remap_pfn_range() failed\n"); | ||
3814 | ret = -EAGAIN; | ||
3815 | goto out; | ||
3816 | } | ||
3817 | |||
3818 | start += PAGE_SIZE; | ||
3819 | size -= PAGE_SIZE; | ||
3820 | } | ||
3821 | |||
3822 | fb->map_count = 1; | ||
3823 | |||
3824 | vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED; | ||
3825 | vma->vm_flags &= ~VM_IO; | ||
3826 | vma->vm_private_data = fb; | ||
3827 | vma->vm_file = file; | ||
3828 | vma->vm_ops = &vino_vm_ops; | ||
3829 | |||
3830 | out: | ||
3831 | up(&vcs->sem); | ||
3832 | |||
3833 | return ret; | ||
3834 | } | ||
3835 | |||
3836 | static unsigned int vino_poll(struct file *file, poll_table *pt) | ||
3837 | { | ||
3838 | struct video_device *dev = video_devdata(file); | ||
3839 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
3840 | unsigned int outgoing; | ||
3841 | unsigned int ret = 0; | ||
3842 | |||
3843 | // lock mutex (?) | ||
3844 | // TODO: this has to be corrected for different read modes | ||
3845 | |||
3846 | dprintk("poll():\n"); | ||
3847 | |||
3848 | if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) { | ||
3849 | dprintk("poll(): vino_queue_get_outgoing() failed\n"); | ||
3850 | ret = POLLERR; | ||
3851 | goto error; | ||
3852 | } | ||
3853 | if (outgoing > 0) | ||
3854 | goto over; | ||
3855 | |||
3856 | poll_wait(file, &vcs->fb_queue.frame_wait_queue, pt); | ||
3857 | |||
3858 | if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) { | ||
3859 | dprintk("poll(): vino_queue_get_outgoing() failed\n"); | ||
3860 | ret = POLLERR; | ||
3861 | goto error; | ||
3862 | } | ||
3863 | |||
3864 | over: | ||
3865 | dprintk("poll(): data %savailable\n", | ||
3866 | (outgoing > 0) ? "" : "not "); | ||
3867 | if (outgoing > 0) { | ||
3868 | ret = POLLIN | POLLRDNORM; | ||
3869 | } | ||
3870 | |||
3871 | error: | ||
3872 | |||
3873 | return ret; | ||
3874 | } | ||
3875 | |||
3876 | static int vino_do_ioctl(struct inode *inode, struct file *file, | ||
3877 | unsigned int cmd, void *arg) | ||
3878 | { | ||
3879 | struct video_device *dev = video_devdata(file); | ||
3880 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
3881 | |||
3882 | switch (_IOC_TYPE(cmd)) { | ||
3883 | case 'v': | ||
3884 | dprintk("ioctl(): V4L1 unsupported (0x%08x)\n", cmd); | ||
3885 | break; | ||
3886 | case 'V': | ||
3887 | dprintk("ioctl(): V4L2 %s (0x%08x)\n", | ||
3888 | v4l2_ioctl_names[_IOC_NR(cmd)], cmd); | ||
3889 | break; | ||
3890 | default: | ||
3891 | dprintk("ioctl(): unsupported command 0x%08x\n", cmd); | ||
3892 | } | ||
3893 | |||
3894 | switch (cmd) { | ||
3895 | /* TODO: V4L1 interface (use compatibility layer?) */ | ||
3896 | /* V4L2 interface */ | ||
3897 | case VIDIOC_QUERYCAP: { | ||
3898 | vino_v4l2_querycap(arg); | ||
3899 | break; | ||
3900 | } | ||
3901 | case VIDIOC_ENUMINPUT: { | ||
3902 | return vino_v4l2_enuminput(vcs, arg); | ||
3903 | } | ||
3904 | case VIDIOC_G_INPUT: { | ||
3905 | return vino_v4l2_g_input(vcs, arg); | ||
3906 | } | ||
3907 | case VIDIOC_S_INPUT: { | ||
3908 | return vino_v4l2_s_input(vcs, arg); | ||
3909 | } | ||
3910 | case VIDIOC_ENUMSTD: { | ||
3911 | return vino_v4l2_enumstd(vcs, arg); | ||
3912 | } | ||
3913 | case VIDIOC_G_STD: { | ||
3914 | return vino_v4l2_g_std(vcs, arg); | ||
3915 | } | ||
3916 | case VIDIOC_S_STD: { | ||
3917 | return vino_v4l2_s_std(vcs, arg); | ||
3918 | } | ||
3919 | case VIDIOC_ENUM_FMT: { | ||
3920 | return vino_v4l2_enum_fmt(vcs, arg); | ||
3921 | } | ||
3922 | case VIDIOC_TRY_FMT: { | ||
3923 | return vino_v4l2_try_fmt(vcs, arg); | ||
3924 | } | ||
3925 | case VIDIOC_G_FMT: { | ||
3926 | return vino_v4l2_g_fmt(vcs, arg); | ||
3927 | } | ||
3928 | case VIDIOC_S_FMT: { | ||
3929 | return vino_v4l2_s_fmt(vcs, arg); | ||
3930 | } | ||
3931 | case VIDIOC_CROPCAP: { | ||
3932 | return vino_v4l2_cropcap(vcs, arg); | ||
3933 | } | ||
3934 | case VIDIOC_G_CROP: { | ||
3935 | return vino_v4l2_g_crop(vcs, arg); | ||
3936 | } | ||
3937 | case VIDIOC_S_CROP: { | ||
3938 | return vino_v4l2_s_crop(vcs, arg); | ||
3939 | } | ||
3940 | case VIDIOC_G_PARM: { | ||
3941 | return vino_v4l2_g_parm(vcs, arg); | ||
3942 | } | ||
3943 | case VIDIOC_S_PARM: { | ||
3944 | return vino_v4l2_s_parm(vcs, arg); | ||
3945 | } | ||
3946 | case VIDIOC_REQBUFS: { | ||
3947 | return vino_v4l2_reqbufs(vcs, arg); | ||
3948 | } | ||
3949 | case VIDIOC_QUERYBUF: { | ||
3950 | return vino_v4l2_querybuf(vcs, arg); | ||
3951 | } | ||
3952 | case VIDIOC_QBUF: { | ||
3953 | return vino_v4l2_qbuf(vcs, arg); | ||
3954 | } | ||
3955 | case VIDIOC_DQBUF: { | ||
3956 | return vino_v4l2_dqbuf(vcs, arg, file->f_flags & O_NONBLOCK); | ||
3957 | } | ||
3958 | case VIDIOC_STREAMON: { | ||
3959 | return vino_v4l2_streamon(vcs); | ||
3960 | } | ||
3961 | case VIDIOC_STREAMOFF: { | ||
3962 | return vino_v4l2_streamoff(vcs); | ||
3963 | } | ||
3964 | case VIDIOC_QUERYCTRL: { | ||
3965 | return vino_v4l2_queryctrl(vcs, arg); | ||
3966 | } | ||
3967 | case VIDIOC_G_CTRL: { | ||
3968 | return vino_v4l2_g_ctrl(vcs, arg); | ||
3969 | } | ||
3970 | case VIDIOC_S_CTRL: { | ||
3971 | return vino_v4l2_s_ctrl(vcs, arg); | ||
3972 | } | ||
3973 | default: | ||
3974 | return -ENOIOCTLCMD; | ||
3975 | } | ||
3976 | |||
3977 | return 0; | ||
3978 | } | ||
3979 | |||
3980 | static int vino_ioctl(struct inode *inode, struct file *file, | ||
3981 | unsigned int cmd, unsigned long arg) | ||
3982 | { | ||
3983 | struct video_device *dev = video_devdata(file); | ||
3984 | struct vino_channel_settings *vcs = video_get_drvdata(dev); | ||
3985 | int ret; | ||
3986 | |||
3987 | if (down_interruptible(&vcs->sem)) | ||
3988 | return -EINTR; | ||
3989 | |||
3990 | ret = video_usercopy(inode, file, cmd, arg, vino_do_ioctl); | ||
3991 | |||
3992 | up(&vcs->sem); | ||
3993 | |||
3994 | return ret; | ||
3995 | } | ||
3996 | |||
3997 | /* Initialization and cleanup */ | ||
3998 | |||
3999 | // __initdata | ||
4000 | static int vino_init_stage = 0; | ||
4001 | |||
4002 | static struct file_operations vino_fops = { | ||
212 | .owner = THIS_MODULE, | 4003 | .owner = THIS_MODULE, |
213 | .type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE, | ||
214 | .hardware = VID_HARDWARE_VINO, | ||
215 | .name = "VINO", | ||
216 | .open = vino_open, | 4004 | .open = vino_open, |
217 | .close = vino_close, | 4005 | .release = vino_close, |
218 | .ioctl = vino_ioctl, | 4006 | .ioctl = vino_ioctl, |
219 | .mmap = vino_mmap, | 4007 | .mmap = vino_mmap, |
4008 | .poll = vino_poll, | ||
4009 | .llseek = no_llseek, | ||
220 | }; | 4010 | }; |
221 | 4011 | ||
222 | static int __init vino_init(void) | 4012 | static struct video_device v4l_device_template = { |
4013 | .name = "NOT SET", | ||
4014 | //.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE | | ||
4015 | // VID_TYPE_CLIPPING | VID_TYPE_SCALES, VID_TYPE_OVERLAY | ||
4016 | .hardware = VID_HARDWARE_VINO, | ||
4017 | .fops = &vino_fops, | ||
4018 | .minor = -1, | ||
4019 | }; | ||
4020 | |||
4021 | static void vino_module_cleanup(int stage) | ||
4022 | { | ||
4023 | switch(stage) { | ||
4024 | case 10: | ||
4025 | video_unregister_device(vino_drvdata->b.v4l_device); | ||
4026 | vino_drvdata->b.v4l_device = NULL; | ||
4027 | case 9: | ||
4028 | video_unregister_device(vino_drvdata->a.v4l_device); | ||
4029 | vino_drvdata->a.v4l_device = NULL; | ||
4030 | case 8: | ||
4031 | vino_i2c_del_bus(); | ||
4032 | case 7: | ||
4033 | free_irq(SGI_VINO_IRQ, NULL); | ||
4034 | case 6: | ||
4035 | if (vino_drvdata->b.v4l_device) { | ||
4036 | video_device_release(vino_drvdata->b.v4l_device); | ||
4037 | vino_drvdata->b.v4l_device = NULL; | ||
4038 | } | ||
4039 | case 5: | ||
4040 | if (vino_drvdata->a.v4l_device) { | ||
4041 | video_device_release(vino_drvdata->a.v4l_device); | ||
4042 | vino_drvdata->a.v4l_device = NULL; | ||
4043 | } | ||
4044 | case 4: | ||
4045 | /* all entries in dma_cpu dummy table have the same address */ | ||
4046 | dma_unmap_single(NULL, | ||
4047 | vino_drvdata->dummy_desc_table.dma_cpu[0], | ||
4048 | PAGE_SIZE, DMA_FROM_DEVICE); | ||
4049 | dma_free_coherent(NULL, VINO_DUMMY_DESC_COUNT | ||
4050 | * sizeof(dma_addr_t), | ||
4051 | (void *)vino_drvdata-> | ||
4052 | dummy_desc_table.dma_cpu, | ||
4053 | vino_drvdata->dummy_desc_table.dma); | ||
4054 | case 3: | ||
4055 | free_page(vino_drvdata->dummy_page); | ||
4056 | case 2: | ||
4057 | kfree(vino_drvdata); | ||
4058 | case 1: | ||
4059 | iounmap(vino); | ||
4060 | case 0: | ||
4061 | break; | ||
4062 | default: | ||
4063 | dprintk("vino_module_cleanup(): invalid cleanup stage = %d\n", | ||
4064 | stage); | ||
4065 | } | ||
4066 | } | ||
4067 | |||
4068 | static int vino_probe(void) | ||
223 | { | 4069 | { |
224 | unsigned long rev; | 4070 | unsigned long rev_id; |
225 | int i, ret = 0; | ||
226 | 4071 | ||
227 | /* VINO is Indy specific beast */ | 4072 | if (ip22_is_fullhouse()) { |
228 | if (ip22_is_fullhouse()) | 4073 | printk(KERN_ERR "VINO doesn't exist in IP22 Fullhouse\n"); |
229 | return -ENODEV; | 4074 | return -ENODEV; |
4075 | } | ||
230 | 4076 | ||
231 | /* | ||
232 | * VINO is in the EISA address space, so the sysid register will tell | ||
233 | * us if the EISA_PRESENT pin on MC has been pulled low. | ||
234 | * | ||
235 | * If EISA_PRESENT is not set we definitely don't have a VINO equiped | ||
236 | * system. | ||
237 | */ | ||
238 | if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) { | 4077 | if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) { |
239 | printk(KERN_ERR "VINO not found\n"); | 4078 | printk(KERN_ERR "VINO is not found (EISA BUS not present)\n"); |
240 | return -ENODEV; | 4079 | return -ENODEV; |
241 | } | 4080 | } |
242 | 4081 | ||
243 | vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino)); | 4082 | vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino)); |
244 | if (!vino) | 4083 | if (!vino) { |
4084 | printk(KERN_ERR "VINO: ioremap() failed\n"); | ||
245 | return -EIO; | 4085 | return -EIO; |
4086 | } | ||
4087 | vino_init_stage++; | ||
246 | 4088 | ||
247 | /* Okay, once we know that VINO is present we'll read its revision | 4089 | if (get_dbe(rev_id, &(vino->rev_id))) { |
248 | * safe way. One never knows... */ | 4090 | printk(KERN_ERR "Failed to read VINO revision register\n"); |
249 | if (get_dbe(rev, &(vino->rev_id))) { | 4091 | vino_module_cleanup(vino_init_stage); |
250 | printk(KERN_ERR "VINO: failed to read revision register\n"); | 4092 | return -ENODEV; |
251 | ret = -ENODEV; | ||
252 | goto out_unmap; | ||
253 | } | 4093 | } |
254 | if (VINO_ID_VALUE(rev) != VINO_CHIP_ID) { | 4094 | |
255 | printk(KERN_ERR "VINO is not VINO (Rev/ID: 0x%04lx)\n", rev); | 4095 | if (VINO_ID_VALUE(rev_id) != VINO_CHIP_ID) { |
256 | ret = -ENODEV; | 4096 | printk(KERN_ERR "Unknown VINO chip ID (Rev/ID: 0x%02lx)\n", |
257 | goto out_unmap; | 4097 | rev_id); |
4098 | vino_module_cleanup(vino_init_stage); | ||
4099 | return -ENODEV; | ||
258 | } | 4100 | } |
259 | printk(KERN_INFO "VINO Rev: 0x%02lx\n", VINO_REV_NUM(rev)); | ||
260 | 4101 | ||
261 | Vino = (struct vino_video *) | 4102 | printk(KERN_INFO "VINO with chip ID %ld, revision %ld found\n", |
262 | kmalloc(sizeof(struct vino_video), GFP_KERNEL); | 4103 | VINO_ID_VALUE(rev_id), VINO_REV_NUM(rev_id)); |
263 | if (!Vino) { | 4104 | |
264 | ret = -ENOMEM; | 4105 | return 0; |
265 | goto out_unmap; | 4106 | } |
4107 | |||
4108 | static int vino_init(void) | ||
4109 | { | ||
4110 | dma_addr_t dma_dummy_address; | ||
4111 | int i; | ||
4112 | |||
4113 | vino_drvdata = (struct vino_settings *) | ||
4114 | kmalloc(sizeof(struct vino_settings), GFP_KERNEL); | ||
4115 | if (!vino_drvdata) { | ||
4116 | vino_module_cleanup(vino_init_stage); | ||
4117 | return -ENOMEM; | ||
266 | } | 4118 | } |
4119 | memset(vino_drvdata, 0, sizeof(struct vino_settings)); | ||
4120 | vino_init_stage++; | ||
267 | 4121 | ||
268 | Vino->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA); | 4122 | /* create a dummy dma descriptor */ |
269 | if (!Vino->dummy_page) { | 4123 | vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA); |
270 | ret = -ENOMEM; | 4124 | if (!vino_drvdata->dummy_page) { |
271 | goto out_free_vino; | 4125 | vino_module_cleanup(vino_init_stage); |
4126 | return -ENOMEM; | ||
272 | } | 4127 | } |
273 | for (i = 0; i < 4; i++) | 4128 | vino_init_stage++; |
274 | Vino->dummy_buf[i] = PHYSADDR(Vino->dummy_page); | 4129 | |
4130 | // TODO: use page_count in dummy_desc_table | ||
4131 | |||
4132 | vino_drvdata->dummy_desc_table.dma_cpu = | ||
4133 | dma_alloc_coherent(NULL, | ||
4134 | VINO_DUMMY_DESC_COUNT * sizeof(dma_addr_t), | ||
4135 | &vino_drvdata->dummy_desc_table.dma, | ||
4136 | GFP_KERNEL | GFP_DMA); | ||
4137 | if (!vino_drvdata->dummy_desc_table.dma_cpu) { | ||
4138 | vino_module_cleanup(vino_init_stage); | ||
4139 | return -ENOMEM; | ||
4140 | } | ||
4141 | vino_init_stage++; | ||
4142 | |||
4143 | dma_dummy_address = dma_map_single(NULL, | ||
4144 | (void *)vino_drvdata->dummy_page, | ||
4145 | PAGE_SIZE, DMA_FROM_DEVICE); | ||
4146 | for (i = 0; i < VINO_DUMMY_DESC_COUNT; i++) { | ||
4147 | vino_drvdata->dummy_desc_table.dma_cpu[i] = dma_dummy_address; | ||
4148 | } | ||
4149 | |||
4150 | /* initialize VINO */ | ||
275 | 4151 | ||
276 | vino->control = 0; | 4152 | vino->control = 0; |
277 | /* prevent VINO from throwing spurious interrupts */ | 4153 | vino->a.next_4_desc = vino_drvdata->dummy_desc_table.dma; |
278 | vino->a.next_4_desc = PHYSADDR(Vino->dummy_buf); | 4154 | vino->b.next_4_desc = vino_drvdata->dummy_desc_table.dma; |
279 | vino->b.next_4_desc = PHYSADDR(Vino->dummy_buf); | 4155 | udelay(VINO_DESC_FETCH_DELAY); |
280 | udelay(5); | 4156 | |
281 | vino->intr_status = 0; | 4157 | vino->intr_status = 0; |
282 | /* set threshold level */ | ||
283 | vino->a.fifo_thres = threshold_a; | ||
284 | vino->b.fifo_thres = threshold_b; | ||
285 | 4158 | ||
286 | init_MUTEX(&Vino->input_lock); | 4159 | vino->a.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT; |
4160 | vino->b.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT; | ||
4161 | |||
4162 | return 0; | ||
4163 | } | ||
4164 | |||
4165 | static int vino_init_channel_settings(struct vino_channel_settings *vcs, | ||
4166 | unsigned int channel, const char *name) | ||
4167 | { | ||
4168 | vcs->channel = channel; | ||
4169 | vcs->input = VINO_INPUT_NONE; | ||
4170 | vcs->alpha = 0; | ||
4171 | vcs->users = 0; | ||
4172 | vcs->data_format = VINO_DATA_FMT_GREY; | ||
4173 | vcs->data_norm = VINO_DATA_NORM_NTSC; | ||
4174 | vcs->decimation = 1; | ||
4175 | vino_set_default_clipping(vcs); | ||
4176 | vino_set_default_framerate(vcs); | ||
4177 | |||
4178 | vcs->capturing = 0; | ||
4179 | |||
4180 | init_MUTEX(&vcs->sem); | ||
4181 | spin_lock_init(&vcs->capture_lock); | ||
4182 | |||
4183 | init_MUTEX(&vcs->fb_queue.queue_sem); | ||
4184 | spin_lock_init(&vcs->fb_queue.queue_lock); | ||
4185 | init_waitqueue_head(&vcs->fb_queue.frame_wait_queue); | ||
4186 | |||
4187 | vcs->v4l_device = video_device_alloc(); | ||
4188 | if (!vcs->v4l_device) { | ||
4189 | vino_module_cleanup(vino_init_stage); | ||
4190 | return -ENOMEM; | ||
4191 | } | ||
4192 | vino_init_stage++; | ||
4193 | |||
4194 | memcpy(vcs->v4l_device, &v4l_device_template, | ||
4195 | sizeof(struct video_device)); | ||
4196 | strcpy(vcs->v4l_device->name, name); | ||
4197 | vcs->v4l_device->release = video_device_release; | ||
4198 | |||
4199 | video_set_drvdata(vcs->v4l_device, vcs); | ||
4200 | |||
4201 | return 0; | ||
4202 | } | ||
4203 | |||
4204 | static int __init vino_module_init(void) | ||
4205 | { | ||
4206 | int ret; | ||
4207 | |||
4208 | printk(KERN_INFO "SGI VINO driver version %s\n", | ||
4209 | VINO_MODULE_VERSION); | ||
4210 | |||
4211 | ret = vino_probe(); | ||
4212 | if (ret) | ||
4213 | return ret; | ||
4214 | |||
4215 | ret = vino_init(); | ||
4216 | if (ret) | ||
4217 | return ret; | ||
4218 | |||
4219 | /* initialize data structures */ | ||
287 | 4220 | ||
288 | if (request_irq(SGI_VINO_IRQ, vino_interrupt, 0, vinostr, NULL)) { | 4221 | spin_lock_init(&vino_drvdata->vino_lock); |
289 | printk(KERN_ERR "VINO: irq%02d registration failed\n", | 4222 | spin_lock_init(&vino_drvdata->input_lock); |
4223 | |||
4224 | ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A, | ||
4225 | vino_v4l_device_name_a); | ||
4226 | if (ret) | ||
4227 | return ret; | ||
4228 | |||
4229 | ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B, | ||
4230 | vino_v4l_device_name_b); | ||
4231 | if (ret) | ||
4232 | return ret; | ||
4233 | |||
4234 | /* initialize hardware and register V4L devices */ | ||
4235 | |||
4236 | ret = request_irq(SGI_VINO_IRQ, vino_interrupt, 0, | ||
4237 | vino_driver_description, NULL); | ||
4238 | if (ret) { | ||
4239 | printk(KERN_ERR "VINO: requesting IRQ %02d failed\n", | ||
290 | SGI_VINO_IRQ); | 4240 | SGI_VINO_IRQ); |
291 | ret = -EAGAIN; | 4241 | vino_module_cleanup(vino_init_stage); |
292 | goto out_free_page; | 4242 | return -EAGAIN; |
293 | } | 4243 | } |
4244 | vino_init_stage++; | ||
294 | 4245 | ||
295 | ret = vino_i2c_add_bus(); | 4246 | ret = vino_i2c_add_bus(); |
296 | if (ret) { | 4247 | if (ret) { |
297 | printk(KERN_ERR "VINO: I2C bus registration failed\n"); | 4248 | printk(KERN_ERR "VINO I2C bus registration failed\n"); |
298 | goto out_free_irq; | 4249 | vino_module_cleanup(vino_init_stage); |
4250 | return ret; | ||
299 | } | 4251 | } |
4252 | vino_init_stage++; | ||
300 | 4253 | ||
301 | if (video_register_device(&Vino->chA.vdev, VFL_TYPE_GRABBER, -1) < 0) { | 4254 | ret = video_register_device(vino_drvdata->a.v4l_device, |
302 | printk("%s, chnl %d: device registration failed.\n", | 4255 | VFL_TYPE_GRABBER, -1); |
303 | Vino->chA.vdev.name, Vino->chA.chan); | 4256 | if (ret < 0) { |
304 | ret = -EINVAL; | 4257 | printk(KERN_ERR "VINO channel A Video4Linux-device " |
305 | goto out_i2c_del_bus; | 4258 | "registration failed\n"); |
4259 | vino_module_cleanup(vino_init_stage); | ||
4260 | return -EINVAL; | ||
306 | } | 4261 | } |
307 | if (video_register_device(&Vino->chB.vdev, VFL_TYPE_GRABBER, -1) < 0) { | 4262 | vino_init_stage++; |
308 | printk("%s, chnl %d: device registration failed.\n", | 4263 | |
309 | Vino->chB.vdev.name, Vino->chB.chan); | 4264 | ret = video_register_device(vino_drvdata->b.v4l_device, |
310 | ret = -EINVAL; | 4265 | VFL_TYPE_GRABBER, -1); |
311 | goto out_unregister_vdev; | 4266 | if (ret < 0) { |
4267 | printk(KERN_ERR "VINO channel B Video4Linux-device " | ||
4268 | "registration failed\n"); | ||
4269 | vino_module_cleanup(vino_init_stage); | ||
4270 | return -EINVAL; | ||
312 | } | 4271 | } |
4272 | vino_init_stage++; | ||
313 | 4273 | ||
314 | return 0; | 4274 | #if defined(CONFIG_KMOD) && defined(MODULE) |
4275 | request_module("saa7191"); | ||
4276 | request_module("indycam"); | ||
4277 | #endif | ||
315 | 4278 | ||
316 | out_unregister_vdev: | 4279 | dprintk("init complete!\n"); |
317 | video_unregister_device(&Vino->chA.vdev); | ||
318 | out_i2c_del_bus: | ||
319 | vino_i2c_del_bus(); | ||
320 | out_free_irq: | ||
321 | free_irq(SGI_VINO_IRQ, NULL); | ||
322 | out_free_page: | ||
323 | free_page(Vino->dummy_page); | ||
324 | out_free_vino: | ||
325 | kfree(Vino); | ||
326 | out_unmap: | ||
327 | iounmap(vino); | ||
328 | 4280 | ||
329 | return ret; | 4281 | return 0; |
330 | } | 4282 | } |
331 | 4283 | ||
332 | static void __exit vino_exit(void) | 4284 | static void __exit vino_module_exit(void) |
333 | { | 4285 | { |
334 | video_unregister_device(&Vino->chA.vdev); | 4286 | dprintk("exiting, stage = %d ...\n", vino_init_stage); |
335 | video_unregister_device(&Vino->chB.vdev); | 4287 | vino_module_cleanup(vino_init_stage); |
336 | vino_i2c_del_bus(); | 4288 | dprintk("cleanup complete, exit!\n"); |
337 | free_irq(SGI_VINO_IRQ, NULL); | ||
338 | free_page(Vino->dummy_page); | ||
339 | kfree(Vino); | ||
340 | iounmap(vino); | ||
341 | } | 4289 | } |
342 | 4290 | ||
343 | module_init(vino_init); | 4291 | module_init(vino_module_init); |
344 | module_exit(vino_exit); | 4292 | module_exit(vino_module_exit); |
345 | |||
346 | MODULE_DESCRIPTION("Video4Linux driver for SGI Indy VINO (IndyCam)"); | ||
347 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/vino.h b/drivers/media/video/vino.h index d2fce472f35a..de2d615ae7c9 100644 --- a/drivers/media/video/vino.h +++ b/drivers/media/video/vino.h | |||
@@ -1,13 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for the VINO (Video In No Out) system found in SGI Indys. | ||
3 | * | ||
4 | * 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 | * | ||
2 | * Copyright (C) 1999 Ulf Karlsson <ulfc@bun.falkenberg.se> | 7 | * Copyright (C) 1999 Ulf Karlsson <ulfc@bun.falkenberg.se> |
3 | * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org> | 8 | * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org> |
4 | */ | 9 | */ |
5 | 10 | ||
6 | #ifndef VINO_H | 11 | #ifndef _VINO_H_ |
7 | #define VINO_H | 12 | #define _VINO_H_ |
8 | 13 | ||
9 | #define VINO_BASE 0x00080000 /* Vino is in the EISA address space, | 14 | #define VINO_BASE 0x00080000 /* Vino is in the EISA address space, |
10 | * but it is not an EISA bus card */ | 15 | * but it is not an EISA bus card */ |
16 | #define VINO_PAGE_SIZE 4096 | ||
11 | 17 | ||
12 | struct sgi_vino_channel { | 18 | struct sgi_vino_channel { |
13 | u32 _pad_alpha; | 19 | u32 _pad_alpha; |
@@ -21,8 +27,9 @@ struct sgi_vino_channel { | |||
21 | u32 _pad_clip_end; | 27 | u32 _pad_clip_end; |
22 | volatile u32 clip_end; | 28 | volatile u32 clip_end; |
23 | 29 | ||
30 | #define VINO_FRAMERT_FULL 0xfff | ||
24 | #define VINO_FRAMERT_PAL (1<<0) /* 0=NTSC 1=PAL */ | 31 | #define VINO_FRAMERT_PAL (1<<0) /* 0=NTSC 1=PAL */ |
25 | #define VINO_FRAMERT_RT(x) (((x) & 0x1fff) << 1) /* bits 1:12 */ | 32 | #define VINO_FRAMERT_RT(x) (((x) & 0xfff) << 1) /* bits 1:12 */ |
26 | u32 _pad_frame_rate; | 33 | u32 _pad_frame_rate; |
27 | volatile u32 frame_rate; | 34 | volatile u32 frame_rate; |
28 | 35 | ||
@@ -67,18 +74,18 @@ struct sgi_vino { | |||
67 | volatile u32 rev_id; | 74 | volatile u32 rev_id; |
68 | 75 | ||
69 | #define VINO_CTRL_LITTLE_ENDIAN (1<<0) | 76 | #define VINO_CTRL_LITTLE_ENDIAN (1<<0) |
70 | #define VINO_CTRL_A_FIELD_TRANS_INT (1<<1) /* Field transferred int */ | 77 | #define VINO_CTRL_A_EOF_INT (1<<1) /* Field transferred int */ |
71 | #define VINO_CTRL_A_FIFO_OF_INT (1<<2) /* FIFO overflow int */ | 78 | #define VINO_CTRL_A_FIFO_INT (1<<2) /* FIFO overflow int */ |
72 | #define VINO_CTRL_A_END_DESC_TBL_INT (1<<3) /* End of desc table int */ | 79 | #define VINO_CTRL_A_EOD_INT (1<<3) /* End of desc table int */ |
73 | #define VINO_CTRL_A_INT (VINO_CTRL_A_FIELD_TRANS_INT | \ | 80 | #define VINO_CTRL_A_INT (VINO_CTRL_A_EOF_INT | \ |
74 | VINO_CTRL_A_FIFO_OF_INT | \ | 81 | VINO_CTRL_A_FIFO_INT | \ |
75 | VINO_CTRL_A_END_DESC_TBL_INT) | 82 | VINO_CTRL_A_EOD_INT) |
76 | #define VINO_CTRL_B_FIELD_TRANS_INT (1<<4) /* Field transferred int */ | 83 | #define VINO_CTRL_B_EOF_INT (1<<4) /* Field transferred int */ |
77 | #define VINO_CTRL_B_FIFO_OF_INT (1<<5) /* FIFO overflow int */ | 84 | #define VINO_CTRL_B_FIFO_INT (1<<5) /* FIFO overflow int */ |
78 | #define VINO_CTRL_B_END_DESC_TBL_INT (1<<6) /* End of desc table int */ | 85 | #define VINO_CTRL_B_EOD_INT (1<<6) /* End of desc table int */ |
79 | #define VINO_CTRL_B_INT (VINO_CTRL_B_FIELD_TRANS_INT | \ | 86 | #define VINO_CTRL_B_INT (VINO_CTRL_B_EOF_INT | \ |
80 | VINO_CTRL_B_FIFO_OF_INT | \ | 87 | VINO_CTRL_B_FIFO_INT | \ |
81 | VINO_CTRL_B_END_DESC_TBL_INT) | 88 | VINO_CTRL_B_EOD_INT) |
82 | #define VINO_CTRL_A_DMA_ENBL (1<<7) | 89 | #define VINO_CTRL_A_DMA_ENBL (1<<7) |
83 | #define VINO_CTRL_A_INTERLEAVE_ENBL (1<<8) | 90 | #define VINO_CTRL_A_INTERLEAVE_ENBL (1<<8) |
84 | #define VINO_CTRL_A_SYNC_ENBL (1<<9) | 91 | #define VINO_CTRL_A_SYNC_ENBL (1<<9) |
@@ -104,18 +111,18 @@ struct sgi_vino { | |||
104 | u32 _pad_control; | 111 | u32 _pad_control; |
105 | volatile u32 control; | 112 | volatile u32 control; |
106 | 113 | ||
107 | #define VINO_INTSTAT_A_FIELD_TRANS (1<<0) /* Field transferred int */ | 114 | #define VINO_INTSTAT_A_EOF (1<<0) /* Field transferred int */ |
108 | #define VINO_INTSTAT_A_FIFO_OF (1<<1) /* FIFO overflow int */ | 115 | #define VINO_INTSTAT_A_FIFO (1<<1) /* FIFO overflow int */ |
109 | #define VINO_INTSTAT_A_END_DESC_TBL (1<<2) /* End of desc table int */ | 116 | #define VINO_INTSTAT_A_EOD (1<<2) /* End of desc table int */ |
110 | #define VINO_INTSTAT_A (VINO_INTSTAT_A_FIELD_TRANS | \ | 117 | #define VINO_INTSTAT_A (VINO_INTSTAT_A_EOF | \ |
111 | VINO_INTSTAT_A_FIFO_OF | \ | 118 | VINO_INTSTAT_A_FIFO | \ |
112 | VINO_INTSTAT_A_END_DESC_TBL) | 119 | VINO_INTSTAT_A_EOD) |
113 | #define VINO_INTSTAT_B_FIELD_TRANS (1<<3) /* Field transferred int */ | 120 | #define VINO_INTSTAT_B_EOF (1<<3) /* Field transferred int */ |
114 | #define VINO_INTSTAT_B_FIFO_OF (1<<4) /* FIFO overflow int */ | 121 | #define VINO_INTSTAT_B_FIFO (1<<4) /* FIFO overflow int */ |
115 | #define VINO_INTSTAT_B_END_DESC_TBL (1<<5) /* End of desc table int */ | 122 | #define VINO_INTSTAT_B_EOD (1<<5) /* End of desc table int */ |
116 | #define VINO_INTSTAT_B (VINO_INTSTAT_B_FIELD_TRANS | \ | 123 | #define VINO_INTSTAT_B (VINO_INTSTAT_B_EOF | \ |
117 | VINO_INTSTAT_B_FIFO_OF | \ | 124 | VINO_INTSTAT_B_FIFO | \ |
118 | VINO_INTSTAT_B_END_DESC_TBL) | 125 | VINO_INTSTAT_B_EOD) |
119 | u32 _pad_intr_status; | 126 | u32 _pad_intr_status; |
120 | volatile u32 intr_status; | 127 | volatile u32 intr_status; |
121 | 128 | ||
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 0a8165974ba7..0a117c61cd18 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c | |||
@@ -2,6 +2,8 @@ | |||
2 | * linux/drivers/mmc/mmc.c | 2 | * linux/drivers/mmc/mmc.c |
3 | * | 3 | * |
4 | * Copyright (C) 2003-2004 Russell King, All Rights Reserved. | 4 | * Copyright (C) 2003-2004 Russell King, All Rights Reserved. |
5 | * SD support Copyright (C) 2004 Ian Molton, All Rights Reserved. | ||
6 | * SD support Copyright (C) 2005 Pierre Ossman, All Rights Reserved. | ||
5 | * | 7 | * |
6 | * This program is free software; you can redistribute it and/or modify | 8 | * 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 | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -16,6 +18,8 @@ | |||
16 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
17 | #include <linux/pagemap.h> | 19 | #include <linux/pagemap.h> |
18 | #include <linux/err.h> | 20 | #include <linux/err.h> |
21 | #include <asm/scatterlist.h> | ||
22 | #include <linux/scatterlist.h> | ||
19 | 23 | ||
20 | #include <linux/mmc/card.h> | 24 | #include <linux/mmc/card.h> |
21 | #include <linux/mmc/host.h> | 25 | #include <linux/mmc/host.h> |
@@ -172,7 +176,81 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries | |||
172 | 176 | ||
173 | EXPORT_SYMBOL(mmc_wait_for_cmd); | 177 | EXPORT_SYMBOL(mmc_wait_for_cmd); |
174 | 178 | ||
179 | /** | ||
180 | * mmc_wait_for_app_cmd - start an application command and wait for | ||
181 | completion | ||
182 | * @host: MMC host to start command | ||
183 | * @rca: RCA to send MMC_APP_CMD to | ||
184 | * @cmd: MMC command to start | ||
185 | * @retries: maximum number of retries | ||
186 | * | ||
187 | * Sends a MMC_APP_CMD, checks the card response, sends the command | ||
188 | * in the parameter and waits for it to complete. Return any error | ||
189 | * that occurred while the command was executing. Do not attempt to | ||
190 | * parse the response. | ||
191 | */ | ||
192 | int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca, | ||
193 | struct mmc_command *cmd, int retries) | ||
194 | { | ||
195 | struct mmc_request mrq; | ||
196 | struct mmc_command appcmd; | ||
197 | |||
198 | int i, err; | ||
199 | |||
200 | BUG_ON(host->card_busy == NULL); | ||
201 | BUG_ON(retries < 0); | ||
202 | |||
203 | err = MMC_ERR_INVALID; | ||
204 | |||
205 | /* | ||
206 | * We have to resend MMC_APP_CMD for each attempt so | ||
207 | * we cannot use the retries field in mmc_command. | ||
208 | */ | ||
209 | for (i = 0;i <= retries;i++) { | ||
210 | memset(&mrq, 0, sizeof(struct mmc_request)); | ||
211 | |||
212 | appcmd.opcode = MMC_APP_CMD; | ||
213 | appcmd.arg = rca << 16; | ||
214 | appcmd.flags = MMC_RSP_R1; | ||
215 | appcmd.retries = 0; | ||
216 | memset(appcmd.resp, 0, sizeof(appcmd.resp)); | ||
217 | appcmd.data = NULL; | ||
218 | |||
219 | mrq.cmd = &appcmd; | ||
220 | appcmd.data = NULL; | ||
221 | |||
222 | mmc_wait_for_req(host, &mrq); | ||
223 | |||
224 | if (appcmd.error) { | ||
225 | err = appcmd.error; | ||
226 | continue; | ||
227 | } | ||
228 | |||
229 | /* Check that card supported application commands */ | ||
230 | if (!(appcmd.resp[0] & R1_APP_CMD)) | ||
231 | return MMC_ERR_FAILED; | ||
232 | |||
233 | memset(&mrq, 0, sizeof(struct mmc_request)); | ||
234 | |||
235 | memset(cmd->resp, 0, sizeof(cmd->resp)); | ||
236 | cmd->retries = 0; | ||
237 | |||
238 | mrq.cmd = cmd; | ||
239 | cmd->data = NULL; | ||
175 | 240 | ||
241 | mmc_wait_for_req(host, &mrq); | ||
242 | |||
243 | err = cmd->error; | ||
244 | if (cmd->error == MMC_ERR_NONE) | ||
245 | break; | ||
246 | } | ||
247 | |||
248 | return err; | ||
249 | } | ||
250 | |||
251 | EXPORT_SYMBOL(mmc_wait_for_app_cmd); | ||
252 | |||
253 | static int mmc_select_card(struct mmc_host *host, struct mmc_card *card); | ||
176 | 254 | ||
177 | /** | 255 | /** |
178 | * __mmc_claim_host - exclusively claim a host | 256 | * __mmc_claim_host - exclusively claim a host |
@@ -206,16 +284,10 @@ int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card) | |||
206 | spin_unlock_irqrestore(&host->lock, flags); | 284 | spin_unlock_irqrestore(&host->lock, flags); |
207 | remove_wait_queue(&host->wq, &wait); | 285 | remove_wait_queue(&host->wq, &wait); |
208 | 286 | ||
209 | if (card != (void *)-1 && host->card_selected != card) { | 287 | if (card != (void *)-1) { |
210 | struct mmc_command cmd; | 288 | err = mmc_select_card(host, card); |
211 | 289 | if (err != MMC_ERR_NONE) | |
212 | host->card_selected = card; | 290 | return err; |
213 | |||
214 | cmd.opcode = MMC_SELECT_CARD; | ||
215 | cmd.arg = card->rca << 16; | ||
216 | cmd.flags = MMC_RSP_R1; | ||
217 | |||
218 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); | ||
219 | } | 291 | } |
220 | 292 | ||
221 | return err; | 293 | return err; |
@@ -245,6 +317,63 @@ void mmc_release_host(struct mmc_host *host) | |||
245 | 317 | ||
246 | EXPORT_SYMBOL(mmc_release_host); | 318 | EXPORT_SYMBOL(mmc_release_host); |
247 | 319 | ||
320 | static int mmc_select_card(struct mmc_host *host, struct mmc_card *card) | ||
321 | { | ||
322 | int err; | ||
323 | struct mmc_command cmd; | ||
324 | |||
325 | BUG_ON(host->card_busy == NULL); | ||
326 | |||
327 | if (host->card_selected == card) | ||
328 | return MMC_ERR_NONE; | ||
329 | |||
330 | host->card_selected = card; | ||
331 | |||
332 | cmd.opcode = MMC_SELECT_CARD; | ||
333 | cmd.arg = card->rca << 16; | ||
334 | cmd.flags = MMC_RSP_R1; | ||
335 | |||
336 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); | ||
337 | if (err != MMC_ERR_NONE) | ||
338 | return err; | ||
339 | |||
340 | /* | ||
341 | * Default bus width is 1 bit. | ||
342 | */ | ||
343 | host->ios.bus_width = MMC_BUS_WIDTH_1; | ||
344 | |||
345 | /* | ||
346 | * We can only change the bus width of the selected | ||
347 | * card so therefore we have to put the handling | ||
348 | * here. | ||
349 | */ | ||
350 | if (host->caps & MMC_CAP_4_BIT_DATA) { | ||
351 | /* | ||
352 | * The card is in 1 bit mode by default so | ||
353 | * we only need to change if it supports the | ||
354 | * wider version. | ||
355 | */ | ||
356 | if (mmc_card_sd(card) && | ||
357 | (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { | ||
358 | struct mmc_command cmd; | ||
359 | cmd.opcode = SD_APP_SET_BUS_WIDTH; | ||
360 | cmd.arg = SD_BUS_WIDTH_4; | ||
361 | cmd.flags = MMC_RSP_R1; | ||
362 | |||
363 | err = mmc_wait_for_app_cmd(host, card->rca, &cmd, | ||
364 | CMD_RETRIES); | ||
365 | if (err != MMC_ERR_NONE) | ||
366 | return err; | ||
367 | |||
368 | host->ios.bus_width = MMC_BUS_WIDTH_4; | ||
369 | } | ||
370 | } | ||
371 | |||
372 | host->ops->set_ios(host, &host->ios); | ||
373 | |||
374 | return MMC_ERR_NONE; | ||
375 | } | ||
376 | |||
248 | /* | 377 | /* |
249 | * Ensure that no card is selected. | 378 | * Ensure that no card is selected. |
250 | */ | 379 | */ |
@@ -322,48 +451,69 @@ static void mmc_decode_cid(struct mmc_card *card) | |||
322 | 451 | ||
323 | memset(&card->cid, 0, sizeof(struct mmc_cid)); | 452 | memset(&card->cid, 0, sizeof(struct mmc_cid)); |
324 | 453 | ||
325 | /* | 454 | if (mmc_card_sd(card)) { |
326 | * The selection of the format here is guesswork based upon | 455 | /* |
327 | * information people have sent to date. | 456 | * SD doesn't currently have a version field so we will |
328 | */ | 457 | * have to assume we can parse this. |
329 | switch (card->csd.mmca_vsn) { | 458 | */ |
330 | case 0: /* MMC v1.? */ | 459 | card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); |
331 | case 1: /* MMC v1.4 */ | 460 | card->cid.oemid = UNSTUFF_BITS(resp, 104, 16); |
332 | card->cid.manfid = UNSTUFF_BITS(resp, 104, 24); | 461 | card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); |
333 | card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); | 462 | card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); |
334 | card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); | 463 | card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); |
335 | card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); | 464 | card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); |
336 | card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); | 465 | card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); |
337 | card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); | 466 | card->cid.hwrev = UNSTUFF_BITS(resp, 60, 4); |
338 | card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); | 467 | card->cid.fwrev = UNSTUFF_BITS(resp, 56, 4); |
339 | card->cid.prod_name[6] = UNSTUFF_BITS(resp, 48, 8); | 468 | card->cid.serial = UNSTUFF_BITS(resp, 24, 32); |
340 | card->cid.hwrev = UNSTUFF_BITS(resp, 44, 4); | 469 | card->cid.year = UNSTUFF_BITS(resp, 12, 8); |
341 | card->cid.fwrev = UNSTUFF_BITS(resp, 40, 4); | 470 | card->cid.month = UNSTUFF_BITS(resp, 8, 4); |
342 | card->cid.serial = UNSTUFF_BITS(resp, 16, 24); | 471 | |
343 | card->cid.month = UNSTUFF_BITS(resp, 12, 4); | 472 | card->cid.year += 2000; /* SD cards year offset */ |
344 | card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; | 473 | } else { |
345 | break; | 474 | /* |
346 | 475 | * The selection of the format here is based upon published | |
347 | case 2: /* MMC v2.x ? */ | 476 | * specs from sandisk and from what people have reported. |
348 | case 3: /* MMC v3.x ? */ | 477 | */ |
349 | card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); | 478 | switch (card->csd.mmca_vsn) { |
350 | card->cid.oemid = UNSTUFF_BITS(resp, 104, 16); | 479 | case 0: /* MMC v1.0 - v1.2 */ |
351 | card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); | 480 | case 1: /* MMC v1.4 */ |
352 | card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); | 481 | card->cid.manfid = UNSTUFF_BITS(resp, 104, 24); |
353 | card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); | 482 | card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); |
354 | card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); | 483 | card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); |
355 | card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); | 484 | card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); |
356 | card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); | 485 | card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); |
357 | card->cid.serial = UNSTUFF_BITS(resp, 16, 32); | 486 | card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); |
358 | card->cid.month = UNSTUFF_BITS(resp, 12, 4); | 487 | card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); |
359 | card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; | 488 | card->cid.prod_name[6] = UNSTUFF_BITS(resp, 48, 8); |
360 | break; | 489 | card->cid.hwrev = UNSTUFF_BITS(resp, 44, 4); |
361 | 490 | card->cid.fwrev = UNSTUFF_BITS(resp, 40, 4); | |
362 | default: | 491 | card->cid.serial = UNSTUFF_BITS(resp, 16, 24); |
363 | printk("%s: card has unknown MMCA version %d\n", | 492 | card->cid.month = UNSTUFF_BITS(resp, 12, 4); |
364 | mmc_hostname(card->host), card->csd.mmca_vsn); | 493 | card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; |
365 | mmc_card_set_bad(card); | 494 | break; |
366 | break; | 495 | |
496 | case 2: /* MMC v2.0 - v2.2 */ | ||
497 | case 3: /* MMC v3.1 - v3.3 */ | ||
498 | card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); | ||
499 | card->cid.oemid = UNSTUFF_BITS(resp, 104, 16); | ||
500 | card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); | ||
501 | card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); | ||
502 | card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); | ||
503 | card->cid.prod_name[3] = UNSTUFF_BITS(resp, 72, 8); | ||
504 | card->cid.prod_name[4] = UNSTUFF_BITS(resp, 64, 8); | ||
505 | card->cid.prod_name[5] = UNSTUFF_BITS(resp, 56, 8); | ||
506 | card->cid.serial = UNSTUFF_BITS(resp, 16, 32); | ||
507 | card->cid.month = UNSTUFF_BITS(resp, 12, 4); | ||
508 | card->cid.year = UNSTUFF_BITS(resp, 8, 4) + 1997; | ||
509 | break; | ||
510 | |||
511 | default: | ||
512 | printk("%s: card has unknown MMCA version %d\n", | ||
513 | mmc_hostname(card->host), card->csd.mmca_vsn); | ||
514 | mmc_card_set_bad(card); | ||
515 | break; | ||
516 | } | ||
367 | } | 517 | } |
368 | } | 518 | } |
369 | 519 | ||
@@ -376,34 +526,86 @@ static void mmc_decode_csd(struct mmc_card *card) | |||
376 | unsigned int e, m, csd_struct; | 526 | unsigned int e, m, csd_struct; |
377 | u32 *resp = card->raw_csd; | 527 | u32 *resp = card->raw_csd; |
378 | 528 | ||
379 | /* | 529 | if (mmc_card_sd(card)) { |
380 | * We only understand CSD structure v1.1 and v2. | 530 | csd_struct = UNSTUFF_BITS(resp, 126, 2); |
381 | * v2 has extra information in bits 15, 11 and 10. | 531 | if (csd_struct != 0) { |
382 | */ | 532 | printk("%s: unrecognised CSD structure version %d\n", |
383 | csd_struct = UNSTUFF_BITS(resp, 126, 2); | 533 | mmc_hostname(card->host), csd_struct); |
384 | if (csd_struct != 1 && csd_struct != 2) { | 534 | mmc_card_set_bad(card); |
385 | printk("%s: unrecognised CSD structure version %d\n", | 535 | return; |
386 | mmc_hostname(card->host), csd_struct); | 536 | } |
387 | mmc_card_set_bad(card); | 537 | |
388 | return; | 538 | m = UNSTUFF_BITS(resp, 115, 4); |
539 | e = UNSTUFF_BITS(resp, 112, 3); | ||
540 | csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; | ||
541 | csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; | ||
542 | |||
543 | m = UNSTUFF_BITS(resp, 99, 4); | ||
544 | e = UNSTUFF_BITS(resp, 96, 3); | ||
545 | csd->max_dtr = tran_exp[e] * tran_mant[m]; | ||
546 | csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); | ||
547 | |||
548 | e = UNSTUFF_BITS(resp, 47, 3); | ||
549 | m = UNSTUFF_BITS(resp, 62, 12); | ||
550 | csd->capacity = (1 + m) << (e + 2); | ||
551 | |||
552 | csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); | ||
553 | } else { | ||
554 | /* | ||
555 | * We only understand CSD structure v1.1 and v1.2. | ||
556 | * v1.2 has extra information in bits 15, 11 and 10. | ||
557 | */ | ||
558 | csd_struct = UNSTUFF_BITS(resp, 126, 2); | ||
559 | if (csd_struct != 1 && csd_struct != 2) { | ||
560 | printk("%s: unrecognised CSD structure version %d\n", | ||
561 | mmc_hostname(card->host), csd_struct); | ||
562 | mmc_card_set_bad(card); | ||
563 | return; | ||
564 | } | ||
565 | |||
566 | csd->mmca_vsn = UNSTUFF_BITS(resp, 122, 4); | ||
567 | m = UNSTUFF_BITS(resp, 115, 4); | ||
568 | e = UNSTUFF_BITS(resp, 112, 3); | ||
569 | csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; | ||
570 | csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; | ||
571 | |||
572 | m = UNSTUFF_BITS(resp, 99, 4); | ||
573 | e = UNSTUFF_BITS(resp, 96, 3); | ||
574 | csd->max_dtr = tran_exp[e] * tran_mant[m]; | ||
575 | csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); | ||
576 | |||
577 | e = UNSTUFF_BITS(resp, 47, 3); | ||
578 | m = UNSTUFF_BITS(resp, 62, 12); | ||
579 | csd->capacity = (1 + m) << (e + 2); | ||
580 | |||
581 | csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); | ||
389 | } | 582 | } |
583 | } | ||
390 | 584 | ||
391 | csd->mmca_vsn = UNSTUFF_BITS(resp, 122, 4); | 585 | /* |
392 | m = UNSTUFF_BITS(resp, 115, 4); | 586 | * Given a 64-bit response, decode to our card SCR structure. |
393 | e = UNSTUFF_BITS(resp, 112, 3); | 587 | */ |
394 | csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; | 588 | static void mmc_decode_scr(struct mmc_card *card) |
395 | csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; | 589 | { |
590 | struct sd_scr *scr = &card->scr; | ||
591 | unsigned int scr_struct; | ||
592 | u32 resp[4]; | ||
593 | |||
594 | BUG_ON(!mmc_card_sd(card)); | ||
396 | 595 | ||
397 | m = UNSTUFF_BITS(resp, 99, 4); | 596 | resp[3] = card->raw_scr[1]; |
398 | e = UNSTUFF_BITS(resp, 96, 3); | 597 | resp[2] = card->raw_scr[0]; |
399 | csd->max_dtr = tran_exp[e] * tran_mant[m]; | ||
400 | csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); | ||
401 | 598 | ||
402 | e = UNSTUFF_BITS(resp, 47, 3); | 599 | scr_struct = UNSTUFF_BITS(resp, 60, 4); |
403 | m = UNSTUFF_BITS(resp, 62, 12); | 600 | if (scr_struct != 0) { |
404 | csd->capacity = (1 + m) << (e + 2); | 601 | printk("%s: unrecognised SCR structure version %d\n", |
602 | mmc_hostname(card->host), scr_struct); | ||
603 | mmc_card_set_bad(card); | ||
604 | return; | ||
605 | } | ||
405 | 606 | ||
406 | csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); | 607 | scr->sda_vsn = UNSTUFF_BITS(resp, 56, 4); |
608 | scr->bus_widths = UNSTUFF_BITS(resp, 48, 4); | ||
407 | } | 609 | } |
408 | 610 | ||
409 | /* | 611 | /* |
@@ -487,6 +689,7 @@ static void mmc_power_up(struct mmc_host *host) | |||
487 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; | 689 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; |
488 | host->ios.chip_select = MMC_CS_DONTCARE; | 690 | host->ios.chip_select = MMC_CS_DONTCARE; |
489 | host->ios.power_mode = MMC_POWER_UP; | 691 | host->ios.power_mode = MMC_POWER_UP; |
692 | host->ios.bus_width = MMC_BUS_WIDTH_1; | ||
490 | host->ops->set_ios(host, &host->ios); | 693 | host->ops->set_ios(host, &host->ios); |
491 | 694 | ||
492 | mmc_delay(1); | 695 | mmc_delay(1); |
@@ -505,6 +708,7 @@ static void mmc_power_off(struct mmc_host *host) | |||
505 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; | 708 | host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; |
506 | host->ios.chip_select = MMC_CS_DONTCARE; | 709 | host->ios.chip_select = MMC_CS_DONTCARE; |
507 | host->ios.power_mode = MMC_POWER_OFF; | 710 | host->ios.power_mode = MMC_POWER_OFF; |
711 | host->ios.bus_width = MMC_BUS_WIDTH_1; | ||
508 | host->ops->set_ios(host, &host->ios); | 712 | host->ops->set_ios(host, &host->ios); |
509 | } | 713 | } |
510 | 714 | ||
@@ -536,6 +740,34 @@ static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) | |||
536 | return err; | 740 | return err; |
537 | } | 741 | } |
538 | 742 | ||
743 | static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) | ||
744 | { | ||
745 | struct mmc_command cmd; | ||
746 | int i, err = 0; | ||
747 | |||
748 | cmd.opcode = SD_APP_OP_COND; | ||
749 | cmd.arg = ocr; | ||
750 | cmd.flags = MMC_RSP_R3; | ||
751 | |||
752 | for (i = 100; i; i--) { | ||
753 | err = mmc_wait_for_app_cmd(host, 0, &cmd, CMD_RETRIES); | ||
754 | if (err != MMC_ERR_NONE) | ||
755 | break; | ||
756 | |||
757 | if (cmd.resp[0] & MMC_CARD_BUSY || ocr == 0) | ||
758 | break; | ||
759 | |||
760 | err = MMC_ERR_TIMEOUT; | ||
761 | |||
762 | mmc_delay(10); | ||
763 | } | ||
764 | |||
765 | if (rocr) | ||
766 | *rocr = cmd.resp[0]; | ||
767 | |||
768 | return err; | ||
769 | } | ||
770 | |||
539 | /* | 771 | /* |
540 | * Discover cards by requesting their CID. If this command | 772 | * Discover cards by requesting their CID. If this command |
541 | * times out, it is not an error; there are no further cards | 773 | * times out, it is not an error; there are no further cards |
@@ -579,13 +811,38 @@ static void mmc_discover_cards(struct mmc_host *host) | |||
579 | 811 | ||
580 | card->state &= ~MMC_STATE_DEAD; | 812 | card->state &= ~MMC_STATE_DEAD; |
581 | 813 | ||
582 | cmd.opcode = MMC_SET_RELATIVE_ADDR; | 814 | if (host->mode == MMC_MODE_SD) { |
583 | cmd.arg = card->rca << 16; | 815 | mmc_card_set_sd(card); |
584 | cmd.flags = MMC_RSP_R1; | ||
585 | 816 | ||
586 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); | 817 | cmd.opcode = SD_SEND_RELATIVE_ADDR; |
587 | if (err != MMC_ERR_NONE) | 818 | cmd.arg = 0; |
588 | mmc_card_set_dead(card); | 819 | cmd.flags = MMC_RSP_R1; |
820 | |||
821 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); | ||
822 | if (err != MMC_ERR_NONE) | ||
823 | mmc_card_set_dead(card); | ||
824 | else { | ||
825 | card->rca = cmd.resp[0] >> 16; | ||
826 | |||
827 | if (!host->ops->get_ro) { | ||
828 | printk(KERN_WARNING "%s: host does not " | ||
829 | "support reading read-only " | ||
830 | "switch. assuming write-enable.\n", | ||
831 | mmc_hostname(host)); | ||
832 | } else { | ||
833 | if (host->ops->get_ro(host)) | ||
834 | mmc_card_set_readonly(card); | ||
835 | } | ||
836 | } | ||
837 | } else { | ||
838 | cmd.opcode = MMC_SET_RELATIVE_ADDR; | ||
839 | cmd.arg = card->rca << 16; | ||
840 | cmd.flags = MMC_RSP_R1; | ||
841 | |||
842 | err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); | ||
843 | if (err != MMC_ERR_NONE) | ||
844 | mmc_card_set_dead(card); | ||
845 | } | ||
589 | } | 846 | } |
590 | } | 847 | } |
591 | 848 | ||
@@ -617,6 +874,79 @@ static void mmc_read_csds(struct mmc_host *host) | |||
617 | } | 874 | } |
618 | } | 875 | } |
619 | 876 | ||
877 | static void mmc_read_scrs(struct mmc_host *host) | ||
878 | { | ||
879 | int err; | ||
880 | struct mmc_card *card; | ||
881 | |||
882 | struct mmc_request mrq; | ||
883 | struct mmc_command cmd; | ||
884 | struct mmc_data data; | ||
885 | |||
886 | struct scatterlist sg; | ||
887 | |||
888 | list_for_each_entry(card, &host->cards, node) { | ||
889 | if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT)) | ||
890 | continue; | ||
891 | if (!mmc_card_sd(card)) | ||
892 | continue; | ||
893 | |||
894 | err = mmc_select_card(host, card); | ||
895 | if (err != MMC_ERR_NONE) { | ||
896 | mmc_card_set_dead(card); | ||
897 | continue; | ||
898 | } | ||
899 | |||
900 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
901 | |||
902 | cmd.opcode = MMC_APP_CMD; | ||
903 | cmd.arg = card->rca << 16; | ||
904 | cmd.flags = MMC_RSP_R1; | ||
905 | |||
906 | err = mmc_wait_for_cmd(host, &cmd, 0); | ||
907 | if ((err != MMC_ERR_NONE) || !(cmd.resp[0] & R1_APP_CMD)) { | ||
908 | mmc_card_set_dead(card); | ||
909 | continue; | ||
910 | } | ||
911 | |||
912 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
913 | |||
914 | cmd.opcode = SD_APP_SEND_SCR; | ||
915 | cmd.arg = 0; | ||
916 | cmd.flags = MMC_RSP_R1; | ||
917 | |||
918 | memset(&data, 0, sizeof(struct mmc_data)); | ||
919 | |||
920 | data.timeout_ns = card->csd.tacc_ns * 10; | ||
921 | data.timeout_clks = card->csd.tacc_clks * 10; | ||
922 | data.blksz_bits = 3; | ||
923 | data.blocks = 1; | ||
924 | data.flags = MMC_DATA_READ; | ||
925 | data.sg = &sg; | ||
926 | data.sg_len = 1; | ||
927 | |||
928 | memset(&mrq, 0, sizeof(struct mmc_request)); | ||
929 | |||
930 | mrq.cmd = &cmd; | ||
931 | mrq.data = &data; | ||
932 | |||
933 | sg_init_one(&sg, (u8*)card->raw_scr, 8); | ||
934 | |||
935 | err = mmc_wait_for_req(host, &mrq); | ||
936 | if (err != MMC_ERR_NONE) { | ||
937 | mmc_card_set_dead(card); | ||
938 | continue; | ||
939 | } | ||
940 | |||
941 | card->raw_scr[0] = ntohl(card->raw_scr[0]); | ||
942 | card->raw_scr[1] = ntohl(card->raw_scr[1]); | ||
943 | |||
944 | mmc_decode_scr(card); | ||
945 | } | ||
946 | |||
947 | mmc_deselect_cards(host); | ||
948 | } | ||
949 | |||
620 | static unsigned int mmc_calculate_clock(struct mmc_host *host) | 950 | static unsigned int mmc_calculate_clock(struct mmc_host *host) |
621 | { | 951 | { |
622 | struct mmc_card *card; | 952 | struct mmc_card *card; |
@@ -669,12 +999,24 @@ static void mmc_setup(struct mmc_host *host) | |||
669 | int err; | 999 | int err; |
670 | u32 ocr; | 1000 | u32 ocr; |
671 | 1001 | ||
1002 | host->mode = MMC_MODE_SD; | ||
1003 | |||
672 | mmc_power_up(host); | 1004 | mmc_power_up(host); |
673 | mmc_idle_cards(host); | 1005 | mmc_idle_cards(host); |
674 | 1006 | ||
675 | err = mmc_send_op_cond(host, 0, &ocr); | 1007 | err = mmc_send_app_op_cond(host, 0, &ocr); |
676 | if (err != MMC_ERR_NONE) | 1008 | |
677 | return; | 1009 | /* |
1010 | * If we fail to detect any SD cards then try | ||
1011 | * searching for MMC cards. | ||
1012 | */ | ||
1013 | if (err != MMC_ERR_NONE) { | ||
1014 | host->mode = MMC_MODE_MMC; | ||
1015 | |||
1016 | err = mmc_send_op_cond(host, 0, &ocr); | ||
1017 | if (err != MMC_ERR_NONE) | ||
1018 | return; | ||
1019 | } | ||
678 | 1020 | ||
679 | host->ocr = mmc_select_voltage(host, ocr); | 1021 | host->ocr = mmc_select_voltage(host, ocr); |
680 | 1022 | ||
@@ -714,7 +1056,10 @@ static void mmc_setup(struct mmc_host *host) | |||
714 | * all get the idea that they should be ready for CMD2. | 1056 | * all get the idea that they should be ready for CMD2. |
715 | * (My SanDisk card seems to need this.) | 1057 | * (My SanDisk card seems to need this.) |
716 | */ | 1058 | */ |
717 | mmc_send_op_cond(host, host->ocr, NULL); | 1059 | if (host->mode == MMC_MODE_SD) |
1060 | mmc_send_app_op_cond(host, host->ocr, NULL); | ||
1061 | else | ||
1062 | mmc_send_op_cond(host, host->ocr, NULL); | ||
718 | 1063 | ||
719 | mmc_discover_cards(host); | 1064 | mmc_discover_cards(host); |
720 | 1065 | ||
@@ -725,6 +1070,9 @@ static void mmc_setup(struct mmc_host *host) | |||
725 | host->ops->set_ios(host, &host->ios); | 1070 | host->ops->set_ios(host, &host->ios); |
726 | 1071 | ||
727 | mmc_read_csds(host); | 1072 | mmc_read_csds(host); |
1073 | |||
1074 | if (host->mode == MMC_MODE_SD) | ||
1075 | mmc_read_scrs(host); | ||
728 | } | 1076 | } |
729 | 1077 | ||
730 | 1078 | ||
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index d4eee99c2bf6..fa83f15fdf16 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c | |||
@@ -95,6 +95,10 @@ static int mmc_blk_open(struct inode *inode, struct file *filp) | |||
95 | if (md->usage == 2) | 95 | if (md->usage == 2) |
96 | check_disk_change(inode->i_bdev); | 96 | check_disk_change(inode->i_bdev); |
97 | ret = 0; | 97 | ret = 0; |
98 | |||
99 | if ((filp->f_mode & FMODE_WRITE) && | ||
100 | mmc_card_readonly(md->queue.card)) | ||
101 | ret = -EROFS; | ||
98 | } | 102 | } |
99 | 103 | ||
100 | return ret; | 104 | return ret; |
@@ -403,9 +407,10 @@ static int mmc_blk_probe(struct mmc_card *card) | |||
403 | if (err) | 407 | if (err) |
404 | goto out; | 408 | goto out; |
405 | 409 | ||
406 | printk(KERN_INFO "%s: %s %s %dKiB\n", | 410 | printk(KERN_INFO "%s: %s %s %dKiB %s\n", |
407 | md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), | 411 | md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), |
408 | (card->csd.capacity << card->csd.read_blkbits) / 1024); | 412 | (card->csd.capacity << card->csd.read_blkbits) / 1024, |
413 | mmc_card_readonly(card)?"(ro)":""); | ||
409 | 414 | ||
410 | mmc_set_drvdata(card, md); | 415 | mmc_set_drvdata(card, md); |
411 | add_disk(md->disk); | 416 | add_disk(md->disk); |
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c index ad8949810fc5..3f4a66ca9555 100644 --- a/drivers/mmc/mmc_sysfs.c +++ b/drivers/mmc/mmc_sysfs.c | |||
@@ -34,6 +34,7 @@ MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1], | |||
34 | card->raw_cid[2], card->raw_cid[3]); | 34 | card->raw_cid[2], card->raw_cid[3]); |
35 | MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], | 35 | MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], |
36 | card->raw_csd[2], card->raw_csd[3]); | 36 | card->raw_csd[2], card->raw_csd[3]); |
37 | MMC_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]); | ||
37 | MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); | 38 | MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); |
38 | MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev); | 39 | MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev); |
39 | MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev); | 40 | MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev); |
@@ -57,6 +58,8 @@ static struct device_attribute mmc_dev_attrs[] = { | |||
57 | __ATTR_NULL | 58 | __ATTR_NULL |
58 | }; | 59 | }; |
59 | 60 | ||
61 | static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr); | ||
62 | |||
60 | 63 | ||
61 | static void mmc_release_card(struct device *dev) | 64 | static void mmc_release_card(struct device *dev) |
62 | { | 65 | { |
@@ -207,10 +210,20 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host) | |||
207 | */ | 210 | */ |
208 | int mmc_register_card(struct mmc_card *card) | 211 | int mmc_register_card(struct mmc_card *card) |
209 | { | 212 | { |
213 | int ret; | ||
214 | |||
210 | snprintf(card->dev.bus_id, sizeof(card->dev.bus_id), | 215 | snprintf(card->dev.bus_id, sizeof(card->dev.bus_id), |
211 | "%s:%04x", mmc_hostname(card->host), card->rca); | 216 | "%s:%04x", mmc_hostname(card->host), card->rca); |
212 | 217 | ||
213 | return device_add(&card->dev); | 218 | ret = device_add(&card->dev); |
219 | if (ret == 0) { | ||
220 | if (mmc_card_sd(card)) { | ||
221 | ret = device_create_file(&card->dev, &mmc_dev_attr_scr); | ||
222 | if (ret) | ||
223 | device_del(&card->dev); | ||
224 | } | ||
225 | } | ||
226 | return ret; | ||
214 | } | 227 | } |
215 | 228 | ||
216 | /* | 229 | /* |
@@ -219,8 +232,12 @@ int mmc_register_card(struct mmc_card *card) | |||
219 | */ | 232 | */ |
220 | void mmc_remove_card(struct mmc_card *card) | 233 | void mmc_remove_card(struct mmc_card *card) |
221 | { | 234 | { |
222 | if (mmc_card_present(card)) | 235 | if (mmc_card_present(card)) { |
236 | if (mmc_card_sd(card)) | ||
237 | device_remove_file(&card->dev, &mmc_dev_attr_scr); | ||
238 | |||
223 | device_del(&card->dev); | 239 | device_del(&card->dev); |
240 | } | ||
224 | 241 | ||
225 | put_device(&card->dev); | 242 | put_device(&card->dev); |
226 | } | 243 | } |
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index b78beb1b0159..e99a53b09e32 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c | |||
@@ -362,6 +362,16 @@ static void pxamci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
362 | pxamci_start_cmd(host, mrq->cmd, cmdat); | 362 | pxamci_start_cmd(host, mrq->cmd, cmdat); |
363 | } | 363 | } |
364 | 364 | ||
365 | static int pxamci_get_ro(struct mmc_host *mmc) | ||
366 | { | ||
367 | struct pxamci_host *host = mmc_priv(mmc); | ||
368 | |||
369 | if (host->pdata && host->pdata->get_ro) | ||
370 | return host->pdata->get_ro(mmc->dev); | ||
371 | /* Host doesn't support read only detection so assume writeable */ | ||
372 | return 0; | ||
373 | } | ||
374 | |||
365 | static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | 375 | static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) |
366 | { | 376 | { |
367 | struct pxamci_host *host = mmc_priv(mmc); | 377 | struct pxamci_host *host = mmc_priv(mmc); |
@@ -401,6 +411,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
401 | 411 | ||
402 | static struct mmc_host_ops pxamci_ops = { | 412 | static struct mmc_host_ops pxamci_ops = { |
403 | .request = pxamci_request, | 413 | .request = pxamci_request, |
414 | .get_ro = pxamci_get_ro, | ||
404 | .set_ios = pxamci_set_ios, | 415 | .set_ios = pxamci_set_ios, |
405 | }; | 416 | }; |
406 | 417 | ||
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 08ae22aed9e8..dec01d38c782 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c | |||
@@ -720,11 +720,28 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data) | |||
720 | * calculate CRC. | 720 | * calculate CRC. |
721 | * | 721 | * |
722 | * Space for CRC must be included in the size. | 722 | * Space for CRC must be included in the size. |
723 | * Two bytes are needed for each data line. | ||
723 | */ | 724 | */ |
724 | blksize = (1 << data->blksz_bits) + 2; | 725 | if (host->bus_width == MMC_BUS_WIDTH_1) |
726 | { | ||
727 | blksize = (1 << data->blksz_bits) + 2; | ||
728 | |||
729 | wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0); | ||
730 | wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF); | ||
731 | } | ||
732 | else if (host->bus_width == MMC_BUS_WIDTH_4) | ||
733 | { | ||
734 | blksize = (1 << data->blksz_bits) + 2 * 4; | ||
725 | 735 | ||
726 | wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0); | 736 | wbsd_write_index(host, WBSD_IDX_PBSMSB, ((blksize >> 4) & 0xF0) |
727 | wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF); | 737 | | WBSD_DATA_WIDTH); |
738 | wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF); | ||
739 | } | ||
740 | else | ||
741 | { | ||
742 | data->error = MMC_ERR_INVALID; | ||
743 | return; | ||
744 | } | ||
728 | 745 | ||
729 | /* | 746 | /* |
730 | * Clear the FIFO. This is needed even for DMA | 747 | * Clear the FIFO. This is needed even for DMA |
@@ -960,9 +977,9 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) | |||
960 | struct wbsd_host* host = mmc_priv(mmc); | 977 | struct wbsd_host* host = mmc_priv(mmc); |
961 | u8 clk, setup, pwr; | 978 | u8 clk, setup, pwr; |
962 | 979 | ||
963 | DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u\n", | 980 | DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n", |
964 | ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, | 981 | ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select, |
965 | ios->vdd); | 982 | ios->vdd, ios->bus_width); |
966 | 983 | ||
967 | spin_lock_bh(&host->lock); | 984 | spin_lock_bh(&host->lock); |
968 | 985 | ||
@@ -1010,6 +1027,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) | |||
1010 | setup = wbsd_read_index(host, WBSD_IDX_SETUP); | 1027 | setup = wbsd_read_index(host, WBSD_IDX_SETUP); |
1011 | if (ios->chip_select == MMC_CS_HIGH) | 1028 | if (ios->chip_select == MMC_CS_HIGH) |
1012 | { | 1029 | { |
1030 | BUG_ON(ios->bus_width != MMC_BUS_WIDTH_1); | ||
1013 | setup |= WBSD_DAT3_H; | 1031 | setup |= WBSD_DAT3_H; |
1014 | host->flags |= WBSD_FIGNORE_DETECT; | 1032 | host->flags |= WBSD_FIGNORE_DETECT; |
1015 | } | 1033 | } |
@@ -1025,12 +1043,41 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) | |||
1025 | } | 1043 | } |
1026 | wbsd_write_index(host, WBSD_IDX_SETUP, setup); | 1044 | wbsd_write_index(host, WBSD_IDX_SETUP, setup); |
1027 | 1045 | ||
1046 | /* | ||
1047 | * Store bus width for later. Will be used when | ||
1048 | * setting up the data transfer. | ||
1049 | */ | ||
1050 | host->bus_width = ios->bus_width; | ||
1051 | |||
1028 | spin_unlock_bh(&host->lock); | 1052 | spin_unlock_bh(&host->lock); |
1029 | } | 1053 | } |
1030 | 1054 | ||
1055 | static int wbsd_get_ro(struct mmc_host* mmc) | ||
1056 | { | ||
1057 | struct wbsd_host* host = mmc_priv(mmc); | ||
1058 | u8 csr; | ||
1059 | |||
1060 | spin_lock_bh(&host->lock); | ||
1061 | |||
1062 | csr = inb(host->base + WBSD_CSR); | ||
1063 | csr |= WBSD_MSLED; | ||
1064 | outb(csr, host->base + WBSD_CSR); | ||
1065 | |||
1066 | mdelay(1); | ||
1067 | |||
1068 | csr = inb(host->base + WBSD_CSR); | ||
1069 | csr &= ~WBSD_MSLED; | ||
1070 | outb(csr, host->base + WBSD_CSR); | ||
1071 | |||
1072 | spin_unlock_bh(&host->lock); | ||
1073 | |||
1074 | return csr & WBSD_WRPT; | ||
1075 | } | ||
1076 | |||
1031 | static struct mmc_host_ops wbsd_ops = { | 1077 | static struct mmc_host_ops wbsd_ops = { |
1032 | .request = wbsd_request, | 1078 | .request = wbsd_request, |
1033 | .set_ios = wbsd_set_ios, | 1079 | .set_ios = wbsd_set_ios, |
1080 | .get_ro = wbsd_get_ro, | ||
1034 | }; | 1081 | }; |
1035 | 1082 | ||
1036 | /*****************************************************************************\ | 1083 | /*****************************************************************************\ |
@@ -1355,6 +1402,7 @@ static int __devinit wbsd_alloc_mmc(struct device* dev) | |||
1355 | mmc->f_min = 375000; | 1402 | mmc->f_min = 375000; |
1356 | mmc->f_max = 24000000; | 1403 | mmc->f_max = 24000000; |
1357 | mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; | 1404 | mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; |
1405 | mmc->caps = MMC_CAP_4_BIT_DATA; | ||
1358 | 1406 | ||
1359 | spin_lock_init(&host->lock); | 1407 | spin_lock_init(&host->lock); |
1360 | 1408 | ||
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h index 8af43549f5d5..9005b5241b3c 100644 --- a/drivers/mmc/wbsd.h +++ b/drivers/mmc/wbsd.h | |||
@@ -106,6 +106,8 @@ | |||
106 | #define WBSD_CLK_16M 0x02 | 106 | #define WBSD_CLK_16M 0x02 |
107 | #define WBSD_CLK_24M 0x03 | 107 | #define WBSD_CLK_24M 0x03 |
108 | 108 | ||
109 | #define WBSD_DATA_WIDTH 0x01 | ||
110 | |||
109 | #define WBSD_DAT3_H 0x08 | 111 | #define WBSD_DAT3_H 0x08 |
110 | #define WBSD_FIFO_RESET 0x04 | 112 | #define WBSD_FIFO_RESET 0x04 |
111 | #define WBSD_SOFT_RESET 0x02 | 113 | #define WBSD_SOFT_RESET 0x02 |
@@ -164,6 +166,7 @@ struct wbsd_host | |||
164 | int firsterr; /* See fifo functions */ | 166 | int firsterr; /* See fifo functions */ |
165 | 167 | ||
166 | u8 clk; /* Current clock speed */ | 168 | u8 clk; /* Current clock speed */ |
169 | unsigned char bus_width; /* Current bus width */ | ||
167 | 170 | ||
168 | int config; /* Config port */ | 171 | int config; /* Config port */ |
169 | u8 unlock_code; /* Code to unlock config */ | 172 | u8 unlock_code; /* Code to unlock config */ |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index eee5115658c8..04e54318bc6a 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -526,6 +526,7 @@ static void nand_wait_ready(struct mtd_info *mtd) | |||
526 | do { | 526 | do { |
527 | if (this->dev_ready(mtd)) | 527 | if (this->dev_ready(mtd)) |
528 | return; | 528 | return; |
529 | touch_softlockup_watchdog(); | ||
529 | } while (time_before(jiffies, timeo)); | 530 | } while (time_before(jiffies, timeo)); |
530 | } | 531 | } |
531 | 532 | ||
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 07746b95fd83..455ba915ede7 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c | |||
@@ -973,6 +973,11 @@ static int vortex_suspend (struct pci_dev *pdev, pm_message_t state) | |||
973 | netif_device_detach(dev); | 973 | netif_device_detach(dev); |
974 | vortex_down(dev, 1); | 974 | vortex_down(dev, 1); |
975 | } | 975 | } |
976 | pci_save_state(pdev); | ||
977 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); | ||
978 | free_irq(dev->irq, dev); | ||
979 | pci_disable_device(pdev); | ||
980 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
976 | } | 981 | } |
977 | return 0; | 982 | return 0; |
978 | } | 983 | } |
@@ -980,8 +985,19 @@ static int vortex_suspend (struct pci_dev *pdev, pm_message_t state) | |||
980 | static int vortex_resume (struct pci_dev *pdev) | 985 | static int vortex_resume (struct pci_dev *pdev) |
981 | { | 986 | { |
982 | struct net_device *dev = pci_get_drvdata(pdev); | 987 | struct net_device *dev = pci_get_drvdata(pdev); |
988 | struct vortex_private *vp = netdev_priv(dev); | ||
983 | 989 | ||
984 | if (dev && dev->priv) { | 990 | if (dev && vp) { |
991 | pci_set_power_state(pdev, PCI_D0); | ||
992 | pci_restore_state(pdev); | ||
993 | pci_enable_device(pdev); | ||
994 | pci_set_master(pdev); | ||
995 | if (request_irq(dev->irq, vp->full_bus_master_rx ? | ||
996 | &boomerang_interrupt : &vortex_interrupt, SA_SHIRQ, dev->name, dev)) { | ||
997 | printk(KERN_WARNING "%s: Could not reserve IRQ %d\n", dev->name, dev->irq); | ||
998 | pci_disable_device(pdev); | ||
999 | return -EBUSY; | ||
1000 | } | ||
985 | if (netif_running(dev)) { | 1001 | if (netif_running(dev)) { |
986 | vortex_up(dev); | 1002 | vortex_up(dev); |
987 | netif_device_attach(dev); | 1003 | netif_device_attach(dev); |
@@ -1873,6 +1889,7 @@ vortex_timer(unsigned long data) | |||
1873 | { | 1889 | { |
1874 | spin_lock_bh(&vp->lock); | 1890 | spin_lock_bh(&vp->lock); |
1875 | mii_status = mdio_read(dev, vp->phys[0], 1); | 1891 | mii_status = mdio_read(dev, vp->phys[0], 1); |
1892 | mii_status = mdio_read(dev, vp->phys[0], 1); | ||
1876 | ok = 1; | 1893 | ok = 1; |
1877 | if (vortex_debug > 2) | 1894 | if (vortex_debug > 2) |
1878 | printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n", | 1895 | printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n", |
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index 10125a1dba22..dd89bda1f131 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c | |||
@@ -4,10 +4,10 @@ | |||
4 | * Description: Driver for the SMC Infrared Communications Controller | 4 | * Description: Driver for the SMC Infrared Communications Controller |
5 | * Status: Experimental. | 5 | * Status: Experimental. |
6 | * Author: Daniele Peri (peri@csai.unipa.it) | 6 | * Author: Daniele Peri (peri@csai.unipa.it) |
7 | * Created at: | 7 | * Created at: |
8 | * Modified at: | 8 | * Modified at: |
9 | * Modified by: | 9 | * Modified by: |
10 | * | 10 | * |
11 | * Copyright (c) 2002 Daniele Peri | 11 | * Copyright (c) 2002 Daniele Peri |
12 | * All Rights Reserved. | 12 | * All Rights Reserved. |
13 | * Copyright (c) 2002 Jean Tourrilhes | 13 | * Copyright (c) 2002 Jean Tourrilhes |
@@ -17,26 +17,26 @@ | |||
17 | * | 17 | * |
18 | * Copyright (c) 2001 Stefani Seibold | 18 | * Copyright (c) 2001 Stefani Seibold |
19 | * Copyright (c) 1999-2001 Dag Brattli | 19 | * Copyright (c) 1999-2001 Dag Brattli |
20 | * Copyright (c) 1998-1999 Thomas Davis, | 20 | * Copyright (c) 1998-1999 Thomas Davis, |
21 | * | 21 | * |
22 | * and irport.c: | 22 | * and irport.c: |
23 | * | 23 | * |
24 | * Copyright (c) 1997, 1998, 1999-2000 Dag Brattli, All Rights Reserved. | 24 | * Copyright (c) 1997, 1998, 1999-2000 Dag Brattli, All Rights Reserved. |
25 | * | 25 | * |
26 | * | 26 | * |
27 | * This program is free software; you can redistribute it and/or | 27 | * This program is free software; you can redistribute it and/or |
28 | * modify it under the terms of the GNU General Public License as | 28 | * modify it under the terms of the GNU General Public License as |
29 | * published by the Free Software Foundation; either version 2 of | 29 | * published by the Free Software Foundation; either version 2 of |
30 | * the License, or (at your option) any later version. | 30 | * the License, or (at your option) any later version. |
31 | * | 31 | * |
32 | * This program is distributed in the hope that it will be useful, | 32 | * This program is distributed in the hope that it will be useful, |
33 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 33 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
34 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 34 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
35 | * GNU General Public License for more details. | 35 | * GNU General Public License for more details. |
36 | * | 36 | * |
37 | * You should have received a copy of the GNU General Public License | 37 | * You should have received a copy of the GNU General Public License |
38 | * along with this program; if not, write to the Free Software | 38 | * along with this program; if not, write to the Free Software |
39 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 39 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
40 | * MA 02111-1307 USA | 40 | * MA 02111-1307 USA |
41 | * | 41 | * |
42 | ********************************************************************/ | 42 | ********************************************************************/ |
@@ -68,24 +68,42 @@ | |||
68 | #include "smsc-ircc2.h" | 68 | #include "smsc-ircc2.h" |
69 | #include "smsc-sio.h" | 69 | #include "smsc-sio.h" |
70 | 70 | ||
71 | |||
72 | MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>"); | ||
73 | MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver"); | ||
74 | MODULE_LICENSE("GPL"); | ||
75 | |||
76 | static int ircc_dma = 255; | ||
77 | module_param(ircc_dma, int, 0); | ||
78 | MODULE_PARM_DESC(ircc_dma, "DMA channel"); | ||
79 | |||
80 | static int ircc_irq = 255; | ||
81 | module_param(ircc_irq, int, 0); | ||
82 | MODULE_PARM_DESC(ircc_irq, "IRQ line"); | ||
83 | |||
84 | static int ircc_fir; | ||
85 | module_param(ircc_fir, int, 0); | ||
86 | MODULE_PARM_DESC(ircc_fir, "FIR Base Address"); | ||
87 | |||
88 | static int ircc_sir; | ||
89 | module_param(ircc_sir, int, 0); | ||
90 | MODULE_PARM_DESC(ircc_sir, "SIR Base Address"); | ||
91 | |||
92 | static int ircc_cfg; | ||
93 | module_param(ircc_cfg, int, 0); | ||
94 | MODULE_PARM_DESC(ircc_cfg, "Configuration register base address"); | ||
95 | |||
96 | static int ircc_transceiver; | ||
97 | module_param(ircc_transceiver, int, 0); | ||
98 | MODULE_PARM_DESC(ircc_transceiver, "Transceiver type"); | ||
99 | |||
71 | /* Types */ | 100 | /* Types */ |
72 | 101 | ||
73 | struct smsc_transceiver { | 102 | struct smsc_transceiver { |
74 | char *name; | 103 | char *name; |
75 | void (*set_for_speed)(int fir_base, u32 speed); | 104 | void (*set_for_speed)(int fir_base, u32 speed); |
76 | int (*probe)(int fir_base); | 105 | int (*probe)(int fir_base); |
77 | }; | 106 | }; |
78 | typedef struct smsc_transceiver smsc_transceiver_t; | ||
79 | |||
80 | #if 0 | ||
81 | struct smc_chip { | ||
82 | char *name; | ||
83 | u16 flags; | ||
84 | u8 devid; | ||
85 | u8 rev; | ||
86 | }; | ||
87 | typedef struct smc_chip smc_chip_t; | ||
88 | #endif | ||
89 | 107 | ||
90 | struct smsc_chip { | 108 | struct smsc_chip { |
91 | char *name; | 109 | char *name; |
@@ -96,20 +114,18 @@ struct smsc_chip { | |||
96 | u8 devid; | 114 | u8 devid; |
97 | u8 rev; | 115 | u8 rev; |
98 | }; | 116 | }; |
99 | typedef struct smsc_chip smsc_chip_t; | ||
100 | 117 | ||
101 | struct smsc_chip_address { | 118 | struct smsc_chip_address { |
102 | unsigned int cfg_base; | 119 | unsigned int cfg_base; |
103 | unsigned int type; | 120 | unsigned int type; |
104 | }; | 121 | }; |
105 | typedef struct smsc_chip_address smsc_chip_address_t; | ||
106 | 122 | ||
107 | /* Private data for each instance */ | 123 | /* Private data for each instance */ |
108 | struct smsc_ircc_cb { | 124 | struct smsc_ircc_cb { |
109 | struct net_device *netdev; /* Yes! we are some kind of netdevice */ | 125 | struct net_device *netdev; /* Yes! we are some kind of netdevice */ |
110 | struct net_device_stats stats; | 126 | struct net_device_stats stats; |
111 | struct irlap_cb *irlap; /* The link layer we are binded to */ | 127 | struct irlap_cb *irlap; /* The link layer we are binded to */ |
112 | 128 | ||
113 | chipio_t io; /* IrDA controller information */ | 129 | chipio_t io; /* IrDA controller information */ |
114 | iobuff_t tx_buff; /* Transmit buffer */ | 130 | iobuff_t tx_buff; /* Transmit buffer */ |
115 | iobuff_t rx_buff; /* Receive buffer */ | 131 | iobuff_t rx_buff; /* Receive buffer */ |
@@ -119,7 +135,7 @@ struct smsc_ircc_cb { | |||
119 | struct qos_info qos; /* QoS capabilities for this device */ | 135 | struct qos_info qos; /* QoS capabilities for this device */ |
120 | 136 | ||
121 | spinlock_t lock; /* For serializing operations */ | 137 | spinlock_t lock; /* For serializing operations */ |
122 | 138 | ||
123 | __u32 new_speed; | 139 | __u32 new_speed; |
124 | __u32 flags; /* Interface flags */ | 140 | __u32 flags; /* Interface flags */ |
125 | 141 | ||
@@ -127,18 +143,20 @@ struct smsc_ircc_cb { | |||
127 | int tx_len; /* Number of frames in tx_buff */ | 143 | int tx_len; /* Number of frames in tx_buff */ |
128 | 144 | ||
129 | int transceiver; | 145 | int transceiver; |
130 | struct pm_dev *pmdev; | 146 | struct platform_device *pldev; |
131 | }; | 147 | }; |
132 | 148 | ||
133 | /* Constants */ | 149 | /* Constants */ |
134 | 150 | ||
135 | static const char *driver_name = "smsc-ircc2"; | 151 | #define SMSC_IRCC2_DRIVER_NAME "smsc-ircc2" |
136 | #define DIM(x) (sizeof(x)/(sizeof(*(x)))) | 152 | |
137 | #define SMSC_IRCC2_C_IRDA_FALLBACK_SPEED 9600 | 153 | #define SMSC_IRCC2_C_IRDA_FALLBACK_SPEED 9600 |
138 | #define SMSC_IRCC2_C_DEFAULT_TRANSCEIVER 1 | 154 | #define SMSC_IRCC2_C_DEFAULT_TRANSCEIVER 1 |
139 | #define SMSC_IRCC2_C_NET_TIMEOUT 0 | 155 | #define SMSC_IRCC2_C_NET_TIMEOUT 0 |
140 | #define SMSC_IRCC2_C_SIR_STOP 0 | 156 | #define SMSC_IRCC2_C_SIR_STOP 0 |
141 | 157 | ||
158 | static const char *driver_name = SMSC_IRCC2_DRIVER_NAME; | ||
159 | |||
142 | /* Prototypes */ | 160 | /* Prototypes */ |
143 | 161 | ||
144 | static int smsc_ircc_open(unsigned int firbase, unsigned int sirbase, u8 dma, u8 irq); | 162 | static int smsc_ircc_open(unsigned int firbase, unsigned int sirbase, u8 dma, u8 irq); |
@@ -147,15 +165,15 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, unsigned int fir_base, | |||
147 | static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self); | 165 | static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self); |
148 | static void smsc_ircc_init_chip(struct smsc_ircc_cb *self); | 166 | static void smsc_ircc_init_chip(struct smsc_ircc_cb *self); |
149 | static int __exit smsc_ircc_close(struct smsc_ircc_cb *self); | 167 | static int __exit smsc_ircc_close(struct smsc_ircc_cb *self); |
150 | static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase); | 168 | static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self); |
151 | static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self, int iobase); | 169 | static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self); |
152 | static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self); | 170 | static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self); |
153 | static int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev); | 171 | static int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev); |
154 | static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev); | 172 | static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev); |
155 | static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int iobase, int bofs); | 173 | static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int bofs); |
156 | static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self, int iobase); | 174 | static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self); |
157 | static void smsc_ircc_change_speed(void *priv, u32 speed); | 175 | static void smsc_ircc_change_speed(struct smsc_ircc_cb *self, u32 speed); |
158 | static void smsc_ircc_set_sir_speed(void *priv, u32 speed); | 176 | static void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, u32 speed); |
159 | static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 177 | static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs); |
160 | static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev); | 178 | static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev); |
161 | static void smsc_ircc_sir_start(struct smsc_ircc_cb *self); | 179 | static void smsc_ircc_sir_start(struct smsc_ircc_cb *self); |
@@ -171,7 +189,6 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cm | |||
171 | static void smsc_ircc_timeout(struct net_device *dev); | 189 | static void smsc_ircc_timeout(struct net_device *dev); |
172 | #endif | 190 | #endif |
173 | static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev); | 191 | static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev); |
174 | static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data); | ||
175 | static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self); | 192 | static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self); |
176 | static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self); | 193 | static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self); |
177 | static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed); | 194 | static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed); |
@@ -179,9 +196,9 @@ static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self); | |||
179 | 196 | ||
180 | /* Probing */ | 197 | /* Probing */ |
181 | static int __init smsc_ircc_look_for_chips(void); | 198 | static int __init smsc_ircc_look_for_chips(void); |
182 | static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg,const smsc_chip_t *chip,char *type); | 199 | static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type); |
183 | static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfg_base, char *type); | 200 | static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned short cfg_base, char *type); |
184 | static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cfg_base, char *type); | 201 | static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type); |
185 | static int __init smsc_superio_fdc(unsigned short cfg_base); | 202 | static int __init smsc_superio_fdc(unsigned short cfg_base); |
186 | static int __init smsc_superio_lpc(unsigned short cfg_base); | 203 | static int __init smsc_superio_lpc(unsigned short cfg_base); |
187 | 204 | ||
@@ -196,21 +213,26 @@ static int smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base); | |||
196 | 213 | ||
197 | /* Power Management */ | 214 | /* Power Management */ |
198 | 215 | ||
199 | static void smsc_ircc_suspend(struct smsc_ircc_cb *self); | 216 | static int smsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level); |
200 | static void smsc_ircc_wakeup(struct smsc_ircc_cb *self); | 217 | static int smsc_ircc_resume(struct device *dev, u32 level); |
201 | static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data); | ||
202 | 218 | ||
219 | static struct device_driver smsc_ircc_driver = { | ||
220 | .name = SMSC_IRCC2_DRIVER_NAME, | ||
221 | .bus = &platform_bus_type, | ||
222 | .suspend = smsc_ircc_suspend, | ||
223 | .resume = smsc_ircc_resume, | ||
224 | }; | ||
203 | 225 | ||
204 | /* Transceivers for SMSC-ircc */ | 226 | /* Transceivers for SMSC-ircc */ |
205 | 227 | ||
206 | static smsc_transceiver_t smsc_transceivers[]= | 228 | static struct smsc_transceiver smsc_transceivers[] = |
207 | { | 229 | { |
208 | { "Toshiba Satellite 1800 (GP data pin select)", smsc_ircc_set_transceiver_toshiba_sat1800, smsc_ircc_probe_transceiver_toshiba_sat1800}, | 230 | { "Toshiba Satellite 1800 (GP data pin select)", smsc_ircc_set_transceiver_toshiba_sat1800, smsc_ircc_probe_transceiver_toshiba_sat1800 }, |
209 | { "Fast pin select", smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select, smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select}, | 231 | { "Fast pin select", smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select, smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select }, |
210 | { "ATC IRMode", smsc_ircc_set_transceiver_smsc_ircc_atc, smsc_ircc_probe_transceiver_smsc_ircc_atc}, | 232 | { "ATC IRMode", smsc_ircc_set_transceiver_smsc_ircc_atc, smsc_ircc_probe_transceiver_smsc_ircc_atc }, |
211 | { NULL, NULL} | 233 | { NULL, NULL } |
212 | }; | 234 | }; |
213 | #define SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS (DIM(smsc_transceivers)-1) | 235 | #define SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS (ARRAY_SIZE(smsc_transceivers) - 1) |
214 | 236 | ||
215 | /* SMC SuperIO chipsets definitions */ | 237 | /* SMC SuperIO chipsets definitions */ |
216 | 238 | ||
@@ -221,7 +243,7 @@ static smsc_transceiver_t smsc_transceivers[]= | |||
221 | #define FIR 4 /* SuperIO Chip has fast IRDA */ | 243 | #define FIR 4 /* SuperIO Chip has fast IRDA */ |
222 | #define SERx4 8 /* SuperIO Chip supports 115,2 KBaud * 4=460,8 KBaud */ | 244 | #define SERx4 8 /* SuperIO Chip supports 115,2 KBaud * 4=460,8 KBaud */ |
223 | 245 | ||
224 | static smsc_chip_t __initdata fdc_chips_flat[]= | 246 | static struct smsc_chip __initdata fdc_chips_flat[] = |
225 | { | 247 | { |
226 | /* Base address 0x3f0 or 0x370 */ | 248 | /* Base address 0x3f0 or 0x370 */ |
227 | { "37C44", KEY55_1|NoIRDA, 0x00, 0x00 }, /* This chip cannot be detected */ | 249 | { "37C44", KEY55_1|NoIRDA, 0x00, 0x00 }, /* This chip cannot be detected */ |
@@ -235,7 +257,7 @@ static smsc_chip_t __initdata fdc_chips_flat[]= | |||
235 | { NULL } | 257 | { NULL } |
236 | }; | 258 | }; |
237 | 259 | ||
238 | static smsc_chip_t __initdata fdc_chips_paged[]= | 260 | static struct smsc_chip __initdata fdc_chips_paged[] = |
239 | { | 261 | { |
240 | /* Base address 0x3f0 or 0x370 */ | 262 | /* Base address 0x3f0 or 0x370 */ |
241 | { "37B72X", KEY55_1|SIR|SERx4, 0x4c, 0x00 }, | 263 | { "37B72X", KEY55_1|SIR|SERx4, 0x4c, 0x00 }, |
@@ -254,7 +276,7 @@ static smsc_chip_t __initdata fdc_chips_paged[]= | |||
254 | { NULL } | 276 | { NULL } |
255 | }; | 277 | }; |
256 | 278 | ||
257 | static smsc_chip_t __initdata lpc_chips_flat[]= | 279 | static struct smsc_chip __initdata lpc_chips_flat[] = |
258 | { | 280 | { |
259 | /* Base address 0x2E or 0x4E */ | 281 | /* Base address 0x2E or 0x4E */ |
260 | { "47N227", KEY55_1|FIR|SERx4, 0x5a, 0x00 }, | 282 | { "47N227", KEY55_1|FIR|SERx4, 0x5a, 0x00 }, |
@@ -262,7 +284,7 @@ static smsc_chip_t __initdata lpc_chips_flat[]= | |||
262 | { NULL } | 284 | { NULL } |
263 | }; | 285 | }; |
264 | 286 | ||
265 | static smsc_chip_t __initdata lpc_chips_paged[]= | 287 | static struct smsc_chip __initdata lpc_chips_paged[] = |
266 | { | 288 | { |
267 | /* Base address 0x2E or 0x4E */ | 289 | /* Base address 0x2E or 0x4E */ |
268 | { "47B27X", KEY55_1|SIR|SERx4, 0x51, 0x00 }, | 290 | { "47B27X", KEY55_1|SIR|SERx4, 0x51, 0x00 }, |
@@ -281,33 +303,25 @@ static smsc_chip_t __initdata lpc_chips_paged[]= | |||
281 | #define SMSCSIO_TYPE_FLAT 4 | 303 | #define SMSCSIO_TYPE_FLAT 4 |
282 | #define SMSCSIO_TYPE_PAGED 8 | 304 | #define SMSCSIO_TYPE_PAGED 8 |
283 | 305 | ||
284 | static smsc_chip_address_t __initdata possible_addresses[]= | 306 | static struct smsc_chip_address __initdata possible_addresses[] = |
285 | { | 307 | { |
286 | {0x3f0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED}, | 308 | { 0x3f0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED }, |
287 | {0x370, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED}, | 309 | { 0x370, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED }, |
288 | {0xe0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED}, | 310 | { 0xe0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED }, |
289 | {0x2e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED}, | 311 | { 0x2e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED }, |
290 | {0x4e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED}, | 312 | { 0x4e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED }, |
291 | {0,0} | 313 | { 0, 0 } |
292 | }; | 314 | }; |
293 | 315 | ||
294 | /* Globals */ | 316 | /* Globals */ |
295 | 317 | ||
296 | static struct smsc_ircc_cb *dev_self[] = { NULL, NULL}; | 318 | static struct smsc_ircc_cb *dev_self[] = { NULL, NULL }; |
297 | 319 | static unsigned short dev_count; | |
298 | static int ircc_irq=255; | ||
299 | static int ircc_dma=255; | ||
300 | static int ircc_fir=0; | ||
301 | static int ircc_sir=0; | ||
302 | static int ircc_cfg=0; | ||
303 | static int ircc_transceiver=0; | ||
304 | |||
305 | static unsigned short dev_count=0; | ||
306 | 320 | ||
307 | static inline void register_bank(int iobase, int bank) | 321 | static inline void register_bank(int iobase, int bank) |
308 | { | 322 | { |
309 | outb(((inb(iobase+IRCC_MASTER) & 0xf0) | (bank & 0x07)), | 323 | outb(((inb(iobase + IRCC_MASTER) & 0xf0) | (bank & 0x07)), |
310 | iobase+IRCC_MASTER); | 324 | iobase + IRCC_MASTER); |
311 | } | 325 | } |
312 | 326 | ||
313 | 327 | ||
@@ -327,34 +341,44 @@ static inline void register_bank(int iobase, int bank) | |||
327 | */ | 341 | */ |
328 | static int __init smsc_ircc_init(void) | 342 | static int __init smsc_ircc_init(void) |
329 | { | 343 | { |
330 | int ret=-ENODEV; | 344 | int ret; |
331 | 345 | ||
332 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); | 346 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); |
333 | 347 | ||
334 | dev_count=0; | 348 | ret = driver_register(&smsc_ircc_driver); |
335 | 349 | if (ret) { | |
336 | if ((ircc_fir>0)&&(ircc_sir>0)) { | 350 | IRDA_ERROR("%s, Can't register driver!\n", driver_name); |
351 | return ret; | ||
352 | } | ||
353 | |||
354 | dev_count = 0; | ||
355 | |||
356 | if (ircc_fir > 0 && ircc_sir > 0) { | ||
337 | IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir); | 357 | IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir); |
338 | IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir); | 358 | IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir); |
339 | 359 | ||
340 | if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq) == 0) | 360 | if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq)) |
341 | return 0; | 361 | ret = -ENODEV; |
342 | 362 | } else { | |
343 | return -ENODEV; | 363 | ret = -ENODEV; |
344 | } | 364 | |
365 | /* try user provided configuration register base address */ | ||
366 | if (ircc_cfg > 0) { | ||
367 | IRDA_MESSAGE(" Overriding configuration address " | ||
368 | "0x%04x\n", ircc_cfg); | ||
369 | if (!smsc_superio_fdc(ircc_cfg)) | ||
370 | ret = 0; | ||
371 | if (!smsc_superio_lpc(ircc_cfg)) | ||
372 | ret = 0; | ||
373 | } | ||
345 | 374 | ||
346 | /* try user provided configuration register base address */ | 375 | if (smsc_ircc_look_for_chips() > 0) |
347 | if (ircc_cfg>0) { | ||
348 | IRDA_MESSAGE(" Overriding configuration address 0x%04x\n", | ||
349 | ircc_cfg); | ||
350 | if (!smsc_superio_fdc(ircc_cfg)) | ||
351 | ret = 0; | ||
352 | if (!smsc_superio_lpc(ircc_cfg)) | ||
353 | ret = 0; | 376 | ret = 0; |
354 | } | 377 | } |
355 | 378 | ||
356 | if(smsc_ircc_look_for_chips()>0) ret = 0; | 379 | if (ret) |
357 | 380 | driver_unregister(&smsc_ircc_driver); | |
381 | |||
358 | return ret; | 382 | return ret; |
359 | } | 383 | } |
360 | 384 | ||
@@ -369,15 +393,15 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u | |||
369 | struct smsc_ircc_cb *self; | 393 | struct smsc_ircc_cb *self; |
370 | struct net_device *dev; | 394 | struct net_device *dev; |
371 | int err; | 395 | int err; |
372 | 396 | ||
373 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); | 397 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); |
374 | 398 | ||
375 | err = smsc_ircc_present(fir_base, sir_base); | 399 | err = smsc_ircc_present(fir_base, sir_base); |
376 | if(err) | 400 | if (err) |
377 | goto err_out; | 401 | goto err_out; |
378 | 402 | ||
379 | err = -ENOMEM; | 403 | err = -ENOMEM; |
380 | if (dev_count > DIM(dev_self)) { | 404 | if (dev_count >= ARRAY_SIZE(dev_self)) { |
381 | IRDA_WARNING("%s(), too many devices!\n", __FUNCTION__); | 405 | IRDA_WARNING("%s(), too many devices!\n", __FUNCTION__); |
382 | goto err_out1; | 406 | goto err_out1; |
383 | } | 407 | } |
@@ -396,14 +420,14 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u | |||
396 | dev->hard_start_xmit = smsc_ircc_hard_xmit_sir; | 420 | dev->hard_start_xmit = smsc_ircc_hard_xmit_sir; |
397 | #if SMSC_IRCC2_C_NET_TIMEOUT | 421 | #if SMSC_IRCC2_C_NET_TIMEOUT |
398 | dev->tx_timeout = smsc_ircc_timeout; | 422 | dev->tx_timeout = smsc_ircc_timeout; |
399 | dev->watchdog_timeo = HZ*2; /* Allow enough time for speed change */ | 423 | dev->watchdog_timeo = HZ * 2; /* Allow enough time for speed change */ |
400 | #endif | 424 | #endif |
401 | dev->open = smsc_ircc_net_open; | 425 | dev->open = smsc_ircc_net_open; |
402 | dev->stop = smsc_ircc_net_close; | 426 | dev->stop = smsc_ircc_net_close; |
403 | dev->do_ioctl = smsc_ircc_net_ioctl; | 427 | dev->do_ioctl = smsc_ircc_net_ioctl; |
404 | dev->get_stats = smsc_ircc_net_get_stats; | 428 | dev->get_stats = smsc_ircc_net_get_stats; |
405 | 429 | ||
406 | self = dev->priv; | 430 | self = netdev_priv(dev); |
407 | self->netdev = dev; | 431 | self->netdev = dev; |
408 | 432 | ||
409 | /* Make ifconfig display some details */ | 433 | /* Make ifconfig display some details */ |
@@ -411,10 +435,10 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u | |||
411 | dev->irq = self->io.irq = irq; | 435 | dev->irq = self->io.irq = irq; |
412 | 436 | ||
413 | /* Need to store self somewhere */ | 437 | /* Need to store self somewhere */ |
414 | dev_self[dev_count++] = self; | 438 | dev_self[dev_count] = self; |
415 | spin_lock_init(&self->lock); | 439 | spin_lock_init(&self->lock); |
416 | 440 | ||
417 | self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE; | 441 | self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE; |
418 | self->tx_buff.truesize = SMSC_IRCC2_TX_BUFF_TRUESIZE; | 442 | self->tx_buff.truesize = SMSC_IRCC2_TX_BUFF_TRUESIZE; |
419 | 443 | ||
420 | self->rx_buff.head = | 444 | self->rx_buff.head = |
@@ -442,33 +466,40 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u | |||
442 | self->rx_buff.state = OUTSIDE_FRAME; | 466 | self->rx_buff.state = OUTSIDE_FRAME; |
443 | self->tx_buff.data = self->tx_buff.head; | 467 | self->tx_buff.data = self->tx_buff.head; |
444 | self->rx_buff.data = self->rx_buff.head; | 468 | self->rx_buff.data = self->rx_buff.head; |
445 | |||
446 | smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq); | ||
447 | 469 | ||
470 | smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq); | ||
448 | smsc_ircc_setup_qos(self); | 471 | smsc_ircc_setup_qos(self); |
449 | |||
450 | smsc_ircc_init_chip(self); | 472 | smsc_ircc_init_chip(self); |
451 | 473 | ||
452 | if(ircc_transceiver > 0 && | 474 | if (ircc_transceiver > 0 && |
453 | ircc_transceiver < SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS) | 475 | ircc_transceiver < SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS) |
454 | self->transceiver = ircc_transceiver; | 476 | self->transceiver = ircc_transceiver; |
455 | else | 477 | else |
456 | smsc_ircc_probe_transceiver(self); | 478 | smsc_ircc_probe_transceiver(self); |
457 | 479 | ||
458 | err = register_netdev(self->netdev); | 480 | err = register_netdev(self->netdev); |
459 | if(err) { | 481 | if (err) { |
460 | IRDA_ERROR("%s, Network device registration failed!\n", | 482 | IRDA_ERROR("%s, Network device registration failed!\n", |
461 | driver_name); | 483 | driver_name); |
462 | goto err_out4; | 484 | goto err_out4; |
463 | } | 485 | } |
464 | 486 | ||
465 | self->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, smsc_ircc_pmproc); | 487 | self->pldev = platform_device_register_simple(SMSC_IRCC2_DRIVER_NAME, |
466 | if (self->pmdev) | 488 | dev_count, NULL, 0); |
467 | self->pmdev->data = self; | 489 | if (IS_ERR(self->pldev)) { |
490 | err = PTR_ERR(self->pldev); | ||
491 | goto err_out5; | ||
492 | } | ||
493 | dev_set_drvdata(&self->pldev->dev, self); | ||
468 | 494 | ||
469 | IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name); | 495 | IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name); |
496 | dev_count++; | ||
470 | 497 | ||
471 | return 0; | 498 | return 0; |
499 | |||
500 | err_out5: | ||
501 | unregister_netdev(self->netdev); | ||
502 | |||
472 | err_out4: | 503 | err_out4: |
473 | dma_free_coherent(NULL, self->tx_buff.truesize, | 504 | dma_free_coherent(NULL, self->tx_buff.truesize, |
474 | self->tx_buff.head, self->tx_buff_dma); | 505 | self->tx_buff.head, self->tx_buff_dma); |
@@ -477,7 +508,7 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u | |||
477 | self->rx_buff.head, self->rx_buff_dma); | 508 | self->rx_buff.head, self->rx_buff_dma); |
478 | err_out2: | 509 | err_out2: |
479 | free_netdev(self->netdev); | 510 | free_netdev(self->netdev); |
480 | dev_self[--dev_count] = NULL; | 511 | dev_self[dev_count] = NULL; |
481 | err_out1: | 512 | err_out1: |
482 | release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT); | 513 | release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT); |
483 | release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT); | 514 | release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT); |
@@ -511,16 +542,16 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base) | |||
511 | 542 | ||
512 | register_bank(fir_base, 3); | 543 | register_bank(fir_base, 3); |
513 | 544 | ||
514 | high = inb(fir_base+IRCC_ID_HIGH); | 545 | high = inb(fir_base + IRCC_ID_HIGH); |
515 | low = inb(fir_base+IRCC_ID_LOW); | 546 | low = inb(fir_base + IRCC_ID_LOW); |
516 | chip = inb(fir_base+IRCC_CHIP_ID); | 547 | chip = inb(fir_base + IRCC_CHIP_ID); |
517 | version = inb(fir_base+IRCC_VERSION); | 548 | version = inb(fir_base + IRCC_VERSION); |
518 | config = inb(fir_base+IRCC_INTERFACE); | 549 | config = inb(fir_base + IRCC_INTERFACE); |
519 | dma = config & IRCC_INTERFACE_DMA_MASK; | 550 | dma = config & IRCC_INTERFACE_DMA_MASK; |
520 | irq = (config & IRCC_INTERFACE_IRQ_MASK) >> 4; | 551 | irq = (config & IRCC_INTERFACE_IRQ_MASK) >> 4; |
521 | 552 | ||
522 | if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) { | 553 | if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) { |
523 | IRDA_WARNING("%s(), addr 0x%04x - no device found!\n", | 554 | IRDA_WARNING("%s(), addr 0x%04x - no device found!\n", |
524 | __FUNCTION__, fir_base); | 555 | __FUNCTION__, fir_base); |
525 | goto out3; | 556 | goto out3; |
526 | } | 557 | } |
@@ -529,6 +560,7 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base) | |||
529 | chip & 0x0f, version, fir_base, sir_base, dma, irq); | 560 | chip & 0x0f, version, fir_base, sir_base, dma, irq); |
530 | 561 | ||
531 | return 0; | 562 | return 0; |
563 | |||
532 | out3: | 564 | out3: |
533 | release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT); | 565 | release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT); |
534 | out2: | 566 | out2: |
@@ -543,16 +575,16 @@ static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base) | |||
543 | * Setup I/O | 575 | * Setup I/O |
544 | * | 576 | * |
545 | */ | 577 | */ |
546 | static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, | 578 | static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, |
547 | unsigned int fir_base, unsigned int sir_base, | 579 | unsigned int fir_base, unsigned int sir_base, |
548 | u8 dma, u8 irq) | 580 | u8 dma, u8 irq) |
549 | { | 581 | { |
550 | unsigned char config, chip_dma, chip_irq; | 582 | unsigned char config, chip_dma, chip_irq; |
551 | 583 | ||
552 | register_bank(fir_base, 3); | 584 | register_bank(fir_base, 3); |
553 | config = inb(fir_base+IRCC_INTERFACE); | 585 | config = inb(fir_base + IRCC_INTERFACE); |
554 | chip_dma = config & IRCC_INTERFACE_DMA_MASK; | 586 | chip_dma = config & IRCC_INTERFACE_DMA_MASK; |
555 | chip_irq = (config & IRCC_INTERFACE_IRQ_MASK) >> 4; | 587 | chip_irq = (config & IRCC_INTERFACE_IRQ_MASK) >> 4; |
556 | 588 | ||
557 | self->io.fir_base = fir_base; | 589 | self->io.fir_base = fir_base; |
558 | self->io.sir_base = sir_base; | 590 | self->io.sir_base = sir_base; |
@@ -566,17 +598,15 @@ static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, | |||
566 | IRDA_MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n", | 598 | IRDA_MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n", |
567 | driver_name, chip_irq, irq); | 599 | driver_name, chip_irq, irq); |
568 | self->io.irq = irq; | 600 | self->io.irq = irq; |
569 | } | 601 | } else |
570 | else | ||
571 | self->io.irq = chip_irq; | 602 | self->io.irq = chip_irq; |
572 | 603 | ||
573 | if (dma < 255) { | 604 | if (dma < 255) { |
574 | if (dma != chip_dma) | 605 | if (dma != chip_dma) |
575 | IRDA_MESSAGE("%s, Overriding DMA - chip says %d, using %d\n", | 606 | IRDA_MESSAGE("%s, Overriding DMA - chip says %d, using %d\n", |
576 | driver_name, chip_dma, dma); | 607 | driver_name, chip_dma, dma); |
577 | self->io.dma = dma; | 608 | self->io.dma = dma; |
578 | } | 609 | } else |
579 | else | ||
580 | self->io.dma = chip_dma; | 610 | self->io.dma = chip_dma; |
581 | 611 | ||
582 | } | 612 | } |
@@ -591,7 +621,7 @@ static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self) | |||
591 | { | 621 | { |
592 | /* Initialize QoS for this device */ | 622 | /* Initialize QoS for this device */ |
593 | irda_init_max_qos_capabilies(&self->qos); | 623 | irda_init_max_qos_capabilies(&self->qos); |
594 | 624 | ||
595 | self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| | 625 | self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| |
596 | IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8); | 626 | IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8); |
597 | 627 | ||
@@ -608,43 +638,43 @@ static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self) | |||
608 | */ | 638 | */ |
609 | static void smsc_ircc_init_chip(struct smsc_ircc_cb *self) | 639 | static void smsc_ircc_init_chip(struct smsc_ircc_cb *self) |
610 | { | 640 | { |
611 | int iobase, ir_mode, ctrl, fast; | 641 | int iobase, ir_mode, ctrl, fast; |
612 | 642 | ||
613 | IRDA_ASSERT( self != NULL, return; ); | 643 | IRDA_ASSERT(self != NULL, return;); |
614 | iobase = self->io.fir_base; | ||
615 | 644 | ||
645 | iobase = self->io.fir_base; | ||
616 | ir_mode = IRCC_CFGA_IRDA_SIR_A; | 646 | ir_mode = IRCC_CFGA_IRDA_SIR_A; |
617 | ctrl = 0; | 647 | ctrl = 0; |
618 | fast = 0; | 648 | fast = 0; |
619 | 649 | ||
620 | register_bank(iobase, 0); | 650 | register_bank(iobase, 0); |
621 | outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER); | 651 | outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER); |
622 | outb(0x00, iobase+IRCC_MASTER); | 652 | outb(0x00, iobase + IRCC_MASTER); |
623 | 653 | ||
624 | register_bank(iobase, 1); | 654 | register_bank(iobase, 1); |
625 | outb(((inb(iobase+IRCC_SCE_CFGA) & 0x87) | ir_mode), | 655 | outb(((inb(iobase + IRCC_SCE_CFGA) & 0x87) | ir_mode), |
626 | iobase+IRCC_SCE_CFGA); | 656 | iobase + IRCC_SCE_CFGA); |
627 | 657 | ||
628 | #ifdef smsc_669 /* Uses pin 88/89 for Rx/Tx */ | 658 | #ifdef smsc_669 /* Uses pin 88/89 for Rx/Tx */ |
629 | outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM), | 659 | outb(((inb(iobase + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM), |
630 | iobase+IRCC_SCE_CFGB); | 660 | iobase + IRCC_SCE_CFGB); |
631 | #else | 661 | #else |
632 | outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR), | 662 | outb(((inb(iobase + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR), |
633 | iobase+IRCC_SCE_CFGB); | 663 | iobase + IRCC_SCE_CFGB); |
634 | #endif | 664 | #endif |
635 | (void) inb(iobase+IRCC_FIFO_THRESHOLD); | 665 | (void) inb(iobase + IRCC_FIFO_THRESHOLD); |
636 | outb(SMSC_IRCC2_FIFO_THRESHOLD, iobase+IRCC_FIFO_THRESHOLD); | 666 | outb(SMSC_IRCC2_FIFO_THRESHOLD, iobase + IRCC_FIFO_THRESHOLD); |
637 | 667 | ||
638 | register_bank(iobase, 4); | 668 | register_bank(iobase, 4); |
639 | outb((inb(iobase+IRCC_CONTROL) & 0x30) | ctrl, iobase+IRCC_CONTROL); | 669 | outb((inb(iobase + IRCC_CONTROL) & 0x30) | ctrl, iobase + IRCC_CONTROL); |
640 | 670 | ||
641 | register_bank(iobase, 0); | 671 | register_bank(iobase, 0); |
642 | outb(fast, iobase+IRCC_LCR_A); | 672 | outb(fast, iobase + IRCC_LCR_A); |
643 | 673 | ||
644 | smsc_ircc_set_sir_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED); | 674 | smsc_ircc_set_sir_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED); |
645 | 675 | ||
646 | /* Power on device */ | 676 | /* Power on device */ |
647 | outb(0x00, iobase+IRCC_MASTER); | 677 | outb(0x00, iobase + IRCC_MASTER); |
648 | } | 678 | } |
649 | 679 | ||
650 | /* | 680 | /* |
@@ -662,12 +692,12 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd | |||
662 | 692 | ||
663 | IRDA_ASSERT(dev != NULL, return -1;); | 693 | IRDA_ASSERT(dev != NULL, return -1;); |
664 | 694 | ||
665 | self = dev->priv; | 695 | self = netdev_priv(dev); |
666 | 696 | ||
667 | IRDA_ASSERT(self != NULL, return -1;); | 697 | IRDA_ASSERT(self != NULL, return -1;); |
668 | 698 | ||
669 | IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd); | 699 | IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, dev->name, cmd); |
670 | 700 | ||
671 | switch (cmd) { | 701 | switch (cmd) { |
672 | case SIOCSBANDWIDTH: /* Set bandwidth */ | 702 | case SIOCSBANDWIDTH: /* Set bandwidth */ |
673 | if (!capable(CAP_NET_ADMIN)) | 703 | if (!capable(CAP_NET_ADMIN)) |
@@ -703,14 +733,14 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd | |||
703 | default: | 733 | default: |
704 | ret = -EOPNOTSUPP; | 734 | ret = -EOPNOTSUPP; |
705 | } | 735 | } |
706 | 736 | ||
707 | return ret; | 737 | return ret; |
708 | } | 738 | } |
709 | 739 | ||
710 | static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev) | 740 | static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev) |
711 | { | 741 | { |
712 | struct smsc_ircc_cb *self = (struct smsc_ircc_cb *) dev->priv; | 742 | struct smsc_ircc_cb *self = netdev_priv(dev); |
713 | 743 | ||
714 | return &self->stats; | 744 | return &self->stats; |
715 | } | 745 | } |
716 | 746 | ||
@@ -724,11 +754,9 @@ static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev) | |||
724 | 754 | ||
725 | static void smsc_ircc_timeout(struct net_device *dev) | 755 | static void smsc_ircc_timeout(struct net_device *dev) |
726 | { | 756 | { |
727 | struct smsc_ircc_cb *self; | 757 | struct smsc_ircc_cb *self = netdev_priv(dev); |
728 | unsigned long flags; | 758 | unsigned long flags; |
729 | 759 | ||
730 | self = (struct smsc_ircc_cb *) dev->priv; | ||
731 | |||
732 | IRDA_WARNING("%s: transmit timed out, changing speed to: %d\n", | 760 | IRDA_WARNING("%s: transmit timed out, changing speed to: %d\n", |
733 | dev->name, self->io.speed); | 761 | dev->name, self->io.speed); |
734 | spin_lock_irqsave(&self->lock, flags); | 762 | spin_lock_irqsave(&self->lock, flags); |
@@ -751,26 +779,23 @@ int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev) | |||
751 | { | 779 | { |
752 | struct smsc_ircc_cb *self; | 780 | struct smsc_ircc_cb *self; |
753 | unsigned long flags; | 781 | unsigned long flags; |
754 | int iobase; | ||
755 | s32 speed; | 782 | s32 speed; |
756 | 783 | ||
757 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); | 784 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); |
758 | 785 | ||
759 | IRDA_ASSERT(dev != NULL, return 0;); | 786 | IRDA_ASSERT(dev != NULL, return 0;); |
760 | |||
761 | self = (struct smsc_ircc_cb *) dev->priv; | ||
762 | IRDA_ASSERT(self != NULL, return 0;); | ||
763 | 787 | ||
764 | iobase = self->io.sir_base; | 788 | self = netdev_priv(dev); |
789 | IRDA_ASSERT(self != NULL, return 0;); | ||
765 | 790 | ||
766 | netif_stop_queue(dev); | 791 | netif_stop_queue(dev); |
767 | 792 | ||
768 | /* Make sure test of self->io.speed & speed change are atomic */ | 793 | /* Make sure test of self->io.speed & speed change are atomic */ |
769 | spin_lock_irqsave(&self->lock, flags); | 794 | spin_lock_irqsave(&self->lock, flags); |
770 | 795 | ||
771 | /* Check if we need to change the speed */ | 796 | /* Check if we need to change the speed */ |
772 | speed = irda_get_next_speed(skb); | 797 | speed = irda_get_next_speed(skb); |
773 | if ((speed != self->io.speed) && (speed != -1)) { | 798 | if (speed != self->io.speed && speed != -1) { |
774 | /* Check for empty frame */ | 799 | /* Check for empty frame */ |
775 | if (!skb->len) { | 800 | if (!skb->len) { |
776 | /* | 801 | /* |
@@ -787,27 +812,26 @@ int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev) | |||
787 | spin_unlock_irqrestore(&self->lock, flags); | 812 | spin_unlock_irqrestore(&self->lock, flags); |
788 | dev_kfree_skb(skb); | 813 | dev_kfree_skb(skb); |
789 | return 0; | 814 | return 0; |
790 | } else { | ||
791 | self->new_speed = speed; | ||
792 | } | 815 | } |
816 | self->new_speed = speed; | ||
793 | } | 817 | } |
794 | 818 | ||
795 | /* Init tx buffer */ | 819 | /* Init tx buffer */ |
796 | self->tx_buff.data = self->tx_buff.head; | 820 | self->tx_buff.data = self->tx_buff.head; |
797 | 821 | ||
798 | /* Copy skb to tx_buff while wrapping, stuffing and making CRC */ | 822 | /* Copy skb to tx_buff while wrapping, stuffing and making CRC */ |
799 | self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, | 823 | self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, |
800 | self->tx_buff.truesize); | 824 | self->tx_buff.truesize); |
801 | 825 | ||
802 | self->stats.tx_bytes += self->tx_buff.len; | 826 | self->stats.tx_bytes += self->tx_buff.len; |
803 | 827 | ||
804 | /* Turn on transmit finished interrupt. Will fire immediately! */ | 828 | /* Turn on transmit finished interrupt. Will fire immediately! */ |
805 | outb(UART_IER_THRI, iobase+UART_IER); | 829 | outb(UART_IER_THRI, self->io.sir_base + UART_IER); |
806 | 830 | ||
807 | spin_unlock_irqrestore(&self->lock, flags); | 831 | spin_unlock_irqrestore(&self->lock, flags); |
808 | 832 | ||
809 | dev_kfree_skb(skb); | 833 | dev_kfree_skb(skb); |
810 | 834 | ||
811 | return 0; | 835 | return 0; |
812 | } | 836 | } |
813 | 837 | ||
@@ -826,9 +850,9 @@ static void smsc_ircc_set_fir_speed(struct smsc_ircc_cb *self, u32 speed) | |||
826 | 850 | ||
827 | self->io.speed = speed; | 851 | self->io.speed = speed; |
828 | 852 | ||
829 | switch(speed) { | 853 | switch (speed) { |
830 | default: | 854 | default: |
831 | case 576000: | 855 | case 576000: |
832 | ir_mode = IRCC_CFGA_IRDA_HDLC; | 856 | ir_mode = IRCC_CFGA_IRDA_HDLC; |
833 | ctrl = IRCC_CRC; | 857 | ctrl = IRCC_CRC; |
834 | fast = 0; | 858 | fast = 0; |
@@ -853,14 +877,14 @@ static void smsc_ircc_set_fir_speed(struct smsc_ircc_cb *self, u32 speed) | |||
853 | Now in tranceiver! | 877 | Now in tranceiver! |
854 | /* This causes an interrupt */ | 878 | /* This causes an interrupt */ |
855 | register_bank(fir_base, 0); | 879 | register_bank(fir_base, 0); |
856 | outb((inb(fir_base+IRCC_LCR_A) & 0xbf) | fast, fir_base+IRCC_LCR_A); | 880 | outb((inb(fir_base + IRCC_LCR_A) & 0xbf) | fast, fir_base + IRCC_LCR_A); |
857 | #endif | 881 | #endif |
858 | 882 | ||
859 | register_bank(fir_base, 1); | 883 | register_bank(fir_base, 1); |
860 | outb(((inb(fir_base+IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | ir_mode), fir_base+IRCC_SCE_CFGA); | 884 | outb(((inb(fir_base + IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | ir_mode), fir_base + IRCC_SCE_CFGA); |
861 | 885 | ||
862 | register_bank(fir_base, 4); | 886 | register_bank(fir_base, 4); |
863 | outb((inb(fir_base+IRCC_CONTROL) & 0x30) | ctrl, fir_base+IRCC_CONTROL); | 887 | outb((inb(fir_base + IRCC_CONTROL) & 0x30) | ctrl, fir_base + IRCC_CONTROL); |
864 | } | 888 | } |
865 | 889 | ||
866 | /* | 890 | /* |
@@ -885,31 +909,31 @@ static void smsc_ircc_fir_start(struct smsc_ircc_cb *self) | |||
885 | /* Reset everything */ | 909 | /* Reset everything */ |
886 | 910 | ||
887 | /* Install FIR transmit handler */ | 911 | /* Install FIR transmit handler */ |
888 | dev->hard_start_xmit = smsc_ircc_hard_xmit_fir; | 912 | dev->hard_start_xmit = smsc_ircc_hard_xmit_fir; |
889 | 913 | ||
890 | /* Clear FIFO */ | 914 | /* Clear FIFO */ |
891 | outb(inb(fir_base+IRCC_LCR_A)|IRCC_LCR_A_FIFO_RESET, fir_base+IRCC_LCR_A); | 915 | outb(inb(fir_base + IRCC_LCR_A) | IRCC_LCR_A_FIFO_RESET, fir_base + IRCC_LCR_A); |
892 | 916 | ||
893 | /* Enable interrupt */ | 917 | /* Enable interrupt */ |
894 | /*outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base+IRCC_IER);*/ | 918 | /*outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base + IRCC_IER);*/ |
895 | 919 | ||
896 | register_bank(fir_base, 1); | 920 | register_bank(fir_base, 1); |
897 | 921 | ||
898 | /* Select the TX/RX interface */ | 922 | /* Select the TX/RX interface */ |
899 | #ifdef SMSC_669 /* Uses pin 88/89 for Rx/Tx */ | 923 | #ifdef SMSC_669 /* Uses pin 88/89 for Rx/Tx */ |
900 | outb(((inb(fir_base+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM), | 924 | outb(((inb(fir_base + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM), |
901 | fir_base+IRCC_SCE_CFGB); | 925 | fir_base + IRCC_SCE_CFGB); |
902 | #else | 926 | #else |
903 | outb(((inb(fir_base+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR), | 927 | outb(((inb(fir_base + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR), |
904 | fir_base+IRCC_SCE_CFGB); | 928 | fir_base + IRCC_SCE_CFGB); |
905 | #endif | 929 | #endif |
906 | (void) inb(fir_base+IRCC_FIFO_THRESHOLD); | 930 | (void) inb(fir_base + IRCC_FIFO_THRESHOLD); |
907 | 931 | ||
908 | /* Enable SCE interrupts */ | 932 | /* Enable SCE interrupts */ |
909 | outb(0, fir_base+IRCC_MASTER); | 933 | outb(0, fir_base + IRCC_MASTER); |
910 | register_bank(fir_base, 0); | 934 | register_bank(fir_base, 0); |
911 | outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base+IRCC_IER); | 935 | outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, fir_base + IRCC_IER); |
912 | outb(IRCC_MASTER_INT_EN, fir_base+IRCC_MASTER); | 936 | outb(IRCC_MASTER_INT_EN, fir_base + IRCC_MASTER); |
913 | } | 937 | } |
914 | 938 | ||
915 | /* | 939 | /* |
@@ -923,13 +947,13 @@ static void smsc_ircc_fir_stop(struct smsc_ircc_cb *self) | |||
923 | int fir_base; | 947 | int fir_base; |
924 | 948 | ||
925 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); | 949 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); |
926 | 950 | ||
927 | IRDA_ASSERT(self != NULL, return;); | 951 | IRDA_ASSERT(self != NULL, return;); |
928 | 952 | ||
929 | fir_base = self->io.fir_base; | 953 | fir_base = self->io.fir_base; |
930 | register_bank(fir_base, 0); | 954 | register_bank(fir_base, 0); |
931 | /*outb(IRCC_MASTER_RESET, fir_base+IRCC_MASTER);*/ | 955 | /*outb(IRCC_MASTER_RESET, fir_base + IRCC_MASTER);*/ |
932 | outb(inb(fir_base+IRCC_LCR_B) & IRCC_LCR_B_SIP_ENABLE, fir_base+IRCC_LCR_B); | 956 | outb(inb(fir_base + IRCC_LCR_B) & IRCC_LCR_B_SIP_ENABLE, fir_base + IRCC_LCR_B); |
933 | } | 957 | } |
934 | 958 | ||
935 | 959 | ||
@@ -941,18 +965,15 @@ static void smsc_ircc_fir_stop(struct smsc_ircc_cb *self) | |||
941 | * This function *must* be called with spinlock held, because it may | 965 | * This function *must* be called with spinlock held, because it may |
942 | * be called from the irq handler. - Jean II | 966 | * be called from the irq handler. - Jean II |
943 | */ | 967 | */ |
944 | static void smsc_ircc_change_speed(void *priv, u32 speed) | 968 | static void smsc_ircc_change_speed(struct smsc_ircc_cb *self, u32 speed) |
945 | { | 969 | { |
946 | struct smsc_ircc_cb *self = (struct smsc_ircc_cb *) priv; | ||
947 | struct net_device *dev; | 970 | struct net_device *dev; |
948 | int iobase; | ||
949 | int last_speed_was_sir; | 971 | int last_speed_was_sir; |
950 | 972 | ||
951 | IRDA_DEBUG(0, "%s() changing speed to: %d\n", __FUNCTION__, speed); | 973 | IRDA_DEBUG(0, "%s() changing speed to: %d\n", __FUNCTION__, speed); |
952 | 974 | ||
953 | IRDA_ASSERT(self != NULL, return;); | 975 | IRDA_ASSERT(self != NULL, return;); |
954 | dev = self->netdev; | 976 | dev = self->netdev; |
955 | iobase = self->io.fir_base; | ||
956 | 977 | ||
957 | last_speed_was_sir = self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED; | 978 | last_speed_was_sir = self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED; |
958 | 979 | ||
@@ -961,30 +982,30 @@ static void smsc_ircc_change_speed(void *priv, u32 speed) | |||
961 | speed= 1152000; | 982 | speed= 1152000; |
962 | self->io.speed = speed; | 983 | self->io.speed = speed; |
963 | last_speed_was_sir = 0; | 984 | last_speed_was_sir = 0; |
964 | smsc_ircc_fir_start(self); | 985 | smsc_ircc_fir_start(self); |
965 | #endif | 986 | #endif |
966 | 987 | ||
967 | if(self->io.speed == 0) | 988 | if (self->io.speed == 0) |
968 | smsc_ircc_sir_start(self); | 989 | smsc_ircc_sir_start(self); |
969 | 990 | ||
970 | #if 0 | 991 | #if 0 |
971 | if(!last_speed_was_sir) speed = self->io.speed; | 992 | if (!last_speed_was_sir) speed = self->io.speed; |
972 | #endif | 993 | #endif |
973 | 994 | ||
974 | if(self->io.speed != speed) smsc_ircc_set_transceiver_for_speed(self, speed); | 995 | if (self->io.speed != speed) |
996 | smsc_ircc_set_transceiver_for_speed(self, speed); | ||
975 | 997 | ||
976 | self->io.speed = speed; | 998 | self->io.speed = speed; |
977 | 999 | ||
978 | if(speed <= SMSC_IRCC2_MAX_SIR_SPEED) { | 1000 | if (speed <= SMSC_IRCC2_MAX_SIR_SPEED) { |
979 | if(!last_speed_was_sir) { | 1001 | if (!last_speed_was_sir) { |
980 | smsc_ircc_fir_stop(self); | 1002 | smsc_ircc_fir_stop(self); |
981 | smsc_ircc_sir_start(self); | 1003 | smsc_ircc_sir_start(self); |
982 | } | 1004 | } |
983 | smsc_ircc_set_sir_speed(self, speed); | 1005 | smsc_ircc_set_sir_speed(self, speed); |
984 | } | 1006 | } else { |
985 | else { | 1007 | if (last_speed_was_sir) { |
986 | if(last_speed_was_sir) { | 1008 | #if SMSC_IRCC2_C_SIR_STOP |
987 | #if SMSC_IRCC2_C_SIR_STOP | ||
988 | smsc_ircc_sir_stop(self); | 1009 | smsc_ircc_sir_stop(self); |
989 | #endif | 1010 | #endif |
990 | smsc_ircc_fir_start(self); | 1011 | smsc_ircc_fir_start(self); |
@@ -994,13 +1015,13 @@ static void smsc_ircc_change_speed(void *priv, u32 speed) | |||
994 | #if 0 | 1015 | #if 0 |
995 | self->tx_buff.len = 10; | 1016 | self->tx_buff.len = 10; |
996 | self->tx_buff.data = self->tx_buff.head; | 1017 | self->tx_buff.data = self->tx_buff.head; |
997 | 1018 | ||
998 | smsc_ircc_dma_xmit(self, iobase, 4000); | 1019 | smsc_ircc_dma_xmit(self, 4000); |
999 | #endif | 1020 | #endif |
1000 | /* Be ready for incoming frames */ | 1021 | /* Be ready for incoming frames */ |
1001 | smsc_ircc_dma_receive(self, iobase); | 1022 | smsc_ircc_dma_receive(self); |
1002 | } | 1023 | } |
1003 | 1024 | ||
1004 | netif_wake_queue(dev); | 1025 | netif_wake_queue(dev); |
1005 | } | 1026 | } |
1006 | 1027 | ||
@@ -1010,10 +1031,9 @@ static void smsc_ircc_change_speed(void *priv, u32 speed) | |||
1010 | * Set speed of IrDA port to specified baudrate | 1031 | * Set speed of IrDA port to specified baudrate |
1011 | * | 1032 | * |
1012 | */ | 1033 | */ |
1013 | void smsc_ircc_set_sir_speed(void *priv, __u32 speed) | 1034 | void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, __u32 speed) |
1014 | { | 1035 | { |
1015 | struct smsc_ircc_cb *self = (struct smsc_ircc_cb *) priv; | 1036 | int iobase; |
1016 | int iobase; | ||
1017 | int fcr; /* FIFO control reg */ | 1037 | int fcr; /* FIFO control reg */ |
1018 | int lcr; /* Line control reg */ | 1038 | int lcr; /* Line control reg */ |
1019 | int divisor; | 1039 | int divisor; |
@@ -1022,38 +1042,36 @@ void smsc_ircc_set_sir_speed(void *priv, __u32 speed) | |||
1022 | 1042 | ||
1023 | IRDA_ASSERT(self != NULL, return;); | 1043 | IRDA_ASSERT(self != NULL, return;); |
1024 | iobase = self->io.sir_base; | 1044 | iobase = self->io.sir_base; |
1025 | 1045 | ||
1026 | /* Update accounting for new speed */ | 1046 | /* Update accounting for new speed */ |
1027 | self->io.speed = speed; | 1047 | self->io.speed = speed; |
1028 | 1048 | ||
1029 | /* Turn off interrupts */ | 1049 | /* Turn off interrupts */ |
1030 | outb(0, iobase+UART_IER); | 1050 | outb(0, iobase + UART_IER); |
1051 | |||
1052 | divisor = SMSC_IRCC2_MAX_SIR_SPEED / speed; | ||
1031 | 1053 | ||
1032 | divisor = SMSC_IRCC2_MAX_SIR_SPEED/speed; | ||
1033 | |||
1034 | fcr = UART_FCR_ENABLE_FIFO; | 1054 | fcr = UART_FCR_ENABLE_FIFO; |
1035 | 1055 | ||
1036 | /* | 1056 | /* |
1037 | * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and | 1057 | * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and |
1038 | * almost 1,7 ms at 19200 bps. At speeds above that we can just forget | 1058 | * almost 1,7 ms at 19200 bps. At speeds above that we can just forget |
1039 | * about this timeout since it will always be fast enough. | 1059 | * about this timeout since it will always be fast enough. |
1040 | */ | 1060 | */ |
1041 | if (self->io.speed < 38400) | 1061 | fcr |= self->io.speed < 38400 ? |
1042 | fcr |= UART_FCR_TRIGGER_1; | 1062 | UART_FCR_TRIGGER_1 : UART_FCR_TRIGGER_14; |
1043 | else | 1063 | |
1044 | fcr |= UART_FCR_TRIGGER_14; | ||
1045 | |||
1046 | /* IrDA ports use 8N1 */ | 1064 | /* IrDA ports use 8N1 */ |
1047 | lcr = UART_LCR_WLEN8; | 1065 | lcr = UART_LCR_WLEN8; |
1048 | 1066 | ||
1049 | outb(UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */ | 1067 | outb(UART_LCR_DLAB | lcr, iobase + UART_LCR); /* Set DLAB */ |
1050 | outb(divisor & 0xff, iobase+UART_DLL); /* Set speed */ | 1068 | outb(divisor & 0xff, iobase + UART_DLL); /* Set speed */ |
1051 | outb(divisor >> 8, iobase+UART_DLM); | 1069 | outb(divisor >> 8, iobase + UART_DLM); |
1052 | outb(lcr, iobase+UART_LCR); /* Set 8N1 */ | 1070 | outb(lcr, iobase + UART_LCR); /* Set 8N1 */ |
1053 | outb(fcr, iobase+UART_FCR); /* Enable FIFO's */ | 1071 | outb(fcr, iobase + UART_FCR); /* Enable FIFO's */ |
1054 | 1072 | ||
1055 | /* Turn on interrups */ | 1073 | /* Turn on interrups */ |
1056 | outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, iobase+UART_IER); | 1074 | outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER); |
1057 | 1075 | ||
1058 | IRDA_DEBUG(2, "%s() speed changed to: %d\n", __FUNCTION__, speed); | 1076 | IRDA_DEBUG(2, "%s() speed changed to: %d\n", __FUNCTION__, speed); |
1059 | } | 1077 | } |
@@ -1070,15 +1088,12 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev) | |||
1070 | struct smsc_ircc_cb *self; | 1088 | struct smsc_ircc_cb *self; |
1071 | unsigned long flags; | 1089 | unsigned long flags; |
1072 | s32 speed; | 1090 | s32 speed; |
1073 | int iobase; | ||
1074 | int mtt; | 1091 | int mtt; |
1075 | 1092 | ||
1076 | IRDA_ASSERT(dev != NULL, return 0;); | 1093 | IRDA_ASSERT(dev != NULL, return 0;); |
1077 | self = (struct smsc_ircc_cb *) dev->priv; | 1094 | self = netdev_priv(dev); |
1078 | IRDA_ASSERT(self != NULL, return 0;); | 1095 | IRDA_ASSERT(self != NULL, return 0;); |
1079 | 1096 | ||
1080 | iobase = self->io.fir_base; | ||
1081 | |||
1082 | netif_stop_queue(dev); | 1097 | netif_stop_queue(dev); |
1083 | 1098 | ||
1084 | /* Make sure test of self->io.speed & speed change are atomic */ | 1099 | /* Make sure test of self->io.speed & speed change are atomic */ |
@@ -1086,30 +1101,31 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev) | |||
1086 | 1101 | ||
1087 | /* Check if we need to change the speed after this frame */ | 1102 | /* Check if we need to change the speed after this frame */ |
1088 | speed = irda_get_next_speed(skb); | 1103 | speed = irda_get_next_speed(skb); |
1089 | if ((speed != self->io.speed) && (speed != -1)) { | 1104 | if (speed != self->io.speed && speed != -1) { |
1090 | /* Check for empty frame */ | 1105 | /* Check for empty frame */ |
1091 | if (!skb->len) { | 1106 | if (!skb->len) { |
1092 | /* Note : you should make sure that speed changes | 1107 | /* Note : you should make sure that speed changes |
1093 | * are not going to corrupt any outgoing frame. | 1108 | * are not going to corrupt any outgoing frame. |
1094 | * Look at nsc-ircc for the gory details - Jean II */ | 1109 | * Look at nsc-ircc for the gory details - Jean II */ |
1095 | smsc_ircc_change_speed(self, speed); | 1110 | smsc_ircc_change_speed(self, speed); |
1096 | spin_unlock_irqrestore(&self->lock, flags); | 1111 | spin_unlock_irqrestore(&self->lock, flags); |
1097 | dev_kfree_skb(skb); | 1112 | dev_kfree_skb(skb); |
1098 | return 0; | 1113 | return 0; |
1099 | } else | 1114 | } |
1100 | self->new_speed = speed; | 1115 | |
1116 | self->new_speed = speed; | ||
1101 | } | 1117 | } |
1102 | 1118 | ||
1103 | memcpy(self->tx_buff.head, skb->data, skb->len); | 1119 | memcpy(self->tx_buff.head, skb->data, skb->len); |
1104 | 1120 | ||
1105 | self->tx_buff.len = skb->len; | 1121 | self->tx_buff.len = skb->len; |
1106 | self->tx_buff.data = self->tx_buff.head; | 1122 | self->tx_buff.data = self->tx_buff.head; |
1107 | 1123 | ||
1108 | mtt = irda_get_mtt(skb); | 1124 | mtt = irda_get_mtt(skb); |
1109 | if (mtt) { | 1125 | if (mtt) { |
1110 | int bofs; | 1126 | int bofs; |
1111 | 1127 | ||
1112 | /* | 1128 | /* |
1113 | * Compute how many BOFs (STA or PA's) we need to waste the | 1129 | * Compute how many BOFs (STA or PA's) we need to waste the |
1114 | * min turn time given the speed of the link. | 1130 | * min turn time given the speed of the link. |
1115 | */ | 1131 | */ |
@@ -1117,11 +1133,12 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev) | |||
1117 | if (bofs > 4095) | 1133 | if (bofs > 4095) |
1118 | bofs = 4095; | 1134 | bofs = 4095; |
1119 | 1135 | ||
1120 | smsc_ircc_dma_xmit(self, iobase, bofs); | 1136 | smsc_ircc_dma_xmit(self, bofs); |
1121 | } else { | 1137 | } else { |
1122 | /* Transmit frame */ | 1138 | /* Transmit frame */ |
1123 | smsc_ircc_dma_xmit(self, iobase, 0); | 1139 | smsc_ircc_dma_xmit(self, 0); |
1124 | } | 1140 | } |
1141 | |||
1125 | spin_unlock_irqrestore(&self->lock, flags); | 1142 | spin_unlock_irqrestore(&self->lock, flags); |
1126 | dev_kfree_skb(skb); | 1143 | dev_kfree_skb(skb); |
1127 | 1144 | ||
@@ -1129,43 +1146,44 @@ static int smsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev) | |||
1129 | } | 1146 | } |
1130 | 1147 | ||
1131 | /* | 1148 | /* |
1132 | * Function smsc_ircc_dma_xmit (self, iobase) | 1149 | * Function smsc_ircc_dma_xmit (self, bofs) |
1133 | * | 1150 | * |
1134 | * Transmit data using DMA | 1151 | * Transmit data using DMA |
1135 | * | 1152 | * |
1136 | */ | 1153 | */ |
1137 | static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int iobase, int bofs) | 1154 | static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int bofs) |
1138 | { | 1155 | { |
1156 | int iobase = self->io.fir_base; | ||
1139 | u8 ctrl; | 1157 | u8 ctrl; |
1140 | 1158 | ||
1141 | IRDA_DEBUG(3, "%s\n", __FUNCTION__); | 1159 | IRDA_DEBUG(3, "%s\n", __FUNCTION__); |
1142 | #if 1 | 1160 | #if 1 |
1143 | /* Disable Rx */ | 1161 | /* Disable Rx */ |
1144 | register_bank(iobase, 0); | 1162 | register_bank(iobase, 0); |
1145 | outb(0x00, iobase+IRCC_LCR_B); | 1163 | outb(0x00, iobase + IRCC_LCR_B); |
1146 | #endif | 1164 | #endif |
1147 | register_bank(iobase, 1); | 1165 | register_bank(iobase, 1); |
1148 | outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, | 1166 | outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, |
1149 | iobase+IRCC_SCE_CFGB); | 1167 | iobase + IRCC_SCE_CFGB); |
1150 | 1168 | ||
1151 | self->io.direction = IO_XMIT; | 1169 | self->io.direction = IO_XMIT; |
1152 | 1170 | ||
1153 | /* Set BOF additional count for generating the min turn time */ | 1171 | /* Set BOF additional count for generating the min turn time */ |
1154 | register_bank(iobase, 4); | 1172 | register_bank(iobase, 4); |
1155 | outb(bofs & 0xff, iobase+IRCC_BOF_COUNT_LO); | 1173 | outb(bofs & 0xff, iobase + IRCC_BOF_COUNT_LO); |
1156 | ctrl = inb(iobase+IRCC_CONTROL) & 0xf0; | 1174 | ctrl = inb(iobase + IRCC_CONTROL) & 0xf0; |
1157 | outb(ctrl | ((bofs >> 8) & 0x0f), iobase+IRCC_BOF_COUNT_HI); | 1175 | outb(ctrl | ((bofs >> 8) & 0x0f), iobase + IRCC_BOF_COUNT_HI); |
1158 | 1176 | ||
1159 | /* Set max Tx frame size */ | 1177 | /* Set max Tx frame size */ |
1160 | outb(self->tx_buff.len >> 8, iobase+IRCC_TX_SIZE_HI); | 1178 | outb(self->tx_buff.len >> 8, iobase + IRCC_TX_SIZE_HI); |
1161 | outb(self->tx_buff.len & 0xff, iobase+IRCC_TX_SIZE_LO); | 1179 | outb(self->tx_buff.len & 0xff, iobase + IRCC_TX_SIZE_LO); |
1162 | 1180 | ||
1163 | /*outb(UART_MCR_OUT2, self->io.sir_base + UART_MCR);*/ | 1181 | /*outb(UART_MCR_OUT2, self->io.sir_base + UART_MCR);*/ |
1164 | 1182 | ||
1165 | /* Enable burst mode chip Tx DMA */ | 1183 | /* Enable burst mode chip Tx DMA */ |
1166 | register_bank(iobase, 1); | 1184 | register_bank(iobase, 1); |
1167 | outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE | | 1185 | outb(inb(iobase + IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE | |
1168 | IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB); | 1186 | IRCC_CFGB_DMA_BURST, iobase + IRCC_SCE_CFGB); |
1169 | 1187 | ||
1170 | /* Setup DMA controller (must be done after enabling chip DMA) */ | 1188 | /* Setup DMA controller (must be done after enabling chip DMA) */ |
1171 | irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len, | 1189 | irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len, |
@@ -1174,50 +1192,52 @@ static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int iobase, int bofs) | |||
1174 | /* Enable interrupt */ | 1192 | /* Enable interrupt */ |
1175 | 1193 | ||
1176 | register_bank(iobase, 0); | 1194 | register_bank(iobase, 0); |
1177 | outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase+IRCC_IER); | 1195 | outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase + IRCC_IER); |
1178 | outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER); | 1196 | outb(IRCC_MASTER_INT_EN, iobase + IRCC_MASTER); |
1179 | 1197 | ||
1180 | /* Enable transmit */ | 1198 | /* Enable transmit */ |
1181 | outb(IRCC_LCR_B_SCE_TRANSMIT | IRCC_LCR_B_SIP_ENABLE, iobase+IRCC_LCR_B); | 1199 | outb(IRCC_LCR_B_SCE_TRANSMIT | IRCC_LCR_B_SIP_ENABLE, iobase + IRCC_LCR_B); |
1182 | } | 1200 | } |
1183 | 1201 | ||
1184 | /* | 1202 | /* |
1185 | * Function smsc_ircc_dma_xmit_complete (self) | 1203 | * Function smsc_ircc_dma_xmit_complete (self) |
1186 | * | 1204 | * |
1187 | * The transfer of a frame in finished. This function will only be called | 1205 | * The transfer of a frame in finished. This function will only be called |
1188 | * by the interrupt handler | 1206 | * by the interrupt handler |
1189 | * | 1207 | * |
1190 | */ | 1208 | */ |
1191 | static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self, int iobase) | 1209 | static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self) |
1192 | { | 1210 | { |
1211 | int iobase = self->io.fir_base; | ||
1212 | |||
1193 | IRDA_DEBUG(3, "%s\n", __FUNCTION__); | 1213 | IRDA_DEBUG(3, "%s\n", __FUNCTION__); |
1194 | #if 0 | 1214 | #if 0 |
1195 | /* Disable Tx */ | 1215 | /* Disable Tx */ |
1196 | register_bank(iobase, 0); | 1216 | register_bank(iobase, 0); |
1197 | outb(0x00, iobase+IRCC_LCR_B); | 1217 | outb(0x00, iobase + IRCC_LCR_B); |
1198 | #endif | 1218 | #endif |
1199 | register_bank(self->io.fir_base, 1); | 1219 | register_bank(iobase, 1); |
1200 | outb(inb(self->io.fir_base+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, | 1220 | outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, |
1201 | self->io.fir_base+IRCC_SCE_CFGB); | 1221 | iobase + IRCC_SCE_CFGB); |
1202 | 1222 | ||
1203 | /* Check for underrun! */ | 1223 | /* Check for underrun! */ |
1204 | register_bank(iobase, 0); | 1224 | register_bank(iobase, 0); |
1205 | if (inb(iobase+IRCC_LSR) & IRCC_LSR_UNDERRUN) { | 1225 | if (inb(iobase + IRCC_LSR) & IRCC_LSR_UNDERRUN) { |
1206 | self->stats.tx_errors++; | 1226 | self->stats.tx_errors++; |
1207 | self->stats.tx_fifo_errors++; | 1227 | self->stats.tx_fifo_errors++; |
1208 | 1228 | ||
1209 | /* Reset error condition */ | 1229 | /* Reset error condition */ |
1210 | register_bank(iobase, 0); | 1230 | register_bank(iobase, 0); |
1211 | outb(IRCC_MASTER_ERROR_RESET, iobase+IRCC_MASTER); | 1231 | outb(IRCC_MASTER_ERROR_RESET, iobase + IRCC_MASTER); |
1212 | outb(0x00, iobase+IRCC_MASTER); | 1232 | outb(0x00, iobase + IRCC_MASTER); |
1213 | } else { | 1233 | } else { |
1214 | self->stats.tx_packets++; | 1234 | self->stats.tx_packets++; |
1215 | self->stats.tx_bytes += self->tx_buff.len; | 1235 | self->stats.tx_bytes += self->tx_buff.len; |
1216 | } | 1236 | } |
1217 | 1237 | ||
1218 | /* Check if it's time to change the speed */ | 1238 | /* Check if it's time to change the speed */ |
1219 | if (self->new_speed) { | 1239 | if (self->new_speed) { |
1220 | smsc_ircc_change_speed(self, self->new_speed); | 1240 | smsc_ircc_change_speed(self, self->new_speed); |
1221 | self->new_speed = 0; | 1241 | self->new_speed = 0; |
1222 | } | 1242 | } |
1223 | 1243 | ||
@@ -1231,31 +1251,32 @@ static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self, int iobase) | |||
1231 | * if it starts to receive a frame. | 1251 | * if it starts to receive a frame. |
1232 | * | 1252 | * |
1233 | */ | 1253 | */ |
1234 | static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase) | 1254 | static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self) |
1235 | { | 1255 | { |
1256 | int iobase = self->io.fir_base; | ||
1236 | #if 0 | 1257 | #if 0 |
1237 | /* Turn off chip DMA */ | 1258 | /* Turn off chip DMA */ |
1238 | register_bank(iobase, 1); | 1259 | register_bank(iobase, 1); |
1239 | outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, | 1260 | outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, |
1240 | iobase+IRCC_SCE_CFGB); | 1261 | iobase + IRCC_SCE_CFGB); |
1241 | #endif | 1262 | #endif |
1242 | 1263 | ||
1243 | /* Disable Tx */ | 1264 | /* Disable Tx */ |
1244 | register_bank(iobase, 0); | 1265 | register_bank(iobase, 0); |
1245 | outb(0x00, iobase+IRCC_LCR_B); | 1266 | outb(0x00, iobase + IRCC_LCR_B); |
1246 | 1267 | ||
1247 | /* Turn off chip DMA */ | 1268 | /* Turn off chip DMA */ |
1248 | register_bank(iobase, 1); | 1269 | register_bank(iobase, 1); |
1249 | outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, | 1270 | outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, |
1250 | iobase+IRCC_SCE_CFGB); | 1271 | iobase + IRCC_SCE_CFGB); |
1251 | 1272 | ||
1252 | self->io.direction = IO_RECV; | 1273 | self->io.direction = IO_RECV; |
1253 | self->rx_buff.data = self->rx_buff.head; | 1274 | self->rx_buff.data = self->rx_buff.head; |
1254 | 1275 | ||
1255 | /* Set max Rx frame size */ | 1276 | /* Set max Rx frame size */ |
1256 | register_bank(iobase, 4); | 1277 | register_bank(iobase, 4); |
1257 | outb((2050 >> 8) & 0x0f, iobase+IRCC_RX_SIZE_HI); | 1278 | outb((2050 >> 8) & 0x0f, iobase + IRCC_RX_SIZE_HI); |
1258 | outb(2050 & 0xff, iobase+IRCC_RX_SIZE_LO); | 1279 | outb(2050 & 0xff, iobase + IRCC_RX_SIZE_LO); |
1259 | 1280 | ||
1260 | /* Setup DMA controller */ | 1281 | /* Setup DMA controller */ |
1261 | irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize, | 1282 | irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize, |
@@ -1263,83 +1284,83 @@ static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self, int iobase) | |||
1263 | 1284 | ||
1264 | /* Enable burst mode chip Rx DMA */ | 1285 | /* Enable burst mode chip Rx DMA */ |
1265 | register_bank(iobase, 1); | 1286 | register_bank(iobase, 1); |
1266 | outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE | | 1287 | outb(inb(iobase + IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE | |
1267 | IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB); | 1288 | IRCC_CFGB_DMA_BURST, iobase + IRCC_SCE_CFGB); |
1268 | 1289 | ||
1269 | /* Enable interrupt */ | 1290 | /* Enable interrupt */ |
1270 | register_bank(iobase, 0); | 1291 | register_bank(iobase, 0); |
1271 | outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase+IRCC_IER); | 1292 | outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase + IRCC_IER); |
1272 | outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER); | 1293 | outb(IRCC_MASTER_INT_EN, iobase + IRCC_MASTER); |
1273 | |||
1274 | 1294 | ||
1275 | /* Enable receiver */ | 1295 | /* Enable receiver */ |
1276 | register_bank(iobase, 0); | 1296 | register_bank(iobase, 0); |
1277 | outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE, | 1297 | outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE, |
1278 | iobase+IRCC_LCR_B); | 1298 | iobase + IRCC_LCR_B); |
1279 | 1299 | ||
1280 | return 0; | 1300 | return 0; |
1281 | } | 1301 | } |
1282 | 1302 | ||
1283 | /* | 1303 | /* |
1284 | * Function smsc_ircc_dma_receive_complete(self, iobase) | 1304 | * Function smsc_ircc_dma_receive_complete(self) |
1285 | * | 1305 | * |
1286 | * Finished with receiving frames | 1306 | * Finished with receiving frames |
1287 | * | 1307 | * |
1288 | */ | 1308 | */ |
1289 | static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self, int iobase) | 1309 | static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self) |
1290 | { | 1310 | { |
1291 | struct sk_buff *skb; | 1311 | struct sk_buff *skb; |
1292 | int len, msgcnt, lsr; | 1312 | int len, msgcnt, lsr; |
1293 | 1313 | int iobase = self->io.fir_base; | |
1314 | |||
1294 | register_bank(iobase, 0); | 1315 | register_bank(iobase, 0); |
1295 | 1316 | ||
1296 | IRDA_DEBUG(3, "%s\n", __FUNCTION__); | 1317 | IRDA_DEBUG(3, "%s\n", __FUNCTION__); |
1297 | #if 0 | 1318 | #if 0 |
1298 | /* Disable Rx */ | 1319 | /* Disable Rx */ |
1299 | register_bank(iobase, 0); | 1320 | register_bank(iobase, 0); |
1300 | outb(0x00, iobase+IRCC_LCR_B); | 1321 | outb(0x00, iobase + IRCC_LCR_B); |
1301 | #endif | 1322 | #endif |
1302 | register_bank(iobase, 0); | 1323 | register_bank(iobase, 0); |
1303 | outb(inb(iobase+IRCC_LSAR) & ~IRCC_LSAR_ADDRESS_MASK, iobase+IRCC_LSAR); | 1324 | outb(inb(iobase + IRCC_LSAR) & ~IRCC_LSAR_ADDRESS_MASK, iobase + IRCC_LSAR); |
1304 | lsr= inb(iobase+IRCC_LSR); | 1325 | lsr= inb(iobase + IRCC_LSR); |
1305 | msgcnt = inb(iobase+IRCC_LCR_B) & 0x08; | 1326 | msgcnt = inb(iobase + IRCC_LCR_B) & 0x08; |
1306 | 1327 | ||
1307 | IRDA_DEBUG(2, "%s: dma count = %d\n", __FUNCTION__, | 1328 | IRDA_DEBUG(2, "%s: dma count = %d\n", __FUNCTION__, |
1308 | get_dma_residue(self->io.dma)); | 1329 | get_dma_residue(self->io.dma)); |
1309 | 1330 | ||
1310 | len = self->rx_buff.truesize - get_dma_residue(self->io.dma); | 1331 | len = self->rx_buff.truesize - get_dma_residue(self->io.dma); |
1311 | 1332 | ||
1312 | /* Look for errors | 1333 | /* Look for errors */ |
1313 | */ | 1334 | if (lsr & (IRCC_LSR_FRAME_ERROR | IRCC_LSR_CRC_ERROR | IRCC_LSR_SIZE_ERROR)) { |
1314 | |||
1315 | if(lsr & (IRCC_LSR_FRAME_ERROR | IRCC_LSR_CRC_ERROR | IRCC_LSR_SIZE_ERROR)) { | ||
1316 | self->stats.rx_errors++; | 1335 | self->stats.rx_errors++; |
1317 | if(lsr & IRCC_LSR_FRAME_ERROR) self->stats.rx_frame_errors++; | 1336 | if (lsr & IRCC_LSR_FRAME_ERROR) |
1318 | if(lsr & IRCC_LSR_CRC_ERROR) self->stats.rx_crc_errors++; | 1337 | self->stats.rx_frame_errors++; |
1319 | if(lsr & IRCC_LSR_SIZE_ERROR) self->stats.rx_length_errors++; | 1338 | if (lsr & IRCC_LSR_CRC_ERROR) |
1320 | if(lsr & (IRCC_LSR_UNDERRUN | IRCC_LSR_OVERRUN)) self->stats.rx_length_errors++; | 1339 | self->stats.rx_crc_errors++; |
1340 | if (lsr & IRCC_LSR_SIZE_ERROR) | ||
1341 | self->stats.rx_length_errors++; | ||
1342 | if (lsr & (IRCC_LSR_UNDERRUN | IRCC_LSR_OVERRUN)) | ||
1343 | self->stats.rx_length_errors++; | ||
1321 | return; | 1344 | return; |
1322 | } | 1345 | } |
1346 | |||
1323 | /* Remove CRC */ | 1347 | /* Remove CRC */ |
1324 | if (self->io.speed < 4000000) | 1348 | len -= self->io.speed < 4000000 ? 2 : 4; |
1325 | len -= 2; | ||
1326 | else | ||
1327 | len -= 4; | ||
1328 | 1349 | ||
1329 | if ((len < 2) || (len > 2050)) { | 1350 | if (len < 2 || len > 2050) { |
1330 | IRDA_WARNING("%s(), bogus len=%d\n", __FUNCTION__, len); | 1351 | IRDA_WARNING("%s(), bogus len=%d\n", __FUNCTION__, len); |
1331 | return; | 1352 | return; |
1332 | } | 1353 | } |
1333 | IRDA_DEBUG(2, "%s: msgcnt = %d, len=%d\n", __FUNCTION__, msgcnt, len); | 1354 | IRDA_DEBUG(2, "%s: msgcnt = %d, len=%d\n", __FUNCTION__, msgcnt, len); |
1334 | 1355 | ||
1335 | skb = dev_alloc_skb(len+1); | 1356 | skb = dev_alloc_skb(len + 1); |
1336 | if (!skb) { | 1357 | if (!skb) { |
1337 | IRDA_WARNING("%s(), memory squeeze, dropping frame.\n", | 1358 | IRDA_WARNING("%s(), memory squeeze, dropping frame.\n", |
1338 | __FUNCTION__); | 1359 | __FUNCTION__); |
1339 | return; | 1360 | return; |
1340 | } | 1361 | } |
1341 | /* Make sure IP header gets aligned */ | 1362 | /* Make sure IP header gets aligned */ |
1342 | skb_reserve(skb, 1); | 1363 | skb_reserve(skb, 1); |
1343 | 1364 | ||
1344 | memcpy(skb_put(skb, len), self->rx_buff.data, len); | 1365 | memcpy(skb_put(skb, len), self->rx_buff.data, len); |
1345 | self->stats.rx_packets++; | 1366 | self->stats.rx_packets++; |
@@ -1357,7 +1378,7 @@ static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self, int iobase | |||
1357 | * Receive one frame from the infrared port | 1378 | * Receive one frame from the infrared port |
1358 | * | 1379 | * |
1359 | */ | 1380 | */ |
1360 | static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self) | 1381 | static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self) |
1361 | { | 1382 | { |
1362 | int boguscount = 0; | 1383 | int boguscount = 0; |
1363 | int iobase; | 1384 | int iobase; |
@@ -1366,20 +1387,20 @@ static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self) | |||
1366 | 1387 | ||
1367 | iobase = self->io.sir_base; | 1388 | iobase = self->io.sir_base; |
1368 | 1389 | ||
1369 | /* | 1390 | /* |
1370 | * Receive all characters in Rx FIFO, unwrap and unstuff them. | 1391 | * Receive all characters in Rx FIFO, unwrap and unstuff them. |
1371 | * async_unwrap_char will deliver all found frames | 1392 | * async_unwrap_char will deliver all found frames |
1372 | */ | 1393 | */ |
1373 | do { | 1394 | do { |
1374 | async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, | 1395 | async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, |
1375 | inb(iobase+UART_RX)); | 1396 | inb(iobase + UART_RX)); |
1376 | 1397 | ||
1377 | /* Make sure we don't stay here to long */ | 1398 | /* Make sure we don't stay here to long */ |
1378 | if (boguscount++ > 32) { | 1399 | if (boguscount++ > 32) { |
1379 | IRDA_DEBUG(2, "%s(), breaking!\n", __FUNCTION__); | 1400 | IRDA_DEBUG(2, "%s(), breaking!\n", __FUNCTION__); |
1380 | break; | 1401 | break; |
1381 | } | 1402 | } |
1382 | } while (inb(iobase+UART_LSR) & UART_LSR_DR); | 1403 | } while (inb(iobase + UART_LSR) & UART_LSR_DR); |
1383 | } | 1404 | } |
1384 | 1405 | ||
1385 | 1406 | ||
@@ -1397,18 +1418,19 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re | |||
1397 | irqreturn_t ret = IRQ_NONE; | 1418 | irqreturn_t ret = IRQ_NONE; |
1398 | 1419 | ||
1399 | if (dev == NULL) { | 1420 | if (dev == NULL) { |
1400 | printk(KERN_WARNING "%s: irq %d for unknown device.\n", | 1421 | printk(KERN_WARNING "%s: irq %d for unknown device.\n", |
1401 | driver_name, irq); | 1422 | driver_name, irq); |
1402 | goto irq_ret; | 1423 | goto irq_ret; |
1403 | } | 1424 | } |
1404 | self = (struct smsc_ircc_cb *) dev->priv; | 1425 | |
1426 | self = netdev_priv(dev); | ||
1405 | IRDA_ASSERT(self != NULL, return IRQ_NONE;); | 1427 | IRDA_ASSERT(self != NULL, return IRQ_NONE;); |
1406 | 1428 | ||
1407 | /* Serialise the interrupt handler in various CPUs, stop Tx path */ | 1429 | /* Serialise the interrupt handler in various CPUs, stop Tx path */ |
1408 | spin_lock(&self->lock); | 1430 | spin_lock(&self->lock); |
1409 | 1431 | ||
1410 | /* Check if we should use the SIR interrupt handler */ | 1432 | /* Check if we should use the SIR interrupt handler */ |
1411 | if (self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED) { | 1433 | if (self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED) { |
1412 | ret = smsc_ircc_interrupt_sir(dev); | 1434 | ret = smsc_ircc_interrupt_sir(dev); |
1413 | goto irq_ret_unlock; | 1435 | goto irq_ret_unlock; |
1414 | } | 1436 | } |
@@ -1416,25 +1438,25 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re | |||
1416 | iobase = self->io.fir_base; | 1438 | iobase = self->io.fir_base; |
1417 | 1439 | ||
1418 | register_bank(iobase, 0); | 1440 | register_bank(iobase, 0); |
1419 | iir = inb(iobase+IRCC_IIR); | 1441 | iir = inb(iobase + IRCC_IIR); |
1420 | if (iir == 0) | 1442 | if (iir == 0) |
1421 | goto irq_ret_unlock; | 1443 | goto irq_ret_unlock; |
1422 | ret = IRQ_HANDLED; | 1444 | ret = IRQ_HANDLED; |
1423 | 1445 | ||
1424 | /* Disable interrupts */ | 1446 | /* Disable interrupts */ |
1425 | outb(0, iobase+IRCC_IER); | 1447 | outb(0, iobase + IRCC_IER); |
1426 | lcra = inb(iobase+IRCC_LCR_A); | 1448 | lcra = inb(iobase + IRCC_LCR_A); |
1427 | lsr = inb(iobase+IRCC_LSR); | 1449 | lsr = inb(iobase + IRCC_LSR); |
1428 | 1450 | ||
1429 | IRDA_DEBUG(2, "%s(), iir = 0x%02x\n", __FUNCTION__, iir); | 1451 | IRDA_DEBUG(2, "%s(), iir = 0x%02x\n", __FUNCTION__, iir); |
1430 | 1452 | ||
1431 | if (iir & IRCC_IIR_EOM) { | 1453 | if (iir & IRCC_IIR_EOM) { |
1432 | if (self->io.direction == IO_RECV) | 1454 | if (self->io.direction == IO_RECV) |
1433 | smsc_ircc_dma_receive_complete(self, iobase); | 1455 | smsc_ircc_dma_receive_complete(self); |
1434 | else | 1456 | else |
1435 | smsc_ircc_dma_xmit_complete(self, iobase); | 1457 | smsc_ircc_dma_xmit_complete(self); |
1436 | 1458 | ||
1437 | smsc_ircc_dma_receive(self, iobase); | 1459 | smsc_ircc_dma_receive(self); |
1438 | } | 1460 | } |
1439 | 1461 | ||
1440 | if (iir & IRCC_IIR_ACTIVE_FRAME) { | 1462 | if (iir & IRCC_IIR_ACTIVE_FRAME) { |
@@ -1444,7 +1466,7 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re | |||
1444 | /* Enable interrupts again */ | 1466 | /* Enable interrupts again */ |
1445 | 1467 | ||
1446 | register_bank(iobase, 0); | 1468 | register_bank(iobase, 0); |
1447 | outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, iobase+IRCC_IER); | 1469 | outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase + IRCC_IER); |
1448 | 1470 | ||
1449 | irq_ret_unlock: | 1471 | irq_ret_unlock: |
1450 | spin_unlock(&self->lock); | 1472 | spin_unlock(&self->lock); |
@@ -1459,7 +1481,7 @@ static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *re | |||
1459 | */ | 1481 | */ |
1460 | static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev) | 1482 | static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev) |
1461 | { | 1483 | { |
1462 | struct smsc_ircc_cb *self = dev->priv; | 1484 | struct smsc_ircc_cb *self = netdev_priv(dev); |
1463 | int boguscount = 0; | 1485 | int boguscount = 0; |
1464 | int iobase; | 1486 | int iobase; |
1465 | int iir, lsr; | 1487 | int iir, lsr; |
@@ -1469,14 +1491,14 @@ static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev) | |||
1469 | 1491 | ||
1470 | iobase = self->io.sir_base; | 1492 | iobase = self->io.sir_base; |
1471 | 1493 | ||
1472 | iir = inb(iobase+UART_IIR) & UART_IIR_ID; | 1494 | iir = inb(iobase + UART_IIR) & UART_IIR_ID; |
1473 | if (iir == 0) | 1495 | if (iir == 0) |
1474 | return IRQ_NONE; | 1496 | return IRQ_NONE; |
1475 | while (iir) { | 1497 | while (iir) { |
1476 | /* Clear interrupt */ | 1498 | /* Clear interrupt */ |
1477 | lsr = inb(iobase+UART_LSR); | 1499 | lsr = inb(iobase + UART_LSR); |
1478 | 1500 | ||
1479 | IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", | 1501 | IRDA_DEBUG(4, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n", |
1480 | __FUNCTION__, iir, lsr, iobase); | 1502 | __FUNCTION__, iir, lsr, iobase); |
1481 | 1503 | ||
1482 | switch (iir) { | 1504 | switch (iir) { |
@@ -1496,13 +1518,13 @@ static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev) | |||
1496 | IRDA_DEBUG(0, "%s(), unhandled IIR=%#x\n", | 1518 | IRDA_DEBUG(0, "%s(), unhandled IIR=%#x\n", |
1497 | __FUNCTION__, iir); | 1519 | __FUNCTION__, iir); |
1498 | break; | 1520 | break; |
1499 | } | 1521 | } |
1500 | 1522 | ||
1501 | /* Make sure we don't stay here to long */ | 1523 | /* Make sure we don't stay here to long */ |
1502 | if (boguscount++ > 100) | 1524 | if (boguscount++ > 100) |
1503 | break; | 1525 | break; |
1504 | 1526 | ||
1505 | iir = inb(iobase + UART_IIR) & UART_IIR_ID; | 1527 | iir = inb(iobase + UART_IIR) & UART_IIR_ID; |
1506 | } | 1528 | } |
1507 | /*spin_unlock(&self->lock);*/ | 1529 | /*spin_unlock(&self->lock);*/ |
1508 | return IRQ_HANDLED; | 1530 | return IRQ_HANDLED; |
@@ -1529,7 +1551,7 @@ static int ircc_is_receiving(struct smsc_ircc_cb *self) | |||
1529 | get_dma_residue(self->io.dma)); | 1551 | get_dma_residue(self->io.dma)); |
1530 | 1552 | ||
1531 | status = (self->rx_buff.state != OUTSIDE_FRAME); | 1553 | status = (self->rx_buff.state != OUTSIDE_FRAME); |
1532 | 1554 | ||
1533 | return status; | 1555 | return status; |
1534 | } | 1556 | } |
1535 | #endif /* unused */ | 1557 | #endif /* unused */ |
@@ -1544,19 +1566,16 @@ static int ircc_is_receiving(struct smsc_ircc_cb *self) | |||
1544 | static int smsc_ircc_net_open(struct net_device *dev) | 1566 | static int smsc_ircc_net_open(struct net_device *dev) |
1545 | { | 1567 | { |
1546 | struct smsc_ircc_cb *self; | 1568 | struct smsc_ircc_cb *self; |
1547 | int iobase; | ||
1548 | char hwname[16]; | 1569 | char hwname[16]; |
1549 | unsigned long flags; | 1570 | unsigned long flags; |
1550 | 1571 | ||
1551 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); | 1572 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); |
1552 | 1573 | ||
1553 | IRDA_ASSERT(dev != NULL, return -1;); | 1574 | IRDA_ASSERT(dev != NULL, return -1;); |
1554 | self = (struct smsc_ircc_cb *) dev->priv; | 1575 | self = netdev_priv(dev); |
1555 | IRDA_ASSERT(self != NULL, return 0;); | 1576 | IRDA_ASSERT(self != NULL, return 0;); |
1556 | |||
1557 | iobase = self->io.fir_base; | ||
1558 | 1577 | ||
1559 | if (request_irq(self->io.irq, smsc_ircc_interrupt, 0, dev->name, | 1578 | if (request_irq(self->io.irq, smsc_ircc_interrupt, 0, dev->name, |
1560 | (void *) dev)) { | 1579 | (void *) dev)) { |
1561 | IRDA_DEBUG(0, "%s(), unable to allocate irq=%d\n", | 1580 | IRDA_DEBUG(0, "%s(), unable to allocate irq=%d\n", |
1562 | __FUNCTION__, self->io.irq); | 1581 | __FUNCTION__, self->io.irq); |
@@ -1568,14 +1587,14 @@ static int smsc_ircc_net_open(struct net_device *dev) | |||
1568 | self->io.speed = 0; | 1587 | self->io.speed = 0; |
1569 | smsc_ircc_change_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED); | 1588 | smsc_ircc_change_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED); |
1570 | spin_unlock_irqrestore(&self->lock, flags); | 1589 | spin_unlock_irqrestore(&self->lock, flags); |
1571 | 1590 | ||
1572 | /* Give self a hardware name */ | 1591 | /* Give self a hardware name */ |
1573 | /* It would be cool to offer the chip revision here - Jean II */ | 1592 | /* It would be cool to offer the chip revision here - Jean II */ |
1574 | sprintf(hwname, "SMSC @ 0x%03x", self->io.fir_base); | 1593 | sprintf(hwname, "SMSC @ 0x%03x", self->io.fir_base); |
1575 | 1594 | ||
1576 | /* | 1595 | /* |
1577 | * Open new IrLAP layer instance, now that everything should be | 1596 | * Open new IrLAP layer instance, now that everything should be |
1578 | * initialized properly | 1597 | * initialized properly |
1579 | */ | 1598 | */ |
1580 | self->irlap = irlap_open(dev, &self->qos, hwname); | 1599 | self->irlap = irlap_open(dev, &self->qos, hwname); |
1581 | 1600 | ||
@@ -1590,7 +1609,7 @@ static int smsc_ircc_net_open(struct net_device *dev) | |||
1590 | __FUNCTION__, self->io.dma); | 1609 | __FUNCTION__, self->io.dma); |
1591 | return -EAGAIN; | 1610 | return -EAGAIN; |
1592 | } | 1611 | } |
1593 | 1612 | ||
1594 | netif_start_queue(dev); | 1613 | netif_start_queue(dev); |
1595 | 1614 | ||
1596 | return 0; | 1615 | return 0; |
@@ -1605,73 +1624,53 @@ static int smsc_ircc_net_open(struct net_device *dev) | |||
1605 | static int smsc_ircc_net_close(struct net_device *dev) | 1624 | static int smsc_ircc_net_close(struct net_device *dev) |
1606 | { | 1625 | { |
1607 | struct smsc_ircc_cb *self; | 1626 | struct smsc_ircc_cb *self; |
1608 | int iobase; | ||
1609 | 1627 | ||
1610 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); | 1628 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); |
1611 | 1629 | ||
1612 | IRDA_ASSERT(dev != NULL, return -1;); | 1630 | IRDA_ASSERT(dev != NULL, return -1;); |
1613 | self = (struct smsc_ircc_cb *) dev->priv; | 1631 | self = netdev_priv(dev); |
1614 | IRDA_ASSERT(self != NULL, return 0;); | 1632 | IRDA_ASSERT(self != NULL, return 0;); |
1615 | |||
1616 | iobase = self->io.fir_base; | ||
1617 | 1633 | ||
1618 | /* Stop device */ | 1634 | /* Stop device */ |
1619 | netif_stop_queue(dev); | 1635 | netif_stop_queue(dev); |
1620 | 1636 | ||
1621 | /* Stop and remove instance of IrLAP */ | 1637 | /* Stop and remove instance of IrLAP */ |
1622 | if (self->irlap) | 1638 | if (self->irlap) |
1623 | irlap_close(self->irlap); | 1639 | irlap_close(self->irlap); |
1624 | self->irlap = NULL; | 1640 | self->irlap = NULL; |
1625 | 1641 | ||
1626 | free_irq(self->io.irq, dev); | 1642 | free_irq(self->io.irq, dev); |
1627 | |||
1628 | disable_dma(self->io.dma); | 1643 | disable_dma(self->io.dma); |
1629 | |||
1630 | free_dma(self->io.dma); | 1644 | free_dma(self->io.dma); |
1631 | 1645 | ||
1632 | return 0; | 1646 | return 0; |
1633 | } | 1647 | } |
1634 | 1648 | ||
1635 | 1649 | static int smsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level) | |
1636 | static void smsc_ircc_suspend(struct smsc_ircc_cb *self) | ||
1637 | { | 1650 | { |
1638 | IRDA_MESSAGE("%s, Suspending\n", driver_name); | 1651 | struct smsc_ircc_cb *self = dev_get_drvdata(dev); |
1639 | 1652 | ||
1640 | if (self->io.suspended) | 1653 | IRDA_MESSAGE("%s, Suspending\n", driver_name); |
1641 | return; | ||
1642 | 1654 | ||
1643 | smsc_ircc_net_close(self->netdev); | 1655 | if (level == SUSPEND_DISABLE && !self->io.suspended) { |
1656 | smsc_ircc_net_close(self->netdev); | ||
1657 | self->io.suspended = 1; | ||
1658 | } | ||
1644 | 1659 | ||
1645 | self->io.suspended = 1; | 1660 | return 0; |
1646 | } | 1661 | } |
1647 | 1662 | ||
1648 | static void smsc_ircc_wakeup(struct smsc_ircc_cb *self) | 1663 | static int smsc_ircc_resume(struct device *dev, u32 level) |
1649 | { | 1664 | { |
1650 | if (!self->io.suspended) | 1665 | struct smsc_ircc_cb *self = dev_get_drvdata(dev); |
1651 | return; | ||
1652 | 1666 | ||
1653 | /* The code was doing a "cli()" here, but this can't be right. | 1667 | if (level == RESUME_ENABLE && self->io.suspended) { |
1654 | * If you need protection, do it in net_open with a spinlock | ||
1655 | * or give a good reason. - Jean II */ | ||
1656 | 1668 | ||
1657 | smsc_ircc_net_open(self->netdev); | 1669 | smsc_ircc_net_open(self->netdev); |
1658 | 1670 | self->io.suspended = 0; | |
1659 | IRDA_MESSAGE("%s, Waking up\n", driver_name); | ||
1660 | } | ||
1661 | 1671 | ||
1662 | static int smsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data) | 1672 | IRDA_MESSAGE("%s, Waking up\n", driver_name); |
1663 | { | 1673 | } |
1664 | struct smsc_ircc_cb *self = (struct smsc_ircc_cb*) dev->data; | ||
1665 | if (self) { | ||
1666 | switch (rqst) { | ||
1667 | case PM_SUSPEND: | ||
1668 | smsc_ircc_suspend(self); | ||
1669 | break; | ||
1670 | case PM_RESUME: | ||
1671 | smsc_ircc_wakeup(self); | ||
1672 | break; | ||
1673 | } | ||
1674 | } | ||
1675 | return 0; | 1674 | return 0; |
1676 | } | 1675 | } |
1677 | 1676 | ||
@@ -1690,10 +1689,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) | |||
1690 | 1689 | ||
1691 | IRDA_ASSERT(self != NULL, return -1;); | 1690 | IRDA_ASSERT(self != NULL, return -1;); |
1692 | 1691 | ||
1693 | iobase = self->io.fir_base; | 1692 | platform_device_unregister(self->pldev); |
1694 | |||
1695 | if (self->pmdev) | ||
1696 | pm_unregister(self->pmdev); | ||
1697 | 1693 | ||
1698 | /* Remove netdevice */ | 1694 | /* Remove netdevice */ |
1699 | unregister_netdev(self->netdev); | 1695 | unregister_netdev(self->netdev); |
@@ -1702,15 +1698,16 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) | |||
1702 | spin_lock_irqsave(&self->lock, flags); | 1698 | spin_lock_irqsave(&self->lock, flags); |
1703 | 1699 | ||
1704 | /* Stop interrupts */ | 1700 | /* Stop interrupts */ |
1701 | iobase = self->io.fir_base; | ||
1705 | register_bank(iobase, 0); | 1702 | register_bank(iobase, 0); |
1706 | outb(0, iobase+IRCC_IER); | 1703 | outb(0, iobase + IRCC_IER); |
1707 | outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER); | 1704 | outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER); |
1708 | outb(0x00, iobase+IRCC_MASTER); | 1705 | outb(0x00, iobase + IRCC_MASTER); |
1709 | #if 0 | 1706 | #if 0 |
1710 | /* Reset to SIR mode */ | 1707 | /* Reset to SIR mode */ |
1711 | register_bank(iobase, 1); | 1708 | register_bank(iobase, 1); |
1712 | outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase+IRCC_SCE_CFGA); | 1709 | outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase + IRCC_SCE_CFGA); |
1713 | outb(IRCC_CFGB_IR, iobase+IRCC_SCE_CFGB); | 1710 | outb(IRCC_CFGB_IR, iobase + IRCC_SCE_CFGB); |
1714 | #endif | 1711 | #endif |
1715 | spin_unlock_irqrestore(&self->lock, flags); | 1712 | spin_unlock_irqrestore(&self->lock, flags); |
1716 | 1713 | ||
@@ -1720,7 +1717,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) | |||
1720 | 1717 | ||
1721 | release_region(self->io.fir_base, self->io.fir_ext); | 1718 | release_region(self->io.fir_base, self->io.fir_ext); |
1722 | 1719 | ||
1723 | IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __FUNCTION__, | 1720 | IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __FUNCTION__, |
1724 | self->io.sir_base); | 1721 | self->io.sir_base); |
1725 | 1722 | ||
1726 | release_region(self->io.sir_base, self->io.sir_ext); | 1723 | release_region(self->io.sir_base, self->io.sir_ext); |
@@ -1728,7 +1725,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) | |||
1728 | if (self->tx_buff.head) | 1725 | if (self->tx_buff.head) |
1729 | dma_free_coherent(NULL, self->tx_buff.truesize, | 1726 | dma_free_coherent(NULL, self->tx_buff.truesize, |
1730 | self->tx_buff.head, self->tx_buff_dma); | 1727 | self->tx_buff.head, self->tx_buff_dma); |
1731 | 1728 | ||
1732 | if (self->rx_buff.head) | 1729 | if (self->rx_buff.head) |
1733 | dma_free_coherent(NULL, self->rx_buff.truesize, | 1730 | dma_free_coherent(NULL, self->rx_buff.truesize, |
1734 | self->rx_buff.head, self->rx_buff_dma); | 1731 | self->rx_buff.head, self->rx_buff_dma); |
@@ -1744,10 +1741,12 @@ static void __exit smsc_ircc_cleanup(void) | |||
1744 | 1741 | ||
1745 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); | 1742 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); |
1746 | 1743 | ||
1747 | for (i=0; i < 2; i++) { | 1744 | for (i = 0; i < 2; i++) { |
1748 | if (dev_self[i]) | 1745 | if (dev_self[i]) |
1749 | smsc_ircc_close(dev_self[i]); | 1746 | smsc_ircc_close(dev_self[i]); |
1750 | } | 1747 | } |
1748 | |||
1749 | driver_unregister(&smsc_ircc_driver); | ||
1751 | } | 1750 | } |
1752 | 1751 | ||
1753 | /* | 1752 | /* |
@@ -1763,34 +1762,34 @@ void smsc_ircc_sir_start(struct smsc_ircc_cb *self) | |||
1763 | 1762 | ||
1764 | IRDA_DEBUG(3, "%s\n", __FUNCTION__); | 1763 | IRDA_DEBUG(3, "%s\n", __FUNCTION__); |
1765 | 1764 | ||
1766 | IRDA_ASSERT(self != NULL, return;); | 1765 | IRDA_ASSERT(self != NULL, return;); |
1767 | dev= self->netdev; | 1766 | dev = self->netdev; |
1768 | IRDA_ASSERT(dev != NULL, return;); | 1767 | IRDA_ASSERT(dev != NULL, return;); |
1769 | dev->hard_start_xmit = &smsc_ircc_hard_xmit_sir; | 1768 | dev->hard_start_xmit = &smsc_ircc_hard_xmit_sir; |
1770 | 1769 | ||
1771 | fir_base = self->io.fir_base; | 1770 | fir_base = self->io.fir_base; |
1772 | sir_base = self->io.sir_base; | 1771 | sir_base = self->io.sir_base; |
1773 | 1772 | ||
1774 | /* Reset everything */ | 1773 | /* Reset everything */ |
1775 | outb(IRCC_MASTER_RESET, fir_base+IRCC_MASTER); | 1774 | outb(IRCC_MASTER_RESET, fir_base + IRCC_MASTER); |
1776 | 1775 | ||
1777 | #if SMSC_IRCC2_C_SIR_STOP | 1776 | #if SMSC_IRCC2_C_SIR_STOP |
1778 | /*smsc_ircc_sir_stop(self);*/ | 1777 | /*smsc_ircc_sir_stop(self);*/ |
1779 | #endif | 1778 | #endif |
1780 | 1779 | ||
1781 | register_bank(fir_base, 1); | 1780 | register_bank(fir_base, 1); |
1782 | outb(((inb(fir_base+IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | IRCC_CFGA_IRDA_SIR_A), fir_base+IRCC_SCE_CFGA); | 1781 | outb(((inb(fir_base + IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | IRCC_CFGA_IRDA_SIR_A), fir_base + IRCC_SCE_CFGA); |
1783 | 1782 | ||
1784 | /* Initialize UART */ | 1783 | /* Initialize UART */ |
1785 | outb(UART_LCR_WLEN8, sir_base+UART_LCR); /* Reset DLAB */ | 1784 | outb(UART_LCR_WLEN8, sir_base + UART_LCR); /* Reset DLAB */ |
1786 | outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), sir_base+UART_MCR); | 1785 | outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), sir_base + UART_MCR); |
1787 | 1786 | ||
1788 | /* Turn on interrups */ | 1787 | /* Turn on interrups */ |
1789 | outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, sir_base+UART_IER); | 1788 | outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, sir_base + UART_IER); |
1790 | 1789 | ||
1791 | IRDA_DEBUG(3, "%s() - exit\n", __FUNCTION__); | 1790 | IRDA_DEBUG(3, "%s() - exit\n", __FUNCTION__); |
1792 | 1791 | ||
1793 | outb(0x00, fir_base+IRCC_MASTER); | 1792 | outb(0x00, fir_base + IRCC_MASTER); |
1794 | } | 1793 | } |
1795 | 1794 | ||
1796 | #if SMSC_IRCC2_C_SIR_STOP | 1795 | #if SMSC_IRCC2_C_SIR_STOP |
@@ -1802,10 +1801,10 @@ void smsc_ircc_sir_stop(struct smsc_ircc_cb *self) | |||
1802 | iobase = self->io.sir_base; | 1801 | iobase = self->io.sir_base; |
1803 | 1802 | ||
1804 | /* Reset UART */ | 1803 | /* Reset UART */ |
1805 | outb(0, iobase+UART_MCR); | 1804 | outb(0, iobase + UART_MCR); |
1806 | 1805 | ||
1807 | /* Turn off interrupts */ | 1806 | /* Turn off interrupts */ |
1808 | outb(0, iobase+UART_IER); | 1807 | outb(0, iobase + UART_IER); |
1809 | } | 1808 | } |
1810 | #endif | 1809 | #endif |
1811 | 1810 | ||
@@ -1831,16 +1830,16 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self) | |||
1831 | /* Finished with frame? */ | 1830 | /* Finished with frame? */ |
1832 | if (self->tx_buff.len > 0) { | 1831 | if (self->tx_buff.len > 0) { |
1833 | /* Write data left in transmit buffer */ | 1832 | /* Write data left in transmit buffer */ |
1834 | actual = smsc_ircc_sir_write(iobase, self->io.fifo_size, | 1833 | actual = smsc_ircc_sir_write(iobase, self->io.fifo_size, |
1835 | self->tx_buff.data, self->tx_buff.len); | 1834 | self->tx_buff.data, self->tx_buff.len); |
1836 | self->tx_buff.data += actual; | 1835 | self->tx_buff.data += actual; |
1837 | self->tx_buff.len -= actual; | 1836 | self->tx_buff.len -= actual; |
1838 | } else { | 1837 | } else { |
1839 | 1838 | ||
1840 | /*if (self->tx_buff.len ==0) {*/ | 1839 | /*if (self->tx_buff.len ==0) {*/ |
1841 | 1840 | ||
1842 | /* | 1841 | /* |
1843 | * Now serial buffer is almost free & we can start | 1842 | * Now serial buffer is almost free & we can start |
1844 | * transmission of another packet. But first we must check | 1843 | * transmission of another packet. But first we must check |
1845 | * if we need to change the speed of the hardware | 1844 | * if we need to change the speed of the hardware |
1846 | */ | 1845 | */ |
@@ -1856,21 +1855,19 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self) | |||
1856 | } | 1855 | } |
1857 | self->stats.tx_packets++; | 1856 | self->stats.tx_packets++; |
1858 | 1857 | ||
1859 | if(self->io.speed <= 115200) { | 1858 | if (self->io.speed <= 115200) { |
1860 | /* | 1859 | /* |
1861 | * Reset Rx FIFO to make sure that all reflected transmit data | 1860 | * Reset Rx FIFO to make sure that all reflected transmit data |
1862 | * is discarded. This is needed for half duplex operation | 1861 | * is discarded. This is needed for half duplex operation |
1863 | */ | 1862 | */ |
1864 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR; | 1863 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR; |
1865 | if (self->io.speed < 38400) | 1864 | fcr |= self->io.speed < 38400 ? |
1866 | fcr |= UART_FCR_TRIGGER_1; | 1865 | UART_FCR_TRIGGER_1 : UART_FCR_TRIGGER_14; |
1867 | else | ||
1868 | fcr |= UART_FCR_TRIGGER_14; | ||
1869 | 1866 | ||
1870 | outb(fcr, iobase+UART_FCR); | 1867 | outb(fcr, iobase + UART_FCR); |
1871 | 1868 | ||
1872 | /* Turn on receive interrupts */ | 1869 | /* Turn on receive interrupts */ |
1873 | outb(UART_IER_RDI, iobase+UART_IER); | 1870 | outb(UART_IER_RDI, iobase + UART_IER); |
1874 | } | 1871 | } |
1875 | } | 1872 | } |
1876 | } | 1873 | } |
@@ -1884,17 +1881,17 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self) | |||
1884 | static int smsc_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len) | 1881 | static int smsc_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len) |
1885 | { | 1882 | { |
1886 | int actual = 0; | 1883 | int actual = 0; |
1887 | 1884 | ||
1888 | /* Tx FIFO should be empty! */ | 1885 | /* Tx FIFO should be empty! */ |
1889 | if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { | 1886 | if (!(inb(iobase + UART_LSR) & UART_LSR_THRE)) { |
1890 | IRDA_WARNING("%s(), failed, fifo not empty!\n", __FUNCTION__); | 1887 | IRDA_WARNING("%s(), failed, fifo not empty!\n", __FUNCTION__); |
1891 | return 0; | 1888 | return 0; |
1892 | } | 1889 | } |
1893 | 1890 | ||
1894 | /* Fill FIFO with current frame */ | 1891 | /* Fill FIFO with current frame */ |
1895 | while ((fifo_size-- > 0) && (actual < len)) { | 1892 | while (fifo_size-- > 0 && actual < len) { |
1896 | /* Transmit next byte */ | 1893 | /* Transmit next byte */ |
1897 | outb(buf[actual], iobase+UART_TX); | 1894 | outb(buf[actual], iobase + UART_TX); |
1898 | actual++; | 1895 | actual++; |
1899 | } | 1896 | } |
1900 | return actual; | 1897 | return actual; |
@@ -1921,20 +1918,21 @@ static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self) | |||
1921 | static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self) | 1918 | static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self) |
1922 | { | 1919 | { |
1923 | unsigned int i; | 1920 | unsigned int i; |
1924 | 1921 | ||
1925 | IRDA_ASSERT(self != NULL, return;); | 1922 | IRDA_ASSERT(self != NULL, return;); |
1926 | 1923 | ||
1927 | for(i=0; smsc_transceivers[i].name!=NULL; i++) | 1924 | for (i = 0; smsc_transceivers[i].name != NULL; i++) |
1928 | if((*smsc_transceivers[i].probe)(self->io.fir_base)) { | 1925 | if (smsc_transceivers[i].probe(self->io.fir_base)) { |
1929 | IRDA_MESSAGE(" %s transceiver found\n", | 1926 | IRDA_MESSAGE(" %s transceiver found\n", |
1930 | smsc_transceivers[i].name); | 1927 | smsc_transceivers[i].name); |
1931 | self->transceiver= i+1; | 1928 | self->transceiver= i + 1; |
1932 | return; | 1929 | return; |
1933 | } | 1930 | } |
1931 | |||
1934 | IRDA_MESSAGE("No transceiver found. Defaulting to %s\n", | 1932 | IRDA_MESSAGE("No transceiver found. Defaulting to %s\n", |
1935 | smsc_transceivers[SMSC_IRCC2_C_DEFAULT_TRANSCEIVER].name); | 1933 | smsc_transceivers[SMSC_IRCC2_C_DEFAULT_TRANSCEIVER].name); |
1936 | 1934 | ||
1937 | self->transceiver= SMSC_IRCC2_C_DEFAULT_TRANSCEIVER; | 1935 | self->transceiver = SMSC_IRCC2_C_DEFAULT_TRANSCEIVER; |
1938 | } | 1936 | } |
1939 | 1937 | ||
1940 | 1938 | ||
@@ -1947,9 +1945,10 @@ static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self) | |||
1947 | static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed) | 1945 | static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed) |
1948 | { | 1946 | { |
1949 | unsigned int trx; | 1947 | unsigned int trx; |
1950 | 1948 | ||
1951 | trx = self->transceiver; | 1949 | trx = self->transceiver; |
1952 | if(trx>0) (*smsc_transceivers[trx-1].set_for_speed)(self->io.fir_base, speed); | 1950 | if (trx > 0) |
1951 | smsc_transceivers[trx - 1].set_for_speed(self->io.fir_base, speed); | ||
1953 | } | 1952 | } |
1954 | 1953 | ||
1955 | /* | 1954 | /* |
@@ -1977,16 +1976,14 @@ static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 s | |||
1977 | 1976 | ||
1978 | static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self) | 1977 | static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self) |
1979 | { | 1978 | { |
1980 | int iobase; | 1979 | int iobase = self->io.sir_base; |
1981 | int count = SMSC_IRCC2_HW_TRANSMITTER_TIMEOUT_US; | 1980 | int count = SMSC_IRCC2_HW_TRANSMITTER_TIMEOUT_US; |
1982 | 1981 | ||
1983 | iobase = self->io.sir_base; | ||
1984 | |||
1985 | /* Calibrated busy loop */ | 1982 | /* Calibrated busy loop */ |
1986 | while((count-- > 0) && !(inb(iobase+UART_LSR) & UART_LSR_TEMT)) | 1983 | while (count-- > 0 && !(inb(iobase + UART_LSR) & UART_LSR_TEMT)) |
1987 | udelay(1); | 1984 | udelay(1); |
1988 | 1985 | ||
1989 | if(count == 0) | 1986 | if (count == 0) |
1990 | IRDA_DEBUG(0, "%s(): stuck transmitter\n", __FUNCTION__); | 1987 | IRDA_DEBUG(0, "%s(): stuck transmitter\n", __FUNCTION__); |
1991 | } | 1988 | } |
1992 | 1989 | ||
@@ -1998,40 +1995,42 @@ static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self) | |||
1998 | 1995 | ||
1999 | static int __init smsc_ircc_look_for_chips(void) | 1996 | static int __init smsc_ircc_look_for_chips(void) |
2000 | { | 1997 | { |
2001 | smsc_chip_address_t *address; | 1998 | struct smsc_chip_address *address; |
2002 | char *type; | 1999 | char *type; |
2003 | unsigned int cfg_base, found; | 2000 | unsigned int cfg_base, found; |
2004 | 2001 | ||
2005 | found = 0; | 2002 | found = 0; |
2006 | address = possible_addresses; | 2003 | address = possible_addresses; |
2007 | 2004 | ||
2008 | while(address->cfg_base){ | 2005 | while (address->cfg_base) { |
2009 | cfg_base = address->cfg_base; | 2006 | cfg_base = address->cfg_base; |
2010 | 2007 | ||
2011 | /*printk(KERN_WARNING "%s(): probing: 0x%02x for: 0x%02x\n", __FUNCTION__, cfg_base, address->type);*/ | 2008 | /*printk(KERN_WARNING "%s(): probing: 0x%02x for: 0x%02x\n", __FUNCTION__, cfg_base, address->type);*/ |
2012 | 2009 | ||
2013 | if( address->type & SMSCSIO_TYPE_FDC){ | 2010 | if (address->type & SMSCSIO_TYPE_FDC) { |
2014 | type = "FDC"; | 2011 | type = "FDC"; |
2015 | if((address->type) & SMSCSIO_TYPE_FLAT) { | 2012 | if (address->type & SMSCSIO_TYPE_FLAT) |
2016 | if(!smsc_superio_flat(fdc_chips_flat,cfg_base, type)) found++; | 2013 | if (!smsc_superio_flat(fdc_chips_flat, cfg_base, type)) |
2017 | } | 2014 | found++; |
2018 | if((address->type) & SMSCSIO_TYPE_PAGED) { | 2015 | |
2019 | if(!smsc_superio_paged(fdc_chips_paged,cfg_base, type)) found++; | 2016 | if (address->type & SMSCSIO_TYPE_PAGED) |
2020 | } | 2017 | if (!smsc_superio_paged(fdc_chips_paged, cfg_base, type)) |
2018 | found++; | ||
2021 | } | 2019 | } |
2022 | if( address->type & SMSCSIO_TYPE_LPC){ | 2020 | if (address->type & SMSCSIO_TYPE_LPC) { |
2023 | type = "LPC"; | 2021 | type = "LPC"; |
2024 | if((address->type) & SMSCSIO_TYPE_FLAT) { | 2022 | if (address->type & SMSCSIO_TYPE_FLAT) |
2025 | if(!smsc_superio_flat(lpc_chips_flat,cfg_base,type)) found++; | 2023 | if (!smsc_superio_flat(lpc_chips_flat, cfg_base, type)) |
2026 | } | 2024 | found++; |
2027 | if((address->type) & SMSCSIO_TYPE_PAGED) { | 2025 | |
2028 | if(!smsc_superio_paged(lpc_chips_paged,cfg_base,"LPC")) found++; | 2026 | if (address->type & SMSCSIO_TYPE_PAGED) |
2029 | } | 2027 | if (!smsc_superio_paged(lpc_chips_paged, cfg_base, type)) |
2028 | found++; | ||
2030 | } | 2029 | } |
2031 | address++; | 2030 | address++; |
2032 | } | 2031 | } |
2033 | return found; | 2032 | return found; |
2034 | } | 2033 | } |
2035 | 2034 | ||
2036 | /* | 2035 | /* |
2037 | * Function smsc_superio_flat (chip, base, type) | 2036 | * Function smsc_superio_flat (chip, base, type) |
@@ -2039,7 +2038,7 @@ static int __init smsc_ircc_look_for_chips(void) | |||
2039 | * Try to get configuration of a smc SuperIO chip with flat register model | 2038 | * Try to get configuration of a smc SuperIO chip with flat register model |
2040 | * | 2039 | * |
2041 | */ | 2040 | */ |
2042 | static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfgbase, char *type) | 2041 | static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned short cfgbase, char *type) |
2043 | { | 2042 | { |
2044 | unsigned short firbase, sirbase; | 2043 | unsigned short firbase, sirbase; |
2045 | u8 mode, dma, irq; | 2044 | u8 mode, dma, irq; |
@@ -2047,39 +2046,37 @@ static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfg | |||
2047 | 2046 | ||
2048 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); | 2047 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); |
2049 | 2048 | ||
2050 | if (smsc_ircc_probe(cfgbase, SMSCSIOFLAT_DEVICEID_REG, chips, type)==NULL) | 2049 | if (smsc_ircc_probe(cfgbase, SMSCSIOFLAT_DEVICEID_REG, chips, type) == NULL) |
2051 | return ret; | 2050 | return ret; |
2052 | 2051 | ||
2053 | outb(SMSCSIOFLAT_UARTMODE0C_REG, cfgbase); | 2052 | outb(SMSCSIOFLAT_UARTMODE0C_REG, cfgbase); |
2054 | mode = inb(cfgbase+1); | 2053 | mode = inb(cfgbase + 1); |
2055 | 2054 | ||
2056 | /*printk(KERN_WARNING "%s(): mode: 0x%02x\n", __FUNCTION__, mode);*/ | 2055 | /*printk(KERN_WARNING "%s(): mode: 0x%02x\n", __FUNCTION__, mode);*/ |
2057 | 2056 | ||
2058 | if(!(mode & SMSCSIOFLAT_UART2MODE_VAL_IRDA)) | 2057 | if (!(mode & SMSCSIOFLAT_UART2MODE_VAL_IRDA)) |
2059 | IRDA_WARNING("%s(): IrDA not enabled\n", __FUNCTION__); | 2058 | IRDA_WARNING("%s(): IrDA not enabled\n", __FUNCTION__); |
2060 | 2059 | ||
2061 | outb(SMSCSIOFLAT_UART2BASEADDR_REG, cfgbase); | 2060 | outb(SMSCSIOFLAT_UART2BASEADDR_REG, cfgbase); |
2062 | sirbase = inb(cfgbase+1) << 2; | 2061 | sirbase = inb(cfgbase + 1) << 2; |
2063 | 2062 | ||
2064 | /* FIR iobase */ | 2063 | /* FIR iobase */ |
2065 | outb(SMSCSIOFLAT_FIRBASEADDR_REG, cfgbase); | 2064 | outb(SMSCSIOFLAT_FIRBASEADDR_REG, cfgbase); |
2066 | firbase = inb(cfgbase+1) << 3; | 2065 | firbase = inb(cfgbase + 1) << 3; |
2067 | 2066 | ||
2068 | /* DMA */ | 2067 | /* DMA */ |
2069 | outb(SMSCSIOFLAT_FIRDMASELECT_REG, cfgbase); | 2068 | outb(SMSCSIOFLAT_FIRDMASELECT_REG, cfgbase); |
2070 | dma = inb(cfgbase+1) & SMSCSIOFLAT_FIRDMASELECT_MASK; | 2069 | dma = inb(cfgbase + 1) & SMSCSIOFLAT_FIRDMASELECT_MASK; |
2071 | 2070 | ||
2072 | /* IRQ */ | 2071 | /* IRQ */ |
2073 | outb(SMSCSIOFLAT_UARTIRQSELECT_REG, cfgbase); | 2072 | outb(SMSCSIOFLAT_UARTIRQSELECT_REG, cfgbase); |
2074 | irq = inb(cfgbase+1) & SMSCSIOFLAT_UART2IRQSELECT_MASK; | 2073 | irq = inb(cfgbase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK; |
2075 | 2074 | ||
2076 | IRDA_MESSAGE("%s(): fir: 0x%02x, sir: 0x%02x, dma: %02d, irq: %d, mode: 0x%02x\n", __FUNCTION__, firbase, sirbase, dma, irq, mode); | 2075 | IRDA_MESSAGE("%s(): fir: 0x%02x, sir: 0x%02x, dma: %02d, irq: %d, mode: 0x%02x\n", __FUNCTION__, firbase, sirbase, dma, irq, mode); |
2077 | 2076 | ||
2078 | if (firbase) { | 2077 | if (firbase && smsc_ircc_open(firbase, sirbase, dma, irq) == 0) |
2079 | if (smsc_ircc_open(firbase, sirbase, dma, irq) == 0) | 2078 | ret = 0; |
2080 | ret=0; | 2079 | |
2081 | } | ||
2082 | |||
2083 | /* Exit configuration */ | 2080 | /* Exit configuration */ |
2084 | outb(SMSCSIO_CFGEXITKEY, cfgbase); | 2081 | outb(SMSCSIO_CFGEXITKEY, cfgbase); |
2085 | 2082 | ||
@@ -2092,26 +2089,26 @@ static int __init smsc_superio_flat(const smsc_chip_t *chips, unsigned short cfg | |||
2092 | * Try to get configuration of a smc SuperIO chip with paged register model | 2089 | * Try to get configuration of a smc SuperIO chip with paged register model |
2093 | * | 2090 | * |
2094 | */ | 2091 | */ |
2095 | static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cfg_base, char *type) | 2092 | static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type) |
2096 | { | 2093 | { |
2097 | unsigned short fir_io, sir_io; | 2094 | unsigned short fir_io, sir_io; |
2098 | int ret = -ENODEV; | 2095 | int ret = -ENODEV; |
2099 | 2096 | ||
2100 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); | 2097 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); |
2101 | 2098 | ||
2102 | if (smsc_ircc_probe(cfg_base,0x20,chips,type)==NULL) | 2099 | if (smsc_ircc_probe(cfg_base, 0x20, chips, type) == NULL) |
2103 | return ret; | 2100 | return ret; |
2104 | 2101 | ||
2105 | /* Select logical device (UART2) */ | 2102 | /* Select logical device (UART2) */ |
2106 | outb(0x07, cfg_base); | 2103 | outb(0x07, cfg_base); |
2107 | outb(0x05, cfg_base + 1); | 2104 | outb(0x05, cfg_base + 1); |
2108 | 2105 | ||
2109 | /* SIR iobase */ | 2106 | /* SIR iobase */ |
2110 | outb(0x60, cfg_base); | 2107 | outb(0x60, cfg_base); |
2111 | sir_io = inb(cfg_base + 1) << 8; | 2108 | sir_io = inb(cfg_base + 1) << 8; |
2112 | outb(0x61, cfg_base); | 2109 | outb(0x61, cfg_base); |
2113 | sir_io |= inb(cfg_base + 1); | 2110 | sir_io |= inb(cfg_base + 1); |
2114 | 2111 | ||
2115 | /* Read FIR base */ | 2112 | /* Read FIR base */ |
2116 | outb(0x62, cfg_base); | 2113 | outb(0x62, cfg_base); |
2117 | fir_io = inb(cfg_base + 1) << 8; | 2114 | fir_io = inb(cfg_base + 1) << 8; |
@@ -2119,11 +2116,9 @@ static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cf | |||
2119 | fir_io |= inb(cfg_base + 1); | 2116 | fir_io |= inb(cfg_base + 1); |
2120 | outb(0x2b, cfg_base); /* ??? */ | 2117 | outb(0x2b, cfg_base); /* ??? */ |
2121 | 2118 | ||
2122 | if (fir_io) { | 2119 | if (fir_io && smsc_ircc_open(fir_io, sir_io, ircc_dma, ircc_irq) == 0) |
2123 | if (smsc_ircc_open(fir_io, sir_io, ircc_dma, ircc_irq) == 0) | 2120 | ret = 0; |
2124 | ret=0; | 2121 | |
2125 | } | ||
2126 | |||
2127 | /* Exit configuration */ | 2122 | /* Exit configuration */ |
2128 | outb(SMSCSIO_CFGEXITKEY, cfg_base); | 2123 | outb(SMSCSIO_CFGEXITKEY, cfg_base); |
2129 | 2124 | ||
@@ -2131,21 +2126,17 @@ static int __init smsc_superio_paged(const smsc_chip_t *chips, unsigned short cf | |||
2131 | } | 2126 | } |
2132 | 2127 | ||
2133 | 2128 | ||
2134 | static int __init smsc_access(unsigned short cfg_base,unsigned char reg) | 2129 | static int __init smsc_access(unsigned short cfg_base, unsigned char reg) |
2135 | { | 2130 | { |
2136 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); | 2131 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); |
2137 | 2132 | ||
2138 | outb(reg, cfg_base); | 2133 | outb(reg, cfg_base); |
2139 | 2134 | return inb(cfg_base) != reg ? -1 : 0; | |
2140 | if (inb(cfg_base)!=reg) | ||
2141 | return -1; | ||
2142 | |||
2143 | return 0; | ||
2144 | } | 2135 | } |
2145 | 2136 | ||
2146 | static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg,const smsc_chip_t *chip,char *type) | 2137 | static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type) |
2147 | { | 2138 | { |
2148 | u8 devid,xdevid,rev; | 2139 | u8 devid, xdevid, rev; |
2149 | 2140 | ||
2150 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); | 2141 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); |
2151 | 2142 | ||
@@ -2158,7 +2149,7 @@ static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg | |||
2158 | 2149 | ||
2159 | outb(reg, cfg_base); | 2150 | outb(reg, cfg_base); |
2160 | 2151 | ||
2161 | xdevid=inb(cfg_base+1); | 2152 | xdevid = inb(cfg_base + 1); |
2162 | 2153 | ||
2163 | /* Enter configuration */ | 2154 | /* Enter configuration */ |
2164 | 2155 | ||
@@ -2168,51 +2159,49 @@ static const smsc_chip_t * __init smsc_ircc_probe(unsigned short cfg_base,u8 reg | |||
2168 | if (smsc_access(cfg_base,0x55)) /* send second key and check */ | 2159 | if (smsc_access(cfg_base,0x55)) /* send second key and check */ |
2169 | return NULL; | 2160 | return NULL; |
2170 | #endif | 2161 | #endif |
2171 | 2162 | ||
2172 | /* probe device ID */ | 2163 | /* probe device ID */ |
2173 | 2164 | ||
2174 | if (smsc_access(cfg_base,reg)) | 2165 | if (smsc_access(cfg_base, reg)) |
2175 | return NULL; | 2166 | return NULL; |
2176 | 2167 | ||
2177 | devid=inb(cfg_base+1); | 2168 | devid = inb(cfg_base + 1); |
2178 | |||
2179 | if (devid==0) /* typical value for unused port */ | ||
2180 | return NULL; | ||
2181 | 2169 | ||
2182 | if (devid==0xff) /* typical value for unused port */ | 2170 | if (devid == 0 || devid == 0xff) /* typical values for unused port */ |
2183 | return NULL; | 2171 | return NULL; |
2184 | 2172 | ||
2185 | /* probe revision ID */ | 2173 | /* probe revision ID */ |
2186 | 2174 | ||
2187 | if (smsc_access(cfg_base,reg+1)) | 2175 | if (smsc_access(cfg_base, reg + 1)) |
2188 | return NULL; | 2176 | return NULL; |
2189 | 2177 | ||
2190 | rev=inb(cfg_base+1); | 2178 | rev = inb(cfg_base + 1); |
2191 | 2179 | ||
2192 | if (rev>=128) /* i think this will make no sense */ | 2180 | if (rev >= 128) /* i think this will make no sense */ |
2193 | return NULL; | 2181 | return NULL; |
2194 | 2182 | ||
2195 | if (devid==xdevid) /* protection against false positives */ | 2183 | if (devid == xdevid) /* protection against false positives */ |
2196 | return NULL; | 2184 | return NULL; |
2197 | 2185 | ||
2198 | /* Check for expected device ID; are there others? */ | 2186 | /* Check for expected device ID; are there others? */ |
2199 | 2187 | ||
2200 | while(chip->devid!=devid) { | 2188 | while (chip->devid != devid) { |
2201 | 2189 | ||
2202 | chip++; | 2190 | chip++; |
2203 | 2191 | ||
2204 | if (chip->name==NULL) | 2192 | if (chip->name == NULL) |
2205 | return NULL; | 2193 | return NULL; |
2206 | } | 2194 | } |
2207 | 2195 | ||
2208 | IRDA_MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n",devid,rev,cfg_base,type,chip->name); | 2196 | IRDA_MESSAGE("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n", |
2197 | devid, rev, cfg_base, type, chip->name); | ||
2209 | 2198 | ||
2210 | if (chip->rev>rev){ | 2199 | if (chip->rev > rev) { |
2211 | IRDA_MESSAGE("Revision higher than expected\n"); | 2200 | IRDA_MESSAGE("Revision higher than expected\n"); |
2212 | return NULL; | 2201 | return NULL; |
2213 | } | 2202 | } |
2214 | 2203 | ||
2215 | if (chip->flags&NoIRDA) | 2204 | if (chip->flags & NoIRDA) |
2216 | IRDA_MESSAGE("chipset does not support IRDA\n"); | 2205 | IRDA_MESSAGE("chipset does not support IRDA\n"); |
2217 | 2206 | ||
2218 | return chip; | 2207 | return chip; |
@@ -2226,8 +2215,8 @@ static int __init smsc_superio_fdc(unsigned short cfg_base) | |||
2226 | IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n", | 2215 | IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n", |
2227 | __FUNCTION__, cfg_base); | 2216 | __FUNCTION__, cfg_base); |
2228 | } else { | 2217 | } else { |
2229 | if (!smsc_superio_flat(fdc_chips_flat,cfg_base,"FDC") | 2218 | if (!smsc_superio_flat(fdc_chips_flat, cfg_base, "FDC") || |
2230 | ||!smsc_superio_paged(fdc_chips_paged,cfg_base,"FDC")) | 2219 | !smsc_superio_paged(fdc_chips_paged, cfg_base, "FDC")) |
2231 | ret = 0; | 2220 | ret = 0; |
2232 | 2221 | ||
2233 | release_region(cfg_base, 2); | 2222 | release_region(cfg_base, 2); |
@@ -2244,9 +2233,10 @@ static int __init smsc_superio_lpc(unsigned short cfg_base) | |||
2244 | IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n", | 2233 | IRDA_WARNING("%s: can't get cfg_base of 0x%03x\n", |
2245 | __FUNCTION__, cfg_base); | 2234 | __FUNCTION__, cfg_base); |
2246 | } else { | 2235 | } else { |
2247 | if (!smsc_superio_flat(lpc_chips_flat,cfg_base,"LPC") | 2236 | if (!smsc_superio_flat(lpc_chips_flat, cfg_base, "LPC") || |
2248 | ||!smsc_superio_paged(lpc_chips_paged,cfg_base,"LPC")) | 2237 | !smsc_superio_paged(lpc_chips_paged, cfg_base, "LPC")) |
2249 | ret = 0; | 2238 | ret = 0; |
2239 | |||
2250 | release_region(cfg_base, 2); | 2240 | release_region(cfg_base, 2); |
2251 | } | 2241 | } |
2252 | return ret; | 2242 | return ret; |
@@ -2269,18 +2259,23 @@ static int __init smsc_superio_lpc(unsigned short cfg_base) | |||
2269 | static void smsc_ircc_set_transceiver_smsc_ircc_atc(int fir_base, u32 speed) | 2259 | static void smsc_ircc_set_transceiver_smsc_ircc_atc(int fir_base, u32 speed) |
2270 | { | 2260 | { |
2271 | unsigned long jiffies_now, jiffies_timeout; | 2261 | unsigned long jiffies_now, jiffies_timeout; |
2272 | u8 val; | 2262 | u8 val; |
2273 | 2263 | ||
2274 | jiffies_now= jiffies; | 2264 | jiffies_now = jiffies; |
2275 | jiffies_timeout= jiffies+SMSC_IRCC2_ATC_PROGRAMMING_TIMEOUT_JIFFIES; | 2265 | jiffies_timeout = jiffies + SMSC_IRCC2_ATC_PROGRAMMING_TIMEOUT_JIFFIES; |
2276 | 2266 | ||
2277 | /* ATC */ | 2267 | /* ATC */ |
2278 | register_bank(fir_base, 4); | 2268 | register_bank(fir_base, 4); |
2279 | outb((inb(fir_base+IRCC_ATC) & IRCC_ATC_MASK) |IRCC_ATC_nPROGREADY|IRCC_ATC_ENABLE, fir_base+IRCC_ATC); | 2269 | outb((inb(fir_base + IRCC_ATC) & IRCC_ATC_MASK) | IRCC_ATC_nPROGREADY|IRCC_ATC_ENABLE, |
2280 | while((val=(inb(fir_base+IRCC_ATC) & IRCC_ATC_nPROGREADY)) && !time_after(jiffies, jiffies_timeout)); | 2270 | fir_base + IRCC_ATC); |
2281 | if(val) | 2271 | |
2272 | while ((val = (inb(fir_base + IRCC_ATC) & IRCC_ATC_nPROGREADY)) && | ||
2273 | !time_after(jiffies, jiffies_timeout)) | ||
2274 | /* empty */; | ||
2275 | |||
2276 | if (val) | ||
2282 | IRDA_WARNING("%s(): ATC: 0x%02x\n", __FUNCTION__, | 2277 | IRDA_WARNING("%s(): ATC: 0x%02x\n", __FUNCTION__, |
2283 | inb(fir_base+IRCC_ATC)); | 2278 | inb(fir_base + IRCC_ATC)); |
2284 | } | 2279 | } |
2285 | 2280 | ||
2286 | /* | 2281 | /* |
@@ -2298,34 +2293,32 @@ static int smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base) | |||
2298 | /* | 2293 | /* |
2299 | * Function smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(self, speed) | 2294 | * Function smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(self, speed) |
2300 | * | 2295 | * |
2301 | * Set transceiver | 2296 | * Set transceiver |
2302 | * | 2297 | * |
2303 | */ | 2298 | */ |
2304 | 2299 | ||
2305 | static void smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(int fir_base, u32 speed) | 2300 | static void smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(int fir_base, u32 speed) |
2306 | { | 2301 | { |
2307 | u8 fast_mode; | 2302 | u8 fast_mode; |
2308 | 2303 | ||
2309 | switch(speed) | 2304 | switch (speed) { |
2310 | { | 2305 | default: |
2311 | default: | 2306 | case 576000 : |
2312 | case 576000 : | 2307 | fast_mode = 0; |
2313 | fast_mode = 0; | ||
2314 | break; | 2308 | break; |
2315 | case 1152000 : | 2309 | case 1152000 : |
2316 | case 4000000 : | 2310 | case 4000000 : |
2317 | fast_mode = IRCC_LCR_A_FAST; | 2311 | fast_mode = IRCC_LCR_A_FAST; |
2318 | break; | 2312 | break; |
2319 | |||
2320 | } | 2313 | } |
2321 | register_bank(fir_base, 0); | 2314 | register_bank(fir_base, 0); |
2322 | outb((inb(fir_base+IRCC_LCR_A) & 0xbf) | fast_mode, fir_base+IRCC_LCR_A); | 2315 | outb((inb(fir_base + IRCC_LCR_A) & 0xbf) | fast_mode, fir_base + IRCC_LCR_A); |
2323 | } | 2316 | } |
2324 | 2317 | ||
2325 | /* | 2318 | /* |
2326 | * Function smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(fir_base) | 2319 | * Function smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(fir_base) |
2327 | * | 2320 | * |
2328 | * Probe transceiver | 2321 | * Probe transceiver |
2329 | * | 2322 | * |
2330 | */ | 2323 | */ |
2331 | 2324 | ||
@@ -2337,35 +2330,34 @@ static int smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(int fir_base) | |||
2337 | /* | 2330 | /* |
2338 | * Function smsc_ircc_set_transceiver_toshiba_sat1800(fir_base, speed) | 2331 | * Function smsc_ircc_set_transceiver_toshiba_sat1800(fir_base, speed) |
2339 | * | 2332 | * |
2340 | * Set transceiver | 2333 | * Set transceiver |
2341 | * | 2334 | * |
2342 | */ | 2335 | */ |
2343 | 2336 | ||
2344 | static void smsc_ircc_set_transceiver_toshiba_sat1800(int fir_base, u32 speed) | 2337 | static void smsc_ircc_set_transceiver_toshiba_sat1800(int fir_base, u32 speed) |
2345 | { | 2338 | { |
2346 | u8 fast_mode; | 2339 | u8 fast_mode; |
2347 | 2340 | ||
2348 | switch(speed) | 2341 | switch (speed) { |
2349 | { | 2342 | default: |
2350 | default: | 2343 | case 576000 : |
2351 | case 576000 : | 2344 | fast_mode = 0; |
2352 | fast_mode = 0; | ||
2353 | break; | 2345 | break; |
2354 | case 1152000 : | 2346 | case 1152000 : |
2355 | case 4000000 : | 2347 | case 4000000 : |
2356 | fast_mode = /*IRCC_LCR_A_FAST |*/ IRCC_LCR_A_GP_DATA; | 2348 | fast_mode = /*IRCC_LCR_A_FAST |*/ IRCC_LCR_A_GP_DATA; |
2357 | break; | 2349 | break; |
2358 | 2350 | ||
2359 | } | 2351 | } |
2360 | /* This causes an interrupt */ | 2352 | /* This causes an interrupt */ |
2361 | register_bank(fir_base, 0); | 2353 | register_bank(fir_base, 0); |
2362 | outb((inb(fir_base+IRCC_LCR_A) & 0xbf) | fast_mode, fir_base+IRCC_LCR_A); | 2354 | outb((inb(fir_base + IRCC_LCR_A) & 0xbf) | fast_mode, fir_base + IRCC_LCR_A); |
2363 | } | 2355 | } |
2364 | 2356 | ||
2365 | /* | 2357 | /* |
2366 | * Function smsc_ircc_probe_transceiver_toshiba_sat1800(fir_base) | 2358 | * Function smsc_ircc_probe_transceiver_toshiba_sat1800(fir_base) |
2367 | * | 2359 | * |
2368 | * Probe transceiver | 2360 | * Probe transceiver |
2369 | * | 2361 | * |
2370 | */ | 2362 | */ |
2371 | 2363 | ||
@@ -2377,20 +2369,3 @@ static int smsc_ircc_probe_transceiver_toshiba_sat1800(int fir_base) | |||
2377 | 2369 | ||
2378 | module_init(smsc_ircc_init); | 2370 | module_init(smsc_ircc_init); |
2379 | module_exit(smsc_ircc_cleanup); | 2371 | module_exit(smsc_ircc_cleanup); |
2380 | |||
2381 | MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>"); | ||
2382 | MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver"); | ||
2383 | MODULE_LICENSE("GPL"); | ||
2384 | |||
2385 | module_param(ircc_dma, int, 0); | ||
2386 | MODULE_PARM_DESC(ircc_dma, "DMA channel"); | ||
2387 | module_param(ircc_irq, int, 0); | ||
2388 | MODULE_PARM_DESC(ircc_irq, "IRQ line"); | ||
2389 | module_param(ircc_fir, int, 0); | ||
2390 | MODULE_PARM_DESC(ircc_fir, "FIR Base Address"); | ||
2391 | module_param(ircc_sir, int, 0); | ||
2392 | MODULE_PARM_DESC(ircc_sir, "SIR Base Address"); | ||
2393 | module_param(ircc_cfg, int, 0); | ||
2394 | MODULE_PARM_DESC(ircc_cfg, "Configuration register base address"); | ||
2395 | module_param(ircc_transceiver, int, 0); | ||
2396 | MODULE_PARM_DESC(ircc_transceiver, "Transceiver type"); | ||
diff --git a/drivers/net/irda/smsc-ircc2.h b/drivers/net/irda/smsc-ircc2.h index 458611cc0d40..0c36286d87f7 100644 --- a/drivers/net/irda/smsc-ircc2.h +++ b/drivers/net/irda/smsc-ircc2.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /********************************************************************* | 1 | /********************************************************************* |
2 | * $Id: smsc-ircc2.h,v 1.12.2.1 2002/10/27 10:52:37 dip Exp $ | 2 | * $Id: smsc-ircc2.h,v 1.12.2.1 2002/10/27 10:52:37 dip Exp $ |
3 | * | 3 | * |
4 | * Description: Definitions for the SMC IrCC chipset | 4 | * Description: Definitions for the SMC IrCC chipset |
5 | * Status: Experimental. | 5 | * Status: Experimental. |
@@ -9,25 +9,25 @@ | |||
9 | * All Rights Reserved. | 9 | * All Rights Reserved. |
10 | * | 10 | * |
11 | * Based on smc-ircc.h: | 11 | * Based on smc-ircc.h: |
12 | * | 12 | * |
13 | * Copyright (c) 1999-2000, Dag Brattli <dagb@cs.uit.no> | 13 | * Copyright (c) 1999-2000, Dag Brattli <dagb@cs.uit.no> |
14 | * Copyright (c) 1998-1999, Thomas Davis (tadavis@jps.net> | 14 | * Copyright (c) 1998-1999, Thomas Davis (tadavis@jps.net> |
15 | * All Rights Reserved | 15 | * All Rights Reserved |
16 | * | 16 | * |
17 | * | 17 | * |
18 | * This program is free software; you can redistribute it and/or | 18 | * This program is free software; you can redistribute it and/or |
19 | * modify it under the terms of the GNU General Public License as | 19 | * modify it under the terms of the GNU General Public License as |
20 | * published by the Free Software Foundation; either version 2 of | 20 | * published by the Free Software Foundation; either version 2 of |
21 | * the License, or (at your option) any later version. | 21 | * the License, or (at your option) any later version. |
22 | * | 22 | * |
23 | * This program is distributed in the hope that it will be useful, | 23 | * This program is distributed in the hope that it will be useful, |
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
26 | * GNU General Public License for more details. | 26 | * GNU General Public License for more details. |
27 | * | 27 | * |
28 | * You should have received a copy of the GNU General Public License | 28 | * You should have received a copy of the GNU General Public License |
29 | * along with this program; if not, write to the Free Software | 29 | * along with this program; if not, write to the Free Software |
30 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 30 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
31 | * MA 02111-1307 USA | 31 | * MA 02111-1307 USA |
32 | * | 32 | * |
33 | ********************************************************************/ | 33 | ********************************************************************/ |
@@ -112,10 +112,10 @@ | |||
112 | 112 | ||
113 | #define IRCC_CFGA_COM 0x00 | 113 | #define IRCC_CFGA_COM 0x00 |
114 | #define IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK 0x87 | 114 | #define IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK 0x87 |
115 | #define IRCC_CFGA_IRDA_SIR_A 0x08 | 115 | #define IRCC_CFGA_IRDA_SIR_A 0x08 |
116 | #define IRCC_CFGA_ASK_SIR 0x10 | 116 | #define IRCC_CFGA_ASK_SIR 0x10 |
117 | #define IRCC_CFGA_IRDA_SIR_B 0x18 | 117 | #define IRCC_CFGA_IRDA_SIR_B 0x18 |
118 | #define IRCC_CFGA_IRDA_HDLC 0x20 | 118 | #define IRCC_CFGA_IRDA_HDLC 0x20 |
119 | #define IRCC_CFGA_IRDA_4PPM 0x28 | 119 | #define IRCC_CFGA_IRDA_4PPM 0x28 |
120 | #define IRCC_CFGA_CONSUMER 0x30 | 120 | #define IRCC_CFGA_CONSUMER 0x30 |
121 | #define IRCC_CFGA_RAW_IR 0x38 | 121 | #define IRCC_CFGA_RAW_IR 0x38 |
@@ -130,7 +130,7 @@ | |||
130 | #define IRCC_CFGB_LPBCK_TX_CRC 0x10 | 130 | #define IRCC_CFGB_LPBCK_TX_CRC 0x10 |
131 | #define IRCC_CFGB_NOWAIT 0x08 | 131 | #define IRCC_CFGB_NOWAIT 0x08 |
132 | #define IRCC_CFGB_STRING_MOVE 0x04 | 132 | #define IRCC_CFGB_STRING_MOVE 0x04 |
133 | #define IRCC_CFGB_DMA_BURST 0x02 | 133 | #define IRCC_CFGB_DMA_BURST 0x02 |
134 | #define IRCC_CFGB_DMA_ENABLE 0x01 | 134 | #define IRCC_CFGB_DMA_ENABLE 0x01 |
135 | 135 | ||
136 | #define IRCC_CFGB_MUX_COM 0x00 | 136 | #define IRCC_CFGB_MUX_COM 0x00 |
@@ -141,11 +141,11 @@ | |||
141 | /* Register block 3 - Identification Registers! */ | 141 | /* Register block 3 - Identification Registers! */ |
142 | #define IRCC_ID_HIGH 0x00 /* 0x10 */ | 142 | #define IRCC_ID_HIGH 0x00 /* 0x10 */ |
143 | #define IRCC_ID_LOW 0x01 /* 0xB8 */ | 143 | #define IRCC_ID_LOW 0x01 /* 0xB8 */ |
144 | #define IRCC_CHIP_ID 0x02 /* 0xF1 */ | 144 | #define IRCC_CHIP_ID 0x02 /* 0xF1 */ |
145 | #define IRCC_VERSION 0x03 /* 0x01 */ | 145 | #define IRCC_VERSION 0x03 /* 0x01 */ |
146 | #define IRCC_INTERFACE 0x04 /* low 4 = DMA, high 4 = IRQ */ | 146 | #define IRCC_INTERFACE 0x04 /* low 4 = DMA, high 4 = IRQ */ |
147 | #define IRCC_INTERFACE_DMA_MASK 0x0F /* low 4 = DMA, high 4 = IRQ */ | 147 | #define IRCC_INTERFACE_DMA_MASK 0x0F /* low 4 = DMA, high 4 = IRQ */ |
148 | #define IRCC_INTERFACE_IRQ_MASK 0xF0 /* low 4 = DMA, high 4 = IRQ */ | 148 | #define IRCC_INTERFACE_IRQ_MASK 0xF0 /* low 4 = DMA, high 4 = IRQ */ |
149 | 149 | ||
150 | /* Register block 4 - IrDA */ | 150 | /* Register block 4 - IrDA */ |
151 | #define IRCC_CONTROL 0x00 | 151 | #define IRCC_CONTROL 0x00 |
@@ -163,10 +163,10 @@ | |||
163 | 163 | ||
164 | /* Register block 5 - IrDA */ | 164 | /* Register block 5 - IrDA */ |
165 | #define IRCC_ATC 0x00 | 165 | #define IRCC_ATC 0x00 |
166 | #define IRCC_ATC_nPROGREADY 0x80 | 166 | #define IRCC_ATC_nPROGREADY 0x80 |
167 | #define IRCC_ATC_SPEED 0x40 | 167 | #define IRCC_ATC_SPEED 0x40 |
168 | #define IRCC_ATC_ENABLE 0x20 | 168 | #define IRCC_ATC_ENABLE 0x20 |
169 | #define IRCC_ATC_MASK 0xE0 | 169 | #define IRCC_ATC_MASK 0xE0 |
170 | 170 | ||
171 | 171 | ||
172 | #define IRCC_IRHALFDUPLEX_TIMEOUT 0x01 | 172 | #define IRCC_IRHALFDUPLEX_TIMEOUT 0x01 |
@@ -178,8 +178,8 @@ | |||
178 | */ | 178 | */ |
179 | 179 | ||
180 | #define SMSC_IRCC2_MAX_SIR_SPEED 115200 | 180 | #define SMSC_IRCC2_MAX_SIR_SPEED 115200 |
181 | #define SMSC_IRCC2_FIR_CHIP_IO_EXTENT 8 | 181 | #define SMSC_IRCC2_FIR_CHIP_IO_EXTENT 8 |
182 | #define SMSC_IRCC2_SIR_CHIP_IO_EXTENT 8 | 182 | #define SMSC_IRCC2_SIR_CHIP_IO_EXTENT 8 |
183 | #define SMSC_IRCC2_FIFO_SIZE 16 | 183 | #define SMSC_IRCC2_FIFO_SIZE 16 |
184 | #define SMSC_IRCC2_FIFO_THRESHOLD 64 | 184 | #define SMSC_IRCC2_FIFO_THRESHOLD 64 |
185 | /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ | 185 | /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ |
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 4598c6a9212d..97f723179f62 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
@@ -2739,6 +2739,7 @@ enum parport_pc_pci_cards { | |||
2739 | syba_2p_epp, | 2739 | syba_2p_epp, |
2740 | syba_1p_ecp, | 2740 | syba_1p_ecp, |
2741 | titan_010l, | 2741 | titan_010l, |
2742 | titan_1284p1, | ||
2742 | titan_1284p2, | 2743 | titan_1284p2, |
2743 | avlab_1p, | 2744 | avlab_1p, |
2744 | avlab_2p, | 2745 | avlab_2p, |
@@ -2811,6 +2812,7 @@ static struct parport_pc_pci { | |||
2811 | /* syba_2p_epp AP138B */ { 2, { { 0, 0x078 }, { 0, 0x178 }, } }, | 2812 | /* syba_2p_epp AP138B */ { 2, { { 0, 0x078 }, { 0, 0x178 }, } }, |
2812 | /* syba_1p_ecp W83787 */ { 1, { { 0, 0x078 }, } }, | 2813 | /* syba_1p_ecp W83787 */ { 1, { { 0, 0x078 }, } }, |
2813 | /* titan_010l */ { 1, { { 3, -1 }, } }, | 2814 | /* titan_010l */ { 1, { { 3, -1 }, } }, |
2815 | /* titan_1284p1 */ { 1, { { 0, 1 }, } }, | ||
2814 | /* titan_1284p2 */ { 2, { { 0, 1 }, { 2, 3 }, } }, | 2816 | /* titan_1284p2 */ { 2, { { 0, 1 }, { 2, 3 }, } }, |
2815 | /* avlab_1p */ { 1, { { 0, 1}, } }, | 2817 | /* avlab_1p */ { 1, { { 0, 1}, } }, |
2816 | /* avlab_2p */ { 2, { { 0, 1}, { 2, 3 },} }, | 2818 | /* avlab_2p */ { 2, { { 0, 1}, { 2, 3 },} }, |
@@ -2884,6 +2886,7 @@ static struct pci_device_id parport_pc_pci_tbl[] = { | |||
2884 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_1p_ecp }, | 2886 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_1p_ecp }, |
2885 | { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_010L, | 2887 | { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_010L, |
2886 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_010l }, | 2888 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_010l }, |
2889 | { 0x9710, 0x9805, 0x1000, 0x0010, 0, 0, titan_1284p1 }, | ||
2887 | { 0x9710, 0x9815, 0x1000, 0x0020, 0, 0, titan_1284p2 }, | 2890 | { 0x9710, 0x9815, 0x1000, 0x0020, 0, 0, titan_1284p2 }, |
2888 | /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/ | 2891 | /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/ |
2889 | { 0x14db, 0x2120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1p}, /* AFAVLAB_TK9902 */ | 2892 | { 0x14db, 0x2120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1p}, /* AFAVLAB_TK9902 */ |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 2b85aa39f954..532f73bb2224 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -91,6 +91,7 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) | |||
91 | { | 91 | { |
92 | struct msi_desc *entry; | 92 | struct msi_desc *entry; |
93 | struct msg_address address; | 93 | struct msg_address address; |
94 | unsigned int irq = vector; | ||
94 | 95 | ||
95 | entry = (struct msi_desc *)msi_desc[vector]; | 96 | entry = (struct msi_desc *)msi_desc[vector]; |
96 | if (!entry || !entry->dev) | 97 | if (!entry || !entry->dev) |
@@ -112,6 +113,7 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) | |||
112 | entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask); | 113 | entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask); |
113 | pci_write_config_dword(entry->dev, msi_lower_address_reg(pos), | 114 | pci_write_config_dword(entry->dev, msi_lower_address_reg(pos), |
114 | address.lo_address.value); | 115 | address.lo_address.value); |
116 | set_native_irq_info(irq, cpu_mask); | ||
115 | break; | 117 | break; |
116 | } | 118 | } |
117 | case PCI_CAP_ID_MSIX: | 119 | case PCI_CAP_ID_MSIX: |
@@ -125,22 +127,13 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) | |||
125 | MSI_TARGET_CPU_SHIFT); | 127 | MSI_TARGET_CPU_SHIFT); |
126 | entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask); | 128 | entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask); |
127 | writel(address.lo_address.value, entry->mask_base + offset); | 129 | writel(address.lo_address.value, entry->mask_base + offset); |
130 | set_native_irq_info(irq, cpu_mask); | ||
128 | break; | 131 | break; |
129 | } | 132 | } |
130 | default: | 133 | default: |
131 | break; | 134 | break; |
132 | } | 135 | } |
133 | } | 136 | } |
134 | |||
135 | #ifdef CONFIG_IRQBALANCE | ||
136 | static inline void move_msi(int vector) | ||
137 | { | ||
138 | if (!cpus_empty(pending_irq_balance_cpumask[vector])) { | ||
139 | set_msi_affinity(vector, pending_irq_balance_cpumask[vector]); | ||
140 | cpus_clear(pending_irq_balance_cpumask[vector]); | ||
141 | } | ||
142 | } | ||
143 | #endif /* CONFIG_IRQBALANCE */ | ||
144 | #endif /* CONFIG_SMP */ | 137 | #endif /* CONFIG_SMP */ |
145 | 138 | ||
146 | static void mask_MSI_irq(unsigned int vector) | 139 | static void mask_MSI_irq(unsigned int vector) |
@@ -191,13 +184,13 @@ static void shutdown_msi_irq(unsigned int vector) | |||
191 | 184 | ||
192 | static void end_msi_irq_wo_maskbit(unsigned int vector) | 185 | static void end_msi_irq_wo_maskbit(unsigned int vector) |
193 | { | 186 | { |
194 | move_msi(vector); | 187 | move_native_irq(vector); |
195 | ack_APIC_irq(); | 188 | ack_APIC_irq(); |
196 | } | 189 | } |
197 | 190 | ||
198 | static void end_msi_irq_w_maskbit(unsigned int vector) | 191 | static void end_msi_irq_w_maskbit(unsigned int vector) |
199 | { | 192 | { |
200 | move_msi(vector); | 193 | move_native_irq(vector); |
201 | unmask_MSI_irq(vector); | 194 | unmask_MSI_irq(vector); |
202 | ack_APIC_irq(); | 195 | ack_APIC_irq(); |
203 | } | 196 | } |
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index 390f1851c0f1..402136a5c9e4 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h | |||
@@ -19,7 +19,6 @@ | |||
19 | #define NR_HP_RESERVED_VECTORS 20 | 19 | #define NR_HP_RESERVED_VECTORS 20 |
20 | 20 | ||
21 | extern int vector_irq[NR_VECTORS]; | 21 | extern int vector_irq[NR_VECTORS]; |
22 | extern cpumask_t pending_irq_balance_cpumask[NR_IRQS]; | ||
23 | extern void (*interrupt[NR_IRQS])(void); | 22 | extern void (*interrupt[NR_IRQS])(void); |
24 | extern int pci_vector_resources(int last, int nr_released); | 23 | extern int pci_vector_resources(int last, int nr_released); |
25 | 24 | ||
@@ -29,10 +28,6 @@ extern int pci_vector_resources(int last, int nr_released); | |||
29 | #define set_msi_irq_affinity NULL | 28 | #define set_msi_irq_affinity NULL |
30 | #endif | 29 | #endif |
31 | 30 | ||
32 | #ifndef CONFIG_IRQBALANCE | ||
33 | static inline void move_msi(int vector) {} | ||
34 | #endif | ||
35 | |||
36 | /* | 31 | /* |
37 | * MSI-X Address Register | 32 | * MSI-X Address Register |
38 | */ | 33 | */ |
diff --git a/drivers/pcmcia/topic.h b/drivers/pcmcia/topic.h index be420bb29113..edccfa5bb400 100644 --- a/drivers/pcmcia/topic.h +++ b/drivers/pcmcia/topic.h | |||
@@ -101,6 +101,8 @@ | |||
101 | #define TOPIC97_AVS_AUDIO_CONTROL 0x02 | 101 | #define TOPIC97_AVS_AUDIO_CONTROL 0x02 |
102 | #define TOPIC97_AVS_VIDEO_CONTROL 0x01 | 102 | #define TOPIC97_AVS_VIDEO_CONTROL 0x01 |
103 | 103 | ||
104 | #define TOPIC_EXCA_IF_CONTROL 0x3e /* 8 bit */ | ||
105 | #define TOPIC_EXCA_IFC_33V_ENA 0x01 | ||
104 | 106 | ||
105 | static void topic97_zoom_video(struct pcmcia_socket *sock, int onoff) | 107 | static void topic97_zoom_video(struct pcmcia_socket *sock, int onoff) |
106 | { | 108 | { |
@@ -137,4 +139,19 @@ static int topic97_override(struct yenta_socket *socket) | |||
137 | return 0; | 139 | return 0; |
138 | } | 140 | } |
139 | 141 | ||
142 | |||
143 | static int topic95_override(struct yenta_socket *socket) | ||
144 | { | ||
145 | u8 fctrl; | ||
146 | |||
147 | /* enable 3.3V support for 16bit cards */ | ||
148 | fctrl = exca_readb(socket, TOPIC_EXCA_IF_CONTROL); | ||
149 | exca_writeb(socket, TOPIC_EXCA_IF_CONTROL, fctrl | TOPIC_EXCA_IFC_33V_ENA); | ||
150 | |||
151 | /* tell yenta to use exca registers to power 16bit cards */ | ||
152 | socket->flags |= YENTA_16BIT_POWER_EXCA | YENTA_16BIT_POWER_DF; | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
140 | #endif /* _LINUX_TOPIC_H */ | 157 | #endif /* _LINUX_TOPIC_H */ |
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 62fd705203fb..0347a29f297b 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
@@ -184,22 +184,52 @@ static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value) | |||
184 | return 0; | 184 | return 0; |
185 | } | 185 | } |
186 | 186 | ||
187 | static int yenta_Vcc_power(u32 control) | 187 | static void yenta_get_power(struct yenta_socket *socket, socket_state_t *state) |
188 | { | 188 | { |
189 | switch (control & CB_SC_VCC_MASK) { | 189 | if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) && |
190 | case CB_SC_VCC_5V: return 50; | 190 | (socket->flags & YENTA_16BIT_POWER_EXCA)) { |
191 | case CB_SC_VCC_3V: return 33; | 191 | u8 reg, vcc, vpp; |
192 | default: return 0; | 192 | |
193 | } | 193 | reg = exca_readb(socket, I365_POWER); |
194 | } | 194 | vcc = reg & I365_VCC_MASK; |
195 | vpp = reg & I365_VPP1_MASK; | ||
196 | state->Vcc = state->Vpp = 0; | ||
197 | |||
198 | if (socket->flags & YENTA_16BIT_POWER_DF) { | ||
199 | if (vcc == I365_VCC_3V) | ||
200 | state->Vcc = 33; | ||
201 | if (vcc == I365_VCC_5V) | ||
202 | state->Vcc = 50; | ||
203 | if (vpp == I365_VPP1_5V) | ||
204 | state->Vpp = state->Vcc; | ||
205 | if (vpp == I365_VPP1_12V) | ||
206 | state->Vpp = 120; | ||
207 | } else { | ||
208 | if (reg & I365_VCC_5V) { | ||
209 | state->Vcc = 50; | ||
210 | if (vpp == I365_VPP1_5V) | ||
211 | state->Vpp = 50; | ||
212 | if (vpp == I365_VPP1_12V) | ||
213 | state->Vpp = 120; | ||
214 | } | ||
215 | } | ||
216 | } else { | ||
217 | u32 control; | ||
195 | 218 | ||
196 | static int yenta_Vpp_power(u32 control) | 219 | control = cb_readl(socket, CB_SOCKET_CONTROL); |
197 | { | 220 | |
198 | switch (control & CB_SC_VPP_MASK) { | 221 | switch (control & CB_SC_VCC_MASK) { |
199 | case CB_SC_VPP_12V: return 120; | 222 | case CB_SC_VCC_5V: state->Vcc = 50; break; |
200 | case CB_SC_VPP_5V: return 50; | 223 | case CB_SC_VCC_3V: state->Vcc = 33; break; |
201 | case CB_SC_VPP_3V: return 33; | 224 | default: state->Vcc = 0; |
202 | default: return 0; | 225 | } |
226 | |||
227 | switch (control & CB_SC_VPP_MASK) { | ||
228 | case CB_SC_VPP_12V: state->Vpp = 120; break; | ||
229 | case CB_SC_VPP_5V: state->Vpp = 50; break; | ||
230 | case CB_SC_VPP_3V: state->Vpp = 33; break; | ||
231 | default: state->Vpp = 0; | ||
232 | } | ||
203 | } | 233 | } |
204 | } | 234 | } |
205 | 235 | ||
@@ -211,8 +241,7 @@ static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state) | |||
211 | 241 | ||
212 | control = cb_readl(socket, CB_SOCKET_CONTROL); | 242 | control = cb_readl(socket, CB_SOCKET_CONTROL); |
213 | 243 | ||
214 | state->Vcc = yenta_Vcc_power(control); | 244 | yenta_get_power(socket, state); |
215 | state->Vpp = yenta_Vpp_power(control); | ||
216 | state->io_irq = socket->io_irq; | 245 | state->io_irq = socket->io_irq; |
217 | 246 | ||
218 | if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) { | 247 | if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) { |
@@ -246,19 +275,54 @@ static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state) | |||
246 | 275 | ||
247 | static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state) | 276 | static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state) |
248 | { | 277 | { |
249 | u32 reg = 0; /* CB_SC_STPCLK? */ | 278 | /* some birdges require to use the ExCA registers to power 16bit cards */ |
250 | switch (state->Vcc) { | 279 | if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) && |
251 | case 33: reg = CB_SC_VCC_3V; break; | 280 | (socket->flags & YENTA_16BIT_POWER_EXCA)) { |
252 | case 50: reg = CB_SC_VCC_5V; break; | 281 | u8 reg, old; |
253 | default: reg = 0; break; | 282 | reg = old = exca_readb(socket, I365_POWER); |
254 | } | 283 | reg &= ~(I365_VCC_MASK | I365_VPP1_MASK | I365_VPP2_MASK); |
255 | switch (state->Vpp) { | 284 | |
256 | case 33: reg |= CB_SC_VPP_3V; break; | 285 | /* i82365SL-DF style */ |
257 | case 50: reg |= CB_SC_VPP_5V; break; | 286 | if (socket->flags & YENTA_16BIT_POWER_DF) { |
258 | case 120: reg |= CB_SC_VPP_12V; break; | 287 | switch (state->Vcc) { |
288 | case 33: reg |= I365_VCC_3V; break; | ||
289 | case 50: reg |= I365_VCC_5V; break; | ||
290 | default: reg = 0; break; | ||
291 | } | ||
292 | switch (state->Vpp) { | ||
293 | case 33: | ||
294 | case 50: reg |= I365_VPP1_5V; break; | ||
295 | case 120: reg |= I365_VPP1_12V; break; | ||
296 | } | ||
297 | } else { | ||
298 | /* i82365SL-B style */ | ||
299 | switch (state->Vcc) { | ||
300 | case 50: reg |= I365_VCC_5V; break; | ||
301 | default: reg = 0; break; | ||
302 | } | ||
303 | switch (state->Vpp) { | ||
304 | case 50: reg |= I365_VPP1_5V | I365_VPP2_5V; break; | ||
305 | case 120: reg |= I365_VPP1_12V | I365_VPP2_12V; break; | ||
306 | } | ||
307 | } | ||
308 | |||
309 | if (reg != old) | ||
310 | exca_writeb(socket, I365_POWER, reg); | ||
311 | } else { | ||
312 | u32 reg = 0; /* CB_SC_STPCLK? */ | ||
313 | switch (state->Vcc) { | ||
314 | case 33: reg = CB_SC_VCC_3V; break; | ||
315 | case 50: reg = CB_SC_VCC_5V; break; | ||
316 | default: reg = 0; break; | ||
317 | } | ||
318 | switch (state->Vpp) { | ||
319 | case 33: reg |= CB_SC_VPP_3V; break; | ||
320 | case 50: reg |= CB_SC_VPP_5V; break; | ||
321 | case 120: reg |= CB_SC_VPP_12V; break; | ||
322 | } | ||
323 | if (reg != cb_readl(socket, CB_SOCKET_CONTROL)) | ||
324 | cb_writel(socket, CB_SOCKET_CONTROL, reg); | ||
259 | } | 325 | } |
260 | if (reg != cb_readl(socket, CB_SOCKET_CONTROL)) | ||
261 | cb_writel(socket, CB_SOCKET_CONTROL, reg); | ||
262 | } | 326 | } |
263 | 327 | ||
264 | static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) | 328 | static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) |
@@ -751,6 +815,7 @@ enum { | |||
751 | CARDBUS_TYPE_TI12XX, | 815 | CARDBUS_TYPE_TI12XX, |
752 | CARDBUS_TYPE_TI1250, | 816 | CARDBUS_TYPE_TI1250, |
753 | CARDBUS_TYPE_RICOH, | 817 | CARDBUS_TYPE_RICOH, |
818 | CARDBUS_TYPE_TOPIC95, | ||
754 | CARDBUS_TYPE_TOPIC97, | 819 | CARDBUS_TYPE_TOPIC97, |
755 | CARDBUS_TYPE_O2MICRO, | 820 | CARDBUS_TYPE_O2MICRO, |
756 | }; | 821 | }; |
@@ -789,6 +854,9 @@ static struct cardbus_type cardbus_type[] = { | |||
789 | .save_state = ricoh_save_state, | 854 | .save_state = ricoh_save_state, |
790 | .restore_state = ricoh_restore_state, | 855 | .restore_state = ricoh_restore_state, |
791 | }, | 856 | }, |
857 | [CARDBUS_TYPE_TOPIC95] = { | ||
858 | .override = topic95_override, | ||
859 | }, | ||
792 | [CARDBUS_TYPE_TOPIC97] = { | 860 | [CARDBUS_TYPE_TOPIC97] = { |
793 | .override = topic97_override, | 861 | .override = topic97_override, |
794 | }, | 862 | }, |
@@ -1196,6 +1264,7 @@ static struct pci_device_id yenta_table [] = { | |||
1196 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH), | 1264 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH), |
1197 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH), | 1265 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH), |
1198 | 1266 | ||
1267 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95, TOPIC95), | ||
1199 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97), | 1268 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97), |
1200 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97), | 1269 | CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97), |
1201 | 1270 | ||
diff --git a/drivers/pcmcia/yenta_socket.h b/drivers/pcmcia/yenta_socket.h index 4e637eef2076..4e75e9e258cd 100644 --- a/drivers/pcmcia/yenta_socket.h +++ b/drivers/pcmcia/yenta_socket.h | |||
@@ -95,6 +95,12 @@ | |||
95 | */ | 95 | */ |
96 | #define CB_MEM_PAGE(map) (0x40 + (map)) | 96 | #define CB_MEM_PAGE(map) (0x40 + (map)) |
97 | 97 | ||
98 | |||
99 | /* control how 16bit cards are powered */ | ||
100 | #define YENTA_16BIT_POWER_EXCA 0x00000001 | ||
101 | #define YENTA_16BIT_POWER_DF 0x00000002 | ||
102 | |||
103 | |||
98 | struct yenta_socket; | 104 | struct yenta_socket; |
99 | 105 | ||
100 | struct cardbus_type { | 106 | struct cardbus_type { |
@@ -113,6 +119,8 @@ struct yenta_socket { | |||
113 | struct pcmcia_socket socket; | 119 | struct pcmcia_socket socket; |
114 | struct cardbus_type *type; | 120 | struct cardbus_type *type; |
115 | 121 | ||
122 | u32 flags; | ||
123 | |||
116 | /* for PCI interrupt probing */ | 124 | /* for PCI interrupt probing */ |
117 | unsigned int probe_status; | 125 | unsigned int probe_status; |
118 | 126 | ||
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index 6e5229e92fbc..e95ed67d4f05 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c | |||
@@ -8,13 +8,6 @@ | |||
8 | #include <linux/config.h> | 8 | #include <linux/config.h> |
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
11 | |||
12 | #ifdef CONFIG_PNP_DEBUG | ||
13 | #define DEBUG | ||
14 | #else | ||
15 | #undef DEBUG | ||
16 | #endif | ||
17 | |||
18 | #include <linux/pnp.h> | 11 | #include <linux/pnp.h> |
19 | #include "base.h" | 12 | #include "base.h" |
20 | 13 | ||
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index 1d037c2a82ac..33da25f3213f 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c | |||
@@ -11,13 +11,6 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/ctype.h> | 12 | #include <linux/ctype.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | |||
15 | #ifdef CONFIG_PNP_DEBUG | ||
16 | #define DEBUG | ||
17 | #else | ||
18 | #undef DEBUG | ||
19 | #endif | ||
20 | |||
21 | #include <linux/pnp.h> | 14 | #include <linux/pnp.h> |
22 | #include "base.h" | 15 | #include "base.h" |
23 | 16 | ||
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 82c5edd5b9ee..beedd86800f4 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c | |||
@@ -142,17 +142,6 @@ static void isapnp_write_word(unsigned char idx, unsigned short val) | |||
142 | isapnp_write_byte(idx+1, val); | 142 | isapnp_write_byte(idx+1, val); |
143 | } | 143 | } |
144 | 144 | ||
145 | static void *isapnp_alloc(long size) | ||
146 | { | ||
147 | void *result; | ||
148 | |||
149 | result = kmalloc(size, GFP_KERNEL); | ||
150 | if (!result) | ||
151 | return NULL; | ||
152 | memset(result, 0, size); | ||
153 | return result; | ||
154 | } | ||
155 | |||
156 | static void isapnp_key(void) | 145 | static void isapnp_key(void) |
157 | { | 146 | { |
158 | unsigned char code = 0x6a, msb; | 147 | unsigned char code = 0x6a, msb; |
@@ -406,7 +395,7 @@ static void isapnp_parse_id(struct pnp_dev * dev, unsigned short vendor, unsigne | |||
406 | struct pnp_id * id; | 395 | struct pnp_id * id; |
407 | if (!dev) | 396 | if (!dev) |
408 | return; | 397 | return; |
409 | id = isapnp_alloc(sizeof(struct pnp_id)); | 398 | id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL); |
410 | if (!id) | 399 | if (!id) |
411 | return; | 400 | return; |
412 | sprintf(id->id, "%c%c%c%x%x%x%x", | 401 | sprintf(id->id, "%c%c%c%x%x%x%x", |
@@ -430,7 +419,7 @@ static struct pnp_dev * __init isapnp_parse_device(struct pnp_card *card, int si | |||
430 | struct pnp_dev *dev; | 419 | struct pnp_dev *dev; |
431 | 420 | ||
432 | isapnp_peek(tmp, size); | 421 | isapnp_peek(tmp, size); |
433 | dev = isapnp_alloc(sizeof(struct pnp_dev)); | 422 | dev = kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL); |
434 | if (!dev) | 423 | if (!dev) |
435 | return NULL; | 424 | return NULL; |
436 | dev->number = number; | 425 | dev->number = number; |
@@ -461,7 +450,7 @@ static void __init isapnp_parse_irq_resource(struct pnp_option *option, | |||
461 | unsigned long bits; | 450 | unsigned long bits; |
462 | 451 | ||
463 | isapnp_peek(tmp, size); | 452 | isapnp_peek(tmp, size); |
464 | irq = isapnp_alloc(sizeof(struct pnp_irq)); | 453 | irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL); |
465 | if (!irq) | 454 | if (!irq) |
466 | return; | 455 | return; |
467 | bits = (tmp[1] << 8) | tmp[0]; | 456 | bits = (tmp[1] << 8) | tmp[0]; |
@@ -485,7 +474,7 @@ static void __init isapnp_parse_dma_resource(struct pnp_option *option, | |||
485 | struct pnp_dma *dma; | 474 | struct pnp_dma *dma; |
486 | 475 | ||
487 | isapnp_peek(tmp, size); | 476 | isapnp_peek(tmp, size); |
488 | dma = isapnp_alloc(sizeof(struct pnp_dma)); | 477 | dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL); |
489 | if (!dma) | 478 | if (!dma) |
490 | return; | 479 | return; |
491 | dma->map = tmp[0]; | 480 | dma->map = tmp[0]; |
@@ -505,7 +494,7 @@ static void __init isapnp_parse_port_resource(struct pnp_option *option, | |||
505 | struct pnp_port *port; | 494 | struct pnp_port *port; |
506 | 495 | ||
507 | isapnp_peek(tmp, size); | 496 | isapnp_peek(tmp, size); |
508 | port = isapnp_alloc(sizeof(struct pnp_port)); | 497 | port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); |
509 | if (!port) | 498 | if (!port) |
510 | return; | 499 | return; |
511 | port->min = (tmp[2] << 8) | tmp[1]; | 500 | port->min = (tmp[2] << 8) | tmp[1]; |
@@ -528,7 +517,7 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option, | |||
528 | struct pnp_port *port; | 517 | struct pnp_port *port; |
529 | 518 | ||
530 | isapnp_peek(tmp, size); | 519 | isapnp_peek(tmp, size); |
531 | port = isapnp_alloc(sizeof(struct pnp_port)); | 520 | port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); |
532 | if (!port) | 521 | if (!port) |
533 | return; | 522 | return; |
534 | port->min = port->max = (tmp[1] << 8) | tmp[0]; | 523 | port->min = port->max = (tmp[1] << 8) | tmp[0]; |
@@ -550,7 +539,7 @@ static void __init isapnp_parse_mem_resource(struct pnp_option *option, | |||
550 | struct pnp_mem *mem; | 539 | struct pnp_mem *mem; |
551 | 540 | ||
552 | isapnp_peek(tmp, size); | 541 | isapnp_peek(tmp, size); |
553 | mem = isapnp_alloc(sizeof(struct pnp_mem)); | 542 | mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); |
554 | if (!mem) | 543 | if (!mem) |
555 | return; | 544 | return; |
556 | mem->min = ((tmp[2] << 8) | tmp[1]) << 8; | 545 | mem->min = ((tmp[2] << 8) | tmp[1]) << 8; |
@@ -573,7 +562,7 @@ static void __init isapnp_parse_mem32_resource(struct pnp_option *option, | |||
573 | struct pnp_mem *mem; | 562 | struct pnp_mem *mem; |
574 | 563 | ||
575 | isapnp_peek(tmp, size); | 564 | isapnp_peek(tmp, size); |
576 | mem = isapnp_alloc(sizeof(struct pnp_mem)); | 565 | mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); |
577 | if (!mem) | 566 | if (!mem) |
578 | return; | 567 | return; |
579 | mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; | 568 | mem->min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; |
@@ -595,7 +584,7 @@ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option, | |||
595 | struct pnp_mem *mem; | 584 | struct pnp_mem *mem; |
596 | 585 | ||
597 | isapnp_peek(tmp, size); | 586 | isapnp_peek(tmp, size); |
598 | mem = isapnp_alloc(sizeof(struct pnp_mem)); | 587 | mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); |
599 | if (!mem) | 588 | if (!mem) |
600 | return; | 589 | return; |
601 | mem->min = mem->max = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; | 590 | mem->min = mem->max = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; |
@@ -838,7 +827,7 @@ static unsigned char __init isapnp_checksum(unsigned char *data) | |||
838 | 827 | ||
839 | static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor, unsigned short device) | 828 | static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor, unsigned short device) |
840 | { | 829 | { |
841 | struct pnp_id * id = isapnp_alloc(sizeof(struct pnp_id)); | 830 | struct pnp_id * id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL); |
842 | if (!id) | 831 | if (!id) |
843 | return; | 832 | return; |
844 | sprintf(id->id, "%c%c%c%x%x%x%x", | 833 | sprintf(id->id, "%c%c%c%x%x%x%x", |
@@ -874,7 +863,7 @@ static int __init isapnp_build_device_list(void) | |||
874 | header[4], header[5], header[6], header[7], header[8]); | 863 | header[4], header[5], header[6], header[7], header[8]); |
875 | printk(KERN_DEBUG "checksum = 0x%x\n", checksum); | 864 | printk(KERN_DEBUG "checksum = 0x%x\n", checksum); |
876 | #endif | 865 | #endif |
877 | if ((card = isapnp_alloc(sizeof(struct pnp_card))) == NULL) | 866 | if ((card = kcalloc(1, sizeof(struct pnp_card), GFP_KERNEL)) == NULL) |
878 | continue; | 867 | continue; |
879 | 868 | ||
880 | card->number = csn; | 869 | card->number = csn; |
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 6c510c19ad7d..94442ffd4aed 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c | |||
@@ -11,13 +11,6 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | |||
15 | #ifdef CONFIG_PNP_DEBUG | ||
16 | #define DEBUG | ||
17 | #else | ||
18 | #undef DEBUG | ||
19 | #endif | ||
20 | |||
21 | #include <linux/pnp.h> | 14 | #include <linux/pnp.h> |
22 | #include "base.h" | 15 | #include "base.h" |
23 | 16 | ||
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 8655dd2e5b83..1a8915e74160 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/config.h> | ||
22 | #include <linux/acpi.h> | 23 | #include <linux/acpi.h> |
23 | #include <linux/pnp.h> | 24 | #include <linux/pnp.h> |
24 | #include <acpi/acpi_bus.h> | 25 | #include <acpi/acpi_bus.h> |
@@ -41,14 +42,6 @@ static inline int is_exclusive_device(struct acpi_device *dev) | |||
41 | return (!acpi_match_ids(dev, excluded_id_list)); | 42 | return (!acpi_match_ids(dev, excluded_id_list)); |
42 | } | 43 | } |
43 | 44 | ||
44 | void *pnpacpi_kmalloc(size_t size, int f) | ||
45 | { | ||
46 | void *p = kmalloc(size, f); | ||
47 | if (p) | ||
48 | memset(p, 0, size); | ||
49 | return p; | ||
50 | } | ||
51 | |||
52 | /* | 45 | /* |
53 | * Compatible Device IDs | 46 | * Compatible Device IDs |
54 | */ | 47 | */ |
@@ -143,7 +136,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) | |||
143 | return 0; | 136 | return 0; |
144 | 137 | ||
145 | pnp_dbg("ACPI device : hid %s", acpi_device_hid(device)); | 138 | pnp_dbg("ACPI device : hid %s", acpi_device_hid(device)); |
146 | dev = pnpacpi_kmalloc(sizeof(struct pnp_dev), GFP_KERNEL); | 139 | dev = kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL); |
147 | if (!dev) { | 140 | if (!dev) { |
148 | pnp_err("Out of memory"); | 141 | pnp_err("Out of memory"); |
149 | return -ENOMEM; | 142 | return -ENOMEM; |
@@ -173,7 +166,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) | |||
173 | dev->number = num; | 166 | dev->number = num; |
174 | 167 | ||
175 | /* set the initial values for the PnP device */ | 168 | /* set the initial values for the PnP device */ |
176 | dev_id = pnpacpi_kmalloc(sizeof(struct pnp_id), GFP_KERNEL); | 169 | dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL); |
177 | if (!dev_id) | 170 | if (!dev_id) |
178 | goto err; | 171 | goto err; |
179 | pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id); | 172 | pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id); |
@@ -205,8 +198,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) | |||
205 | for (i = 0; i < cid_list->count; i++) { | 198 | for (i = 0; i < cid_list->count; i++) { |
206 | if (!ispnpidacpi(cid_list->id[i].value)) | 199 | if (!ispnpidacpi(cid_list->id[i].value)) |
207 | continue; | 200 | continue; |
208 | dev_id = pnpacpi_kmalloc(sizeof(struct pnp_id), | 201 | dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL); |
209 | GFP_KERNEL); | ||
210 | if (!dev_id) | 202 | if (!dev_id) |
211 | continue; | 203 | continue; |
212 | 204 | ||
diff --git a/drivers/pnp/pnpacpi/pnpacpi.h b/drivers/pnp/pnpacpi/pnpacpi.h index 76f907e09ee6..f28e2ed66fa3 100644 --- a/drivers/pnp/pnpacpi/pnpacpi.h +++ b/drivers/pnp/pnpacpi/pnpacpi.h | |||
@@ -5,7 +5,6 @@ | |||
5 | #include <linux/acpi.h> | 5 | #include <linux/acpi.h> |
6 | #include <linux/pnp.h> | 6 | #include <linux/pnp.h> |
7 | 7 | ||
8 | void *pnpacpi_kmalloc(size_t size, int f); | ||
9 | acpi_status pnpacpi_parse_allocated_resource(acpi_handle, struct pnp_resource_table*); | 8 | acpi_status pnpacpi_parse_allocated_resource(acpi_handle, struct pnp_resource_table*); |
10 | acpi_status pnpacpi_parse_resource_option_data(acpi_handle, struct pnp_dev*); | 9 | acpi_status pnpacpi_parse_resource_option_data(acpi_handle, struct pnp_dev*); |
11 | int pnpacpi_encode_resources(struct pnp_resource_table *, struct acpi_buffer *); | 10 | int pnpacpi_encode_resources(struct pnp_resource_table *, struct acpi_buffer *); |
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 75575f6c349c..675b76a42403 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
@@ -244,7 +244,7 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, struct acpi_reso | |||
244 | 244 | ||
245 | if (p->number_of_channels == 0) | 245 | if (p->number_of_channels == 0) |
246 | return; | 246 | return; |
247 | dma = pnpacpi_kmalloc(sizeof(struct pnp_dma), GFP_KERNEL); | 247 | dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL); |
248 | if (!dma) | 248 | if (!dma) |
249 | return; | 249 | return; |
250 | 250 | ||
@@ -300,7 +300,7 @@ static void pnpacpi_parse_irq_option(struct pnp_option *option, | |||
300 | 300 | ||
301 | if (p->number_of_interrupts == 0) | 301 | if (p->number_of_interrupts == 0) |
302 | return; | 302 | return; |
303 | irq = pnpacpi_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL); | 303 | irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL); |
304 | if (!irq) | 304 | if (!irq) |
305 | return; | 305 | return; |
306 | 306 | ||
@@ -321,7 +321,7 @@ static void pnpacpi_parse_ext_irq_option(struct pnp_option *option, | |||
321 | 321 | ||
322 | if (p->number_of_interrupts == 0) | 322 | if (p->number_of_interrupts == 0) |
323 | return; | 323 | return; |
324 | irq = pnpacpi_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL); | 324 | irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL); |
325 | if (!irq) | 325 | if (!irq) |
326 | return; | 326 | return; |
327 | 327 | ||
@@ -342,7 +342,7 @@ pnpacpi_parse_port_option(struct pnp_option *option, | |||
342 | 342 | ||
343 | if (io->range_length == 0) | 343 | if (io->range_length == 0) |
344 | return; | 344 | return; |
345 | port = pnpacpi_kmalloc(sizeof(struct pnp_port), GFP_KERNEL); | 345 | port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); |
346 | if (!port) | 346 | if (!port) |
347 | return; | 347 | return; |
348 | port->min = io->min_base_address; | 348 | port->min = io->min_base_address; |
@@ -363,7 +363,7 @@ pnpacpi_parse_fixed_port_option(struct pnp_option *option, | |||
363 | 363 | ||
364 | if (io->range_length == 0) | 364 | if (io->range_length == 0) |
365 | return; | 365 | return; |
366 | port = pnpacpi_kmalloc(sizeof(struct pnp_port), GFP_KERNEL); | 366 | port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); |
367 | if (!port) | 367 | if (!port) |
368 | return; | 368 | return; |
369 | port->min = port->max = io->base_address; | 369 | port->min = port->max = io->base_address; |
@@ -382,7 +382,7 @@ pnpacpi_parse_mem24_option(struct pnp_option *option, | |||
382 | 382 | ||
383 | if (p->range_length == 0) | 383 | if (p->range_length == 0) |
384 | return; | 384 | return; |
385 | mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL); | 385 | mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); |
386 | if (!mem) | 386 | if (!mem) |
387 | return; | 387 | return; |
388 | mem->min = p->min_base_address; | 388 | mem->min = p->min_base_address; |
@@ -405,7 +405,7 @@ pnpacpi_parse_mem32_option(struct pnp_option *option, | |||
405 | 405 | ||
406 | if (p->range_length == 0) | 406 | if (p->range_length == 0) |
407 | return; | 407 | return; |
408 | mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL); | 408 | mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); |
409 | if (!mem) | 409 | if (!mem) |
410 | return; | 410 | return; |
411 | mem->min = p->min_base_address; | 411 | mem->min = p->min_base_address; |
@@ -428,7 +428,7 @@ pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, | |||
428 | 428 | ||
429 | if (p->range_length == 0) | 429 | if (p->range_length == 0) |
430 | return; | 430 | return; |
431 | mem = pnpacpi_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL); | 431 | mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); |
432 | if (!mem) | 432 | if (!mem) |
433 | return; | 433 | return; |
434 | mem->min = mem->max = p->range_base_address; | 434 | mem->min = mem->max = p->range_base_address; |
@@ -612,7 +612,7 @@ int pnpacpi_build_resource_template(acpi_handle handle, | |||
612 | if (!res_cnt) | 612 | if (!res_cnt) |
613 | return -EINVAL; | 613 | return -EINVAL; |
614 | buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1; | 614 | buffer->length = sizeof(struct acpi_resource) * (res_cnt + 1) + 1; |
615 | buffer->pointer = pnpacpi_kmalloc(buffer->length - 1, GFP_KERNEL); | 615 | buffer->pointer = kcalloc(1, buffer->length - 1, GFP_KERNEL); |
616 | if (!buffer->pointer) | 616 | if (!buffer->pointer) |
617 | return -ENOMEM; | 617 | return -ENOMEM; |
618 | pnp_dbg("Res cnt %d", res_cnt); | 618 | pnp_dbg("Res cnt %d", res_cnt); |
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index 778a324028f4..f49674f07949 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c | |||
@@ -86,16 +86,6 @@ int pnp_bios_present(void) | |||
86 | 86 | ||
87 | struct pnp_dev_node_info node_info; | 87 | struct pnp_dev_node_info node_info; |
88 | 88 | ||
89 | void *pnpbios_kmalloc(size_t size, int f) | ||
90 | { | ||
91 | void *p = kmalloc( size, f ); | ||
92 | if ( p == NULL ) | ||
93 | printk(KERN_ERR "PnPBIOS: kmalloc() failed\n"); | ||
94 | else | ||
95 | memset(p, 0, size); | ||
96 | return p; | ||
97 | } | ||
98 | |||
99 | /* | 89 | /* |
100 | * | 90 | * |
101 | * DOCKING FUNCTIONS | 91 | * DOCKING FUNCTIONS |
@@ -121,10 +111,10 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info) | |||
121 | if (!current->fs->root) { | 111 | if (!current->fs->root) { |
122 | return -EAGAIN; | 112 | return -EAGAIN; |
123 | } | 113 | } |
124 | if (!(envp = (char **) pnpbios_kmalloc (20 * sizeof (char *), GFP_KERNEL))) { | 114 | if (!(envp = (char **) kcalloc (20, sizeof (char *), GFP_KERNEL))) { |
125 | return -ENOMEM; | 115 | return -ENOMEM; |
126 | } | 116 | } |
127 | if (!(buf = pnpbios_kmalloc (256, GFP_KERNEL))) { | 117 | if (!(buf = kcalloc (1, 256, GFP_KERNEL))) { |
128 | kfree (envp); | 118 | kfree (envp); |
129 | return -ENOMEM; | 119 | return -ENOMEM; |
130 | } | 120 | } |
@@ -231,7 +221,7 @@ static int pnpbios_get_resources(struct pnp_dev * dev, struct pnp_resource_table | |||
231 | if(!pnpbios_is_dynamic(dev)) | 221 | if(!pnpbios_is_dynamic(dev)) |
232 | return -EPERM; | 222 | return -EPERM; |
233 | 223 | ||
234 | node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL); | 224 | node = kcalloc(1, node_info.max_node_size, GFP_KERNEL); |
235 | if (!node) | 225 | if (!node) |
236 | return -1; | 226 | return -1; |
237 | if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) { | 227 | if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) { |
@@ -254,7 +244,7 @@ static int pnpbios_set_resources(struct pnp_dev * dev, struct pnp_resource_table | |||
254 | if (!pnpbios_is_dynamic(dev)) | 244 | if (!pnpbios_is_dynamic(dev)) |
255 | return -EPERM; | 245 | return -EPERM; |
256 | 246 | ||
257 | node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL); | 247 | node = kcalloc(1, node_info.max_node_size, GFP_KERNEL); |
258 | if (!node) | 248 | if (!node) |
259 | return -1; | 249 | return -1; |
260 | if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) { | 250 | if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) { |
@@ -305,7 +295,7 @@ static int pnpbios_disable_resources(struct pnp_dev *dev) | |||
305 | if(dev->flags & PNPBIOS_NO_DISABLE || !pnpbios_is_dynamic(dev)) | 295 | if(dev->flags & PNPBIOS_NO_DISABLE || !pnpbios_is_dynamic(dev)) |
306 | return -EPERM; | 296 | return -EPERM; |
307 | 297 | ||
308 | node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL); | 298 | node = kcalloc(1, node_info.max_node_size, GFP_KERNEL); |
309 | if (!node) | 299 | if (!node) |
310 | return -ENOMEM; | 300 | return -ENOMEM; |
311 | 301 | ||
@@ -347,7 +337,7 @@ static int insert_device(struct pnp_dev *dev, struct pnp_bios_node * node) | |||
347 | } | 337 | } |
348 | 338 | ||
349 | /* set the initial values for the PnP device */ | 339 | /* set the initial values for the PnP device */ |
350 | dev_id = pnpbios_kmalloc(sizeof(struct pnp_id), GFP_KERNEL); | 340 | dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL); |
351 | if (!dev_id) | 341 | if (!dev_id) |
352 | return -1; | 342 | return -1; |
353 | pnpid32_to_pnpid(node->eisa_id,id); | 343 | pnpid32_to_pnpid(node->eisa_id,id); |
@@ -385,7 +375,7 @@ static void __init build_devlist(void) | |||
385 | struct pnp_bios_node *node; | 375 | struct pnp_bios_node *node; |
386 | struct pnp_dev *dev; | 376 | struct pnp_dev *dev; |
387 | 377 | ||
388 | node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL); | 378 | node = kcalloc(1, node_info.max_node_size, GFP_KERNEL); |
389 | if (!node) | 379 | if (!node) |
390 | return; | 380 | return; |
391 | 381 | ||
@@ -402,7 +392,7 @@ static void __init build_devlist(void) | |||
402 | break; | 392 | break; |
403 | } | 393 | } |
404 | nodes_got++; | 394 | nodes_got++; |
405 | dev = pnpbios_kmalloc(sizeof (struct pnp_dev), GFP_KERNEL); | 395 | dev = kcalloc(1, sizeof (struct pnp_dev), GFP_KERNEL); |
406 | if (!dev) | 396 | if (!dev) |
407 | break; | 397 | break; |
408 | if(insert_device(dev,node)<0) | 398 | if(insert_device(dev,node)<0) |
diff --git a/drivers/pnp/pnpbios/pnpbios.h b/drivers/pnp/pnpbios/pnpbios.h index 01896e705ed4..d8cb2fd1f127 100644 --- a/drivers/pnp/pnpbios/pnpbios.h +++ b/drivers/pnp/pnpbios/pnpbios.h | |||
@@ -26,7 +26,6 @@ union pnp_bios_install_struct { | |||
26 | 26 | ||
27 | extern int pnp_bios_present(void); | 27 | extern int pnp_bios_present(void); |
28 | extern int pnpbios_dont_use_current_config; | 28 | extern int pnpbios_dont_use_current_config; |
29 | extern void *pnpbios_kmalloc(size_t size, int f); | ||
30 | 29 | ||
31 | extern int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node * node); | 30 | extern int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node * node); |
32 | extern int pnpbios_read_resources_from_node(struct pnp_resource_table *res, struct pnp_bios_node * node); | 31 | extern int pnpbios_read_resources_from_node(struct pnp_resource_table *res, struct pnp_bios_node * node); |
diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c index 6bb8e1973fd4..5a3dfc97f5e9 100644 --- a/drivers/pnp/pnpbios/proc.c +++ b/drivers/pnp/pnpbios/proc.c | |||
@@ -87,7 +87,7 @@ static int proc_read_escd(char *buf, char **start, off_t pos, | |||
87 | return -EFBIG; | 87 | return -EFBIG; |
88 | } | 88 | } |
89 | 89 | ||
90 | tmpbuf = pnpbios_kmalloc(escd.escd_size, GFP_KERNEL); | 90 | tmpbuf = kcalloc(1, escd.escd_size, GFP_KERNEL); |
91 | if (!tmpbuf) return -ENOMEM; | 91 | if (!tmpbuf) return -ENOMEM; |
92 | 92 | ||
93 | if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) { | 93 | if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) { |
@@ -133,7 +133,7 @@ static int proc_read_devices(char *buf, char **start, off_t pos, | |||
133 | if (pos >= 0xff) | 133 | if (pos >= 0xff) |
134 | return 0; | 134 | return 0; |
135 | 135 | ||
136 | node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL); | 136 | node = kcalloc(1, node_info.max_node_size, GFP_KERNEL); |
137 | if (!node) return -ENOMEM; | 137 | if (!node) return -ENOMEM; |
138 | 138 | ||
139 | for (nodenum=pos; nodenum<0xff; ) { | 139 | for (nodenum=pos; nodenum<0xff; ) { |
@@ -168,7 +168,7 @@ static int proc_read_node(char *buf, char **start, off_t pos, | |||
168 | u8 nodenum = (long)data; | 168 | u8 nodenum = (long)data; |
169 | int len; | 169 | int len; |
170 | 170 | ||
171 | node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL); | 171 | node = kcalloc(1, node_info.max_node_size, GFP_KERNEL); |
172 | if (!node) return -ENOMEM; | 172 | if (!node) return -ENOMEM; |
173 | if (pnp_bios_get_dev_node(&nodenum, boot, node)) { | 173 | if (pnp_bios_get_dev_node(&nodenum, boot, node)) { |
174 | kfree(node); | 174 | kfree(node); |
@@ -188,7 +188,7 @@ static int proc_write_node(struct file *file, const char __user *buf, | |||
188 | u8 nodenum = (long)data; | 188 | u8 nodenum = (long)data; |
189 | int ret = count; | 189 | int ret = count; |
190 | 190 | ||
191 | node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL); | 191 | node = kcalloc(1, node_info.max_node_size, GFP_KERNEL); |
192 | if (!node) | 192 | if (!node) |
193 | return -ENOMEM; | 193 | return -ENOMEM; |
194 | if (pnp_bios_get_dev_node(&nodenum, boot, node)) { | 194 | if (pnp_bios_get_dev_node(&nodenum, boot, node)) { |
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index e305bb132c24..b0ca65b68645 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c | |||
@@ -247,7 +247,7 @@ static void | |||
247 | pnpbios_parse_mem_option(unsigned char *p, int size, struct pnp_option *option) | 247 | pnpbios_parse_mem_option(unsigned char *p, int size, struct pnp_option *option) |
248 | { | 248 | { |
249 | struct pnp_mem * mem; | 249 | struct pnp_mem * mem; |
250 | mem = pnpbios_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL); | 250 | mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); |
251 | if (!mem) | 251 | if (!mem) |
252 | return; | 252 | return; |
253 | mem->min = ((p[5] << 8) | p[4]) << 8; | 253 | mem->min = ((p[5] << 8) | p[4]) << 8; |
@@ -263,7 +263,7 @@ static void | |||
263 | pnpbios_parse_mem32_option(unsigned char *p, int size, struct pnp_option *option) | 263 | pnpbios_parse_mem32_option(unsigned char *p, int size, struct pnp_option *option) |
264 | { | 264 | { |
265 | struct pnp_mem * mem; | 265 | struct pnp_mem * mem; |
266 | mem = pnpbios_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL); | 266 | mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); |
267 | if (!mem) | 267 | if (!mem) |
268 | return; | 268 | return; |
269 | mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4]; | 269 | mem->min = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4]; |
@@ -279,7 +279,7 @@ static void | |||
279 | pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, struct pnp_option *option) | 279 | pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, struct pnp_option *option) |
280 | { | 280 | { |
281 | struct pnp_mem * mem; | 281 | struct pnp_mem * mem; |
282 | mem = pnpbios_kmalloc(sizeof(struct pnp_mem), GFP_KERNEL); | 282 | mem = kcalloc(1, sizeof(struct pnp_mem), GFP_KERNEL); |
283 | if (!mem) | 283 | if (!mem) |
284 | return; | 284 | return; |
285 | mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4]; | 285 | mem->min = mem->max = (p[7] << 24) | (p[6] << 16) | (p[5] << 8) | p[4]; |
@@ -296,7 +296,7 @@ pnpbios_parse_irq_option(unsigned char *p, int size, struct pnp_option *option) | |||
296 | struct pnp_irq * irq; | 296 | struct pnp_irq * irq; |
297 | unsigned long bits; | 297 | unsigned long bits; |
298 | 298 | ||
299 | irq = pnpbios_kmalloc(sizeof(struct pnp_irq), GFP_KERNEL); | 299 | irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL); |
300 | if (!irq) | 300 | if (!irq) |
301 | return; | 301 | return; |
302 | bits = (p[2] << 8) | p[1]; | 302 | bits = (p[2] << 8) | p[1]; |
@@ -313,7 +313,7 @@ static void | |||
313 | pnpbios_parse_dma_option(unsigned char *p, int size, struct pnp_option *option) | 313 | pnpbios_parse_dma_option(unsigned char *p, int size, struct pnp_option *option) |
314 | { | 314 | { |
315 | struct pnp_dma * dma; | 315 | struct pnp_dma * dma; |
316 | dma = pnpbios_kmalloc(sizeof(struct pnp_dma), GFP_KERNEL); | 316 | dma = kcalloc(1, sizeof(struct pnp_dma), GFP_KERNEL); |
317 | if (!dma) | 317 | if (!dma) |
318 | return; | 318 | return; |
319 | dma->map = p[1]; | 319 | dma->map = p[1]; |
@@ -326,7 +326,7 @@ static void | |||
326 | pnpbios_parse_port_option(unsigned char *p, int size, struct pnp_option *option) | 326 | pnpbios_parse_port_option(unsigned char *p, int size, struct pnp_option *option) |
327 | { | 327 | { |
328 | struct pnp_port * port; | 328 | struct pnp_port * port; |
329 | port = pnpbios_kmalloc(sizeof(struct pnp_port), GFP_KERNEL); | 329 | port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); |
330 | if (!port) | 330 | if (!port) |
331 | return; | 331 | return; |
332 | port->min = (p[3] << 8) | p[2]; | 332 | port->min = (p[3] << 8) | p[2]; |
@@ -342,7 +342,7 @@ static void | |||
342 | pnpbios_parse_fixed_port_option(unsigned char *p, int size, struct pnp_option *option) | 342 | pnpbios_parse_fixed_port_option(unsigned char *p, int size, struct pnp_option *option) |
343 | { | 343 | { |
344 | struct pnp_port * port; | 344 | struct pnp_port * port; |
345 | port = pnpbios_kmalloc(sizeof(struct pnp_port), GFP_KERNEL); | 345 | port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL); |
346 | if (!port) | 346 | if (!port) |
347 | return; | 347 | return; |
348 | port->min = port->max = (p[2] << 8) | p[1]; | 348 | port->min = port->max = (p[2] << 8) | p[1]; |
@@ -530,7 +530,7 @@ pnpbios_parse_compatible_ids(unsigned char *p, unsigned char *end, struct pnp_de | |||
530 | case SMALL_TAG_COMPATDEVID: /* compatible ID */ | 530 | case SMALL_TAG_COMPATDEVID: /* compatible ID */ |
531 | if (len != 4) | 531 | if (len != 4) |
532 | goto len_err; | 532 | goto len_err; |
533 | dev_id = pnpbios_kmalloc(sizeof (struct pnp_id), GFP_KERNEL); | 533 | dev_id = kcalloc(1, sizeof (struct pnp_id), GFP_KERNEL); |
534 | if (!dev_id) | 534 | if (!dev_id) |
535 | return NULL; | 535 | return NULL; |
536 | memset(dev_id, 0, sizeof(struct pnp_id)); | 536 | memset(dev_id, 0, sizeof(struct pnp_id)); |
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index 596a02d7e03d..8936b0cb2ec3 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c | |||
@@ -16,13 +16,6 @@ | |||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | |||
20 | #ifdef CONFIG_PNP_DEBUG | ||
21 | #define DEBUG | ||
22 | #else | ||
23 | #undef DEBUG | ||
24 | #endif | ||
25 | |||
26 | #include <linux/pnp.h> | 19 | #include <linux/pnp.h> |
27 | #include "base.h" | 20 | #include "base.h" |
28 | 21 | ||
diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c index b952aec49189..61fe998944bd 100644 --- a/drivers/pnp/support.c +++ b/drivers/pnp/support.c | |||
@@ -8,13 +8,6 @@ | |||
8 | #include <linux/config.h> | 8 | #include <linux/config.h> |
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/ctype.h> | 10 | #include <linux/ctype.h> |
11 | |||
12 | #ifdef CONFIG_PNP_DEBUG | ||
13 | #define DEBUG | ||
14 | #else | ||
15 | #undef DEBUG | ||
16 | #endif | ||
17 | |||
18 | #include <linux/pnp.h> | 11 | #include <linux/pnp.h> |
19 | #include "base.h" | 12 | #include "base.h" |
20 | 13 | ||
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 029c2482e127..ffcdeb68641c 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c | |||
@@ -494,7 +494,7 @@ static int qs_port_start(struct ata_port *ap) | |||
494 | if (rc) | 494 | if (rc) |
495 | return rc; | 495 | return rc; |
496 | qs_enter_reg_mode(ap); | 496 | qs_enter_reg_mode(ap); |
497 | pp = kcalloc(1, sizeof(*pp), GFP_KERNEL); | 497 | pp = kzalloc(sizeof(*pp), GFP_KERNEL); |
498 | if (!pp) { | 498 | if (!pp) { |
499 | rc = -ENOMEM; | 499 | rc = -ENOMEM; |
500 | goto err_out; | 500 | goto err_out; |
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 9097f2f7b12a..2efb317153ce 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <asm/io.h> | 40 | #include <asm/io.h> |
41 | #include <asm/irq.h> | 41 | #include <asm/irq.h> |
42 | #include <asm/system.h> | 42 | #include <asm/system.h> |
43 | #include <asm/segment.h> | ||
44 | #include <asm/delay.h> | 43 | #include <asm/delay.h> |
45 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
46 | 45 | ||
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index b116122e569a..170c9d2a749c 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c | |||
@@ -2474,8 +2474,7 @@ static struct tty_operations rs_360_ops = { | |||
2474 | .tiocmset = rs_360_tiocmset, | 2474 | .tiocmset = rs_360_tiocmset, |
2475 | }; | 2475 | }; |
2476 | 2476 | ||
2477 | /* int __init rs_360_init(void) */ | 2477 | static int __init rs_360_init(void) |
2478 | int rs_360_init(void) | ||
2479 | { | 2478 | { |
2480 | struct serial_state * state; | 2479 | struct serial_state * state; |
2481 | ser_info_t *info; | 2480 | ser_info_t *info; |
@@ -2827,10 +2826,7 @@ int rs_360_init(void) | |||
2827 | 2826 | ||
2828 | return 0; | 2827 | return 0; |
2829 | } | 2828 | } |
2830 | 2829 | module_init(rs_360_init); | |
2831 | |||
2832 | |||
2833 | |||
2834 | 2830 | ||
2835 | /* This must always be called before the rs_360_init() function, otherwise | 2831 | /* This must always be called before the rs_360_init() function, otherwise |
2836 | * it blows away the port control information. | 2832 | * it blows away the port control information. |
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 5690594b257b..40d3e7139cfe 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c | |||
@@ -446,7 +446,6 @@ static char *serial_version = "$Revision: 1.25 $"; | |||
446 | #include <asm/io.h> | 446 | #include <asm/io.h> |
447 | #include <asm/irq.h> | 447 | #include <asm/irq.h> |
448 | #include <asm/system.h> | 448 | #include <asm/system.h> |
449 | #include <asm/segment.h> | ||
450 | #include <asm/bitops.h> | 449 | #include <asm/bitops.h> |
451 | #include <linux/delay.h> | 450 | #include <linux/delay.h> |
452 | 451 | ||
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index 79f8df4d66b7..eb31125c6a30 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c | |||
@@ -56,7 +56,6 @@ | |||
56 | #include <linux/bitops.h> | 56 | #include <linux/bitops.h> |
57 | 57 | ||
58 | #include <asm/system.h> | 58 | #include <asm/system.h> |
59 | #include <asm/segment.h> | ||
60 | #include <asm/io.h> | 59 | #include <asm/io.h> |
61 | #include <asm/irq.h> | 60 | #include <asm/irq.h> |
62 | #include <asm/uaccess.h> | 61 | #include <asm/uaccess.h> |
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index 8c40167778de..43b03c55f453 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <asm/io.h> | 40 | #include <asm/io.h> |
41 | #include <asm/irq.h> | 41 | #include <asm/irq.h> |
42 | #include <asm/system.h> | 42 | #include <asm/system.h> |
43 | #include <asm/segment.h> | ||
44 | #include <asm/semaphore.h> | 43 | #include <asm/semaphore.h> |
45 | #include <asm/delay.h> | 44 | #include <asm/delay.h> |
46 | #include <asm/coldfire.h> | 45 | #include <asm/coldfire.h> |
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index bb1db1959854..c466739428b2 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c | |||
@@ -960,7 +960,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, | |||
960 | intf->altsetting->desc.bInterfaceNumber); | 960 | intf->altsetting->desc.bInterfaceNumber); |
961 | 961 | ||
962 | /* instance init */ | 962 | /* instance init */ |
963 | instance = kcalloc(1, sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL); | 963 | instance = kzalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL); |
964 | if (!instance) { | 964 | if (!instance) { |
965 | dev_dbg(dev, "%s: no memory for instance data!\n", __func__); | 965 | dev_dbg(dev, "%s: no memory for instance data!\n", __func__); |
966 | return -ENOMEM; | 966 | return -ENOMEM; |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 9f44e83c6a69..12ecdb03ee5f 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -1669,7 +1669,7 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, | |||
1669 | { | 1669 | { |
1670 | struct usb_hcd *hcd; | 1670 | struct usb_hcd *hcd; |
1671 | 1671 | ||
1672 | hcd = kcalloc(1, sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL); | 1672 | hcd = kzalloc(sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL); |
1673 | if (!hcd) { | 1673 | if (!hcd) { |
1674 | dev_dbg (dev, "hcd alloc failed\n"); | 1674 | dev_dbg (dev, "hcd alloc failed\n"); |
1675 | return NULL; | 1675 | return NULL; |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index b56f25864ed6..4c972b57c7c3 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -638,7 +638,7 @@ iso_stream_alloc (unsigned mem_flags) | |||
638 | { | 638 | { |
639 | struct ehci_iso_stream *stream; | 639 | struct ehci_iso_stream *stream; |
640 | 640 | ||
641 | stream = kcalloc(1, sizeof *stream, mem_flags); | 641 | stream = kzalloc(sizeof *stream, mem_flags); |
642 | if (likely (stream != NULL)) { | 642 | if (likely (stream != NULL)) { |
643 | INIT_LIST_HEAD(&stream->td_list); | 643 | INIT_LIST_HEAD(&stream->td_list); |
644 | INIT_LIST_HEAD(&stream->free_list); | 644 | INIT_LIST_HEAD(&stream->free_list); |
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 76cb496c5836..75128c371800 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
@@ -717,7 +717,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, | |||
717 | } | 717 | } |
718 | /* avoid all allocations within spinlocks: request or endpoint */ | 718 | /* avoid all allocations within spinlocks: request or endpoint */ |
719 | if (!hep->hcpriv) { | 719 | if (!hep->hcpriv) { |
720 | ep = kcalloc(1, sizeof *ep, mem_flags); | 720 | ep = kzalloc(sizeof *ep, mem_flags); |
721 | if (!ep) | 721 | if (!ep) |
722 | return -ENOMEM; | 722 | return -ENOMEM; |
723 | } | 723 | } |
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 80eaf659c198..d2a1fd40dfcb 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c | |||
@@ -835,7 +835,7 @@ static int sl811h_urb_enqueue( | |||
835 | 835 | ||
836 | /* avoid all allocations within spinlocks */ | 836 | /* avoid all allocations within spinlocks */ |
837 | if (!hep->hcpriv) | 837 | if (!hep->hcpriv) |
838 | ep = kcalloc(1, sizeof *ep, mem_flags); | 838 | ep = kzalloc(sizeof *ep, mem_flags); |
839 | 839 | ||
840 | spin_lock_irqsave(&sl811->lock, flags); | 840 | spin_lock_irqsave(&sl811->lock, flags); |
841 | 841 | ||
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c index 13532f3e3efc..74f8760d7c07 100644 --- a/drivers/usb/input/acecad.c +++ b/drivers/usb/input/acecad.c | |||
@@ -152,7 +152,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ | |||
152 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | 152 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); |
153 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | 153 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); |
154 | 154 | ||
155 | acecad = kcalloc(1, sizeof(struct usb_acecad), GFP_KERNEL); | 155 | acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL); |
156 | if (!acecad) | 156 | if (!acecad) |
157 | return -ENOMEM; | 157 | return -ENOMEM; |
158 | 158 | ||
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c index 0dc439f10823..becb87efb869 100644 --- a/drivers/usb/input/itmtouch.c +++ b/drivers/usb/input/itmtouch.c | |||
@@ -166,7 +166,7 @@ static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id | |||
166 | interface = intf->cur_altsetting; | 166 | interface = intf->cur_altsetting; |
167 | endpoint = &interface->endpoint[0].desc; | 167 | endpoint = &interface->endpoint[0].desc; |
168 | 168 | ||
169 | if (!(itmtouch = kcalloc(1, sizeof(struct itmtouch_dev), GFP_KERNEL))) { | 169 | if (!(itmtouch = kzalloc(sizeof(struct itmtouch_dev), GFP_KERNEL))) { |
170 | err("%s - Out of memory.", __FUNCTION__); | 170 | err("%s - Out of memory.", __FUNCTION__); |
171 | return -ENOMEM; | 171 | return -ENOMEM; |
172 | } | 172 | } |
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c index 256963863478..acc71ec560e9 100644 --- a/drivers/usb/input/pid.c +++ b/drivers/usb/input/pid.c | |||
@@ -263,7 +263,7 @@ int hid_pid_init(struct hid_device *hid) | |||
263 | struct hid_ff_pid *private; | 263 | struct hid_ff_pid *private; |
264 | struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list); | 264 | struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list); |
265 | 265 | ||
266 | private = hid->ff_private = kcalloc(1, sizeof(struct hid_ff_pid), GFP_KERNEL); | 266 | private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); |
267 | if (!private) | 267 | if (!private) |
268 | return -ENOMEM; | 268 | return -ENOMEM; |
269 | 269 | ||
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 9aae884475be..4af321fae390 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile | |||
@@ -3,3 +3,4 @@ | |||
3 | obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o | 3 | obj-$(CONFIG_LCD_CLASS_DEVICE) += lcd.o |
4 | obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o | 4 | obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o |
5 | obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o | 5 | obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o |
6 | obj-$(CONFIG_SHARP_LOCOMO) += locomolcd.o | ||
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c new file mode 100644 index 000000000000..ada6e75eb048 --- /dev/null +++ b/drivers/video/backlight/locomolcd.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * Backlight control code for Sharp Zaurus SL-5500 | ||
3 | * | ||
4 | * Copyright 2005 John Lenz <lenz@cs.wisc.edu> | ||
5 | * Maintainer: Pavel Machek <pavel@suse.cz> (unless John wants to :-) | ||
6 | * GPL v2 | ||
7 | * | ||
8 | * This driver assumes single CPU. That's okay, because collie is | ||
9 | * slightly old hardware, and noone is going to retrofit second CPU to | ||
10 | * old PDA. | ||
11 | */ | ||
12 | |||
13 | /* LCD power functions */ | ||
14 | #include <linux/config.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | |||
21 | #include <asm/hardware/locomo.h> | ||
22 | #include <asm/irq.h> | ||
23 | |||
24 | #ifdef CONFIG_SA1100_COLLIE | ||
25 | #include <asm/arch/collie.h> | ||
26 | #else | ||
27 | #include <asm/arch/poodle.h> | ||
28 | #endif | ||
29 | |||
30 | extern void (*sa1100fb_lcd_power)(int on); | ||
31 | |||
32 | static struct locomo_dev *locomolcd_dev; | ||
33 | |||
34 | static void locomolcd_on(int comadj) | ||
35 | { | ||
36 | locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0); | ||
37 | locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 1); | ||
38 | mdelay(2); | ||
39 | |||
40 | locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0); | ||
41 | locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 1); | ||
42 | mdelay(2); | ||
43 | |||
44 | locomo_m62332_senddata(locomolcd_dev, comadj, 0); | ||
45 | mdelay(5); | ||
46 | |||
47 | locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0); | ||
48 | locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 1); | ||
49 | mdelay(10); | ||
50 | |||
51 | /* TFTCRST | CPSOUT=0 | CPSEN */ | ||
52 | locomo_writel(0x01, locomolcd_dev->mapbase + LOCOMO_TC); | ||
53 | |||
54 | /* Set CPSD */ | ||
55 | locomo_writel(6, locomolcd_dev->mapbase + LOCOMO_CPSD); | ||
56 | |||
57 | /* TFTCRST | CPSOUT=0 | CPSEN */ | ||
58 | locomo_writel((0x04 | 0x01), locomolcd_dev->mapbase + LOCOMO_TC); | ||
59 | mdelay(10); | ||
60 | |||
61 | locomo_gpio_set_dir(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0); | ||
62 | locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 1); | ||
63 | } | ||
64 | |||
65 | static void locomolcd_off(int comadj) | ||
66 | { | ||
67 | /* TFTCRST=1 | CPSOUT=1 | CPSEN = 0 */ | ||
68 | locomo_writel(0x06, locomolcd_dev->mapbase + LOCOMO_TC); | ||
69 | mdelay(1); | ||
70 | |||
71 | locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHA_ON, 0); | ||
72 | mdelay(110); | ||
73 | |||
74 | locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VEE_ON, 0); | ||
75 | mdelay(700); | ||
76 | |||
77 | /* TFTCRST=0 | CPSOUT=0 | CPSEN = 0 */ | ||
78 | locomo_writel(0, locomolcd_dev->mapbase + LOCOMO_TC); | ||
79 | locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_MOD, 0); | ||
80 | locomo_gpio_write(locomolcd_dev, LOCOMO_GPIO_LCD_VSHD_ON, 0); | ||
81 | } | ||
82 | |||
83 | void locomolcd_power(int on) | ||
84 | { | ||
85 | int comadj = 118; | ||
86 | unsigned long flags; | ||
87 | |||
88 | local_irq_save(flags); | ||
89 | |||
90 | if (!locomolcd_dev) { | ||
91 | local_irq_restore(flags); | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | /* read comadj */ | ||
96 | #ifdef CONFIG_MACH_POODLE | ||
97 | comadj = 118; | ||
98 | #else | ||
99 | comadj = 128; | ||
100 | #endif | ||
101 | |||
102 | if (on) | ||
103 | locomolcd_on(comadj); | ||
104 | else | ||
105 | locomolcd_off(comadj); | ||
106 | |||
107 | local_irq_restore(flags); | ||
108 | } | ||
109 | EXPORT_SYMBOL(locomolcd_power); | ||
110 | |||
111 | static int poodle_lcd_probe(struct locomo_dev *dev) | ||
112 | { | ||
113 | unsigned long flags; | ||
114 | |||
115 | local_irq_save(flags); | ||
116 | locomolcd_dev = dev; | ||
117 | |||
118 | /* the poodle_lcd_power function is called for the first time | ||
119 | * from fs_initcall, which is before locomo is activated. | ||
120 | * We need to recall poodle_lcd_power here*/ | ||
121 | #ifdef CONFIG_MACH_POODLE | ||
122 | locomolcd_power(1); | ||
123 | #endif | ||
124 | local_irq_restore(flags); | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static int poodle_lcd_remove(struct locomo_dev *dev) | ||
129 | { | ||
130 | unsigned long flags; | ||
131 | local_irq_save(flags); | ||
132 | locomolcd_dev = NULL; | ||
133 | local_irq_restore(flags); | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static struct locomo_driver poodle_lcd_driver = { | ||
138 | .drv = { | ||
139 | .name = "locomo-backlight", | ||
140 | }, | ||
141 | .devid = LOCOMO_DEVID_BACKLIGHT, | ||
142 | .probe = poodle_lcd_probe, | ||
143 | .remove = poodle_lcd_remove, | ||
144 | }; | ||
145 | |||
146 | static int __init poodle_lcd_init(void) | ||
147 | { | ||
148 | int ret = locomo_driver_register(&poodle_lcd_driver); | ||
149 | if (ret) return ret; | ||
150 | |||
151 | #ifdef CONFIG_SA1100_COLLIE | ||
152 | sa1100fb_lcd_power = locomolcd_power; | ||
153 | #endif | ||
154 | return 0; | ||
155 | } | ||
156 | device_initcall(poodle_lcd_init); | ||
157 | |||
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c index 71b69da0c40d..162012bb9264 100644 --- a/drivers/video/q40fb.c +++ b/drivers/video/q40fb.c | |||
@@ -21,7 +21,6 @@ | |||
21 | 21 | ||
22 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
23 | #include <asm/setup.h> | 23 | #include <asm/setup.h> |
24 | #include <asm/segment.h> | ||
25 | #include <asm/system.h> | 24 | #include <asm/system.h> |
26 | #include <asm/q40_master.h> | 25 | #include <asm/q40_master.h> |
27 | #include <linux/fb.h> | 26 | #include <linux/fb.h> |
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index adcda697ea60..0030c071da8f 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c | |||
@@ -5,9 +5,15 @@ | |||
5 | * | 5 | * |
6 | * Copyright (C) 2002, ATI Corp. | 6 | * Copyright (C) 2002, ATI Corp. |
7 | * Copyright (C) 2004-2005 Richard Purdie | 7 | * Copyright (C) 2004-2005 Richard Purdie |
8 | * Copyright (c) 2005 Ian Molton | ||
8 | * | 9 | * |
9 | * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net> | 10 | * Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net> |
10 | * | 11 | * |
12 | * Generic platform support by Ian Molton <spyro@f2s.com> | ||
13 | * and Richard Purdie <rpurdie@rpsys.net> | ||
14 | * | ||
15 | * w32xx support by Ian Molton | ||
16 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | 17 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 18 | * it under the terms of the GNU General Public License version 2 as |
13 | * published by the Free Software Foundation. | 19 | * published by the Free Software Foundation. |
@@ -21,7 +27,7 @@ | |||
21 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
22 | #include <linux/device.h> | 28 | #include <linux/device.h> |
23 | #include <linux/string.h> | 29 | #include <linux/string.h> |
24 | #include <linux/proc_fs.h> | 30 | #include <linux/vmalloc.h> |
25 | #include <asm/io.h> | 31 | #include <asm/io.h> |
26 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
27 | #include <video/w100fb.h> | 33 | #include <video/w100fb.h> |
@@ -30,114 +36,78 @@ | |||
30 | /* | 36 | /* |
31 | * Prototypes | 37 | * Prototypes |
32 | */ | 38 | */ |
33 | static void w100fb_save_buffer(void); | ||
34 | static void w100fb_clear_buffer(void); | ||
35 | static void w100fb_restore_buffer(void); | ||
36 | static void w100fb_clear_screen(u32 mode, long int offset); | ||
37 | static void w100_resume(void); | ||
38 | static void w100_suspend(u32 mode); | 39 | static void w100_suspend(u32 mode); |
39 | static void w100_init_qvga_rotation(u16 deg); | ||
40 | static void w100_init_vga_rotation(u16 deg); | ||
41 | static void w100_vsync(void); | 40 | static void w100_vsync(void); |
42 | static void w100_init_sharp_lcd(u32 mode); | 41 | static void w100_hw_init(struct w100fb_par*); |
43 | static void w100_pwm_setup(void); | 42 | static void w100_pwm_setup(struct w100fb_par*); |
44 | static void w100_InitExtMem(u32 mode); | 43 | static void w100_init_clocks(struct w100fb_par*); |
45 | static void w100_hw_init(void); | 44 | static void w100_setup_memory(struct w100fb_par*); |
46 | static u16 w100_set_fastsysclk(u16 Freq); | 45 | static void w100_init_lcd(struct w100fb_par*); |
47 | 46 | static void w100_set_dispregs(struct w100fb_par*); | |
48 | static void lcdtg_hw_init(u32 mode); | 47 | static void w100_update_enable(void); |
49 | static void lcdtg_lcd_change(u32 mode); | 48 | static void w100_update_disable(void); |
50 | static void lcdtg_resume(void); | 49 | static void calc_hsync(struct w100fb_par *par); |
51 | static void lcdtg_suspend(void); | 50 | struct w100_pll_info *w100_get_xtal_table(unsigned int freq); |
52 | |||
53 | |||
54 | /* Register offsets & lengths */ | ||
55 | #define REMAPPED_FB_LEN 0x15ffff | ||
56 | |||
57 | #define BITS_PER_PIXEL 16 | ||
58 | 51 | ||
59 | /* Pseudo palette size */ | 52 | /* Pseudo palette size */ |
60 | #define MAX_PALETTES 16 | 53 | #define MAX_PALETTES 16 |
61 | 54 | ||
62 | /* for resolution change */ | ||
63 | #define LCD_MODE_INIT (-1) | ||
64 | #define LCD_MODE_480 0 | ||
65 | #define LCD_MODE_320 1 | ||
66 | #define LCD_MODE_240 2 | ||
67 | #define LCD_MODE_640 3 | ||
68 | |||
69 | #define LCD_SHARP_QVGA 0 | ||
70 | #define LCD_SHARP_VGA 1 | ||
71 | |||
72 | #define LCD_MODE_PORTRAIT 0 | ||
73 | #define LCD_MODE_LANDSCAPE 1 | ||
74 | |||
75 | #define W100_SUSPEND_EXTMEM 0 | 55 | #define W100_SUSPEND_EXTMEM 0 |
76 | #define W100_SUSPEND_ALL 1 | 56 | #define W100_SUSPEND_ALL 1 |
77 | 57 | ||
78 | /* General frame buffer data structures */ | 58 | #define BITS_PER_PIXEL 16 |
79 | struct w100fb_par { | ||
80 | u32 xres; | ||
81 | u32 yres; | ||
82 | int fastsysclk_mode; | ||
83 | int lcdMode; | ||
84 | int rotation_flag; | ||
85 | int blanking_flag; | ||
86 | int comadj; | ||
87 | int phadadj; | ||
88 | }; | ||
89 | |||
90 | static struct w100fb_par *current_par; | ||
91 | 59 | ||
92 | /* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */ | 60 | /* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */ |
93 | static void *remapped_base; | 61 | static void *remapped_base; |
94 | static void *remapped_regs; | 62 | static void *remapped_regs; |
95 | static void *remapped_fbuf; | 63 | static void *remapped_fbuf; |
96 | 64 | ||
97 | /* External Function */ | 65 | #define REMAPPED_FB_LEN 0x15ffff |
98 | static void(*w100fb_ssp_send)(u8 adrs, u8 data); | 66 | |
67 | /* This is the offset in the w100's address space we map the current | ||
68 | framebuffer memory to. We use the position of external memory as | ||
69 | we can remap internal memory to there if external isn't present. */ | ||
70 | #define W100_FB_BASE MEM_EXT_BASE_VALUE | ||
71 | |||
99 | 72 | ||
100 | /* | 73 | /* |
101 | * Sysfs functions | 74 | * Sysfs functions |
102 | */ | 75 | */ |
103 | 76 | static ssize_t flip_show(struct device *dev, struct device_attribute *attr, char *buf) | |
104 | static ssize_t rotation_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
105 | { | 77 | { |
106 | struct fb_info *info = dev_get_drvdata(dev); | 78 | struct fb_info *info = dev_get_drvdata(dev); |
107 | struct w100fb_par *par=info->par; | 79 | struct w100fb_par *par=info->par; |
108 | 80 | ||
109 | return sprintf(buf, "%d\n",par->rotation_flag); | 81 | return sprintf(buf, "%d\n",par->flip); |
110 | } | 82 | } |
111 | 83 | ||
112 | static ssize_t rotation_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 84 | static ssize_t flip_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
113 | { | 85 | { |
114 | unsigned int rotate; | 86 | unsigned int flip; |
115 | struct fb_info *info = dev_get_drvdata(dev); | 87 | struct fb_info *info = dev_get_drvdata(dev); |
116 | struct w100fb_par *par=info->par; | 88 | struct w100fb_par *par=info->par; |
117 | 89 | ||
118 | rotate = simple_strtoul(buf, NULL, 10); | 90 | flip = simple_strtoul(buf, NULL, 10); |
91 | |||
92 | if (flip > 0) | ||
93 | par->flip = 1; | ||
94 | else | ||
95 | par->flip = 0; | ||
119 | 96 | ||
120 | if (rotate > 0) par->rotation_flag = 1; | 97 | w100_update_disable(); |
121 | else par->rotation_flag = 0; | 98 | w100_set_dispregs(par); |
99 | w100_update_enable(); | ||
122 | 100 | ||
123 | if (par->lcdMode == LCD_MODE_320) | 101 | calc_hsync(par); |
124 | w100_init_qvga_rotation(par->rotation_flag ? 270 : 90); | ||
125 | else if (par->lcdMode == LCD_MODE_240) | ||
126 | w100_init_qvga_rotation(par->rotation_flag ? 180 : 0); | ||
127 | else if (par->lcdMode == LCD_MODE_640) | ||
128 | w100_init_vga_rotation(par->rotation_flag ? 270 : 90); | ||
129 | else if (par->lcdMode == LCD_MODE_480) | ||
130 | w100_init_vga_rotation(par->rotation_flag ? 180 : 0); | ||
131 | 102 | ||
132 | return count; | 103 | return count; |
133 | } | 104 | } |
134 | 105 | ||
135 | static DEVICE_ATTR(rotation, 0644, rotation_show, rotation_store); | 106 | static DEVICE_ATTR(flip, 0644, flip_show, flip_store); |
136 | 107 | ||
137 | static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 108 | static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
138 | { | 109 | { |
139 | unsigned long param; | 110 | unsigned long regs, param; |
140 | unsigned long regs; | ||
141 | regs = simple_strtoul(buf, NULL, 16); | 111 | regs = simple_strtoul(buf, NULL, 16); |
142 | param = readl(remapped_regs + regs); | 112 | param = readl(remapped_regs + regs); |
143 | printk("Read Register 0x%08lX: 0x%08lX\n", regs, param); | 113 | printk("Read Register 0x%08lX: 0x%08lX\n", regs, param); |
@@ -148,8 +118,7 @@ static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read); | |||
148 | 118 | ||
149 | static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 119 | static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
150 | { | 120 | { |
151 | unsigned long regs; | 121 | unsigned long regs, param; |
152 | unsigned long param; | ||
153 | sscanf(buf, "%lx %lx", ®s, ¶m); | 122 | sscanf(buf, "%lx %lx", ®s, ¶m); |
154 | 123 | ||
155 | if (regs <= 0x2000) { | 124 | if (regs <= 0x2000) { |
@@ -163,54 +132,56 @@ static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *att | |||
163 | static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write); | 132 | static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write); |
164 | 133 | ||
165 | 134 | ||
166 | static ssize_t fastsysclk_show(struct device *dev, struct device_attribute *attr, char *buf) | 135 | static ssize_t fastpllclk_show(struct device *dev, struct device_attribute *attr, char *buf) |
167 | { | 136 | { |
168 | struct fb_info *info = dev_get_drvdata(dev); | 137 | struct fb_info *info = dev_get_drvdata(dev); |
169 | struct w100fb_par *par=info->par; | 138 | struct w100fb_par *par=info->par; |
170 | 139 | ||
171 | return sprintf(buf, "%d\n",par->fastsysclk_mode); | 140 | return sprintf(buf, "%d\n",par->fastpll_mode); |
172 | } | 141 | } |
173 | 142 | ||
174 | static ssize_t fastsysclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 143 | static ssize_t fastpllclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
175 | { | 144 | { |
176 | int param; | ||
177 | struct fb_info *info = dev_get_drvdata(dev); | 145 | struct fb_info *info = dev_get_drvdata(dev); |
178 | struct w100fb_par *par=info->par; | 146 | struct w100fb_par *par=info->par; |
179 | 147 | ||
180 | param = simple_strtoul(buf, NULL, 10); | 148 | if (simple_strtoul(buf, NULL, 10) > 0) { |
181 | 149 | par->fastpll_mode=1; | |
182 | if (param == 75) { | 150 | printk("w100fb: Using fast system clock (if possible)\n"); |
183 | printk("Set fastsysclk %d\n", param); | 151 | } else { |
184 | par->fastsysclk_mode = param; | 152 | par->fastpll_mode=0; |
185 | w100_set_fastsysclk(par->fastsysclk_mode); | 153 | printk("w100fb: Using normal system clock\n"); |
186 | } else if (param == 100) { | ||
187 | printk("Set fastsysclk %d\n", param); | ||
188 | par->fastsysclk_mode = param; | ||
189 | w100_set_fastsysclk(par->fastsysclk_mode); | ||
190 | } | 154 | } |
155 | |||
156 | w100_init_clocks(par); | ||
157 | calc_hsync(par); | ||
158 | |||
191 | return count; | 159 | return count; |
192 | } | 160 | } |
193 | 161 | ||
194 | static DEVICE_ATTR(fastsysclk, 0644, fastsysclk_show, fastsysclk_store); | 162 | static DEVICE_ATTR(fastpllclk, 0644, fastpllclk_show, fastpllclk_store); |
195 | 163 | ||
196 | /* | 164 | /* |
197 | * The touchscreen on this device needs certain information | 165 | * Some touchscreens need hsync information from the video driver to |
198 | * from the video driver to function correctly. We export it here. | 166 | * function correctly. We export it here. |
199 | */ | 167 | */ |
200 | int w100fb_get_xres(void) { | 168 | unsigned long w100fb_get_hsynclen(struct device *dev) |
201 | return current_par->xres; | 169 | { |
202 | } | 170 | struct fb_info *info = dev_get_drvdata(dev); |
171 | struct w100fb_par *par=info->par; | ||
203 | 172 | ||
204 | int w100fb_get_blanking(void) { | 173 | /* If display is blanked/suspended, hsync isn't active */ |
205 | return current_par->blanking_flag; | 174 | if (par->blanked) |
175 | return 0; | ||
176 | else | ||
177 | return par->hsync_len; | ||
206 | } | 178 | } |
179 | EXPORT_SYMBOL(w100fb_get_hsynclen); | ||
207 | 180 | ||
208 | int w100fb_get_fastsysclk(void) { | 181 | static void w100fb_clear_screen(struct w100fb_par *par) |
209 | return current_par->fastsysclk_mode; | 182 | { |
183 | memset_io(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), 0, (par->xres * par->yres * BITS_PER_PIXEL/8)); | ||
210 | } | 184 | } |
211 | EXPORT_SYMBOL(w100fb_get_xres); | ||
212 | EXPORT_SYMBOL(w100fb_get_blanking); | ||
213 | EXPORT_SYMBOL(w100fb_get_fastsysclk); | ||
214 | 185 | ||
215 | 186 | ||
216 | /* | 187 | /* |
@@ -234,7 +205,6 @@ static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
234 | * according to the RGB bitfield information. | 205 | * according to the RGB bitfield information. |
235 | */ | 206 | */ |
236 | if (regno < MAX_PALETTES) { | 207 | if (regno < MAX_PALETTES) { |
237 | |||
238 | u32 *pal = info->pseudo_palette; | 208 | u32 *pal = info->pseudo_palette; |
239 | 209 | ||
240 | val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); | 210 | val = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); |
@@ -250,115 +220,90 @@ static int w100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | |||
250 | */ | 220 | */ |
251 | static int w100fb_blank(int blank_mode, struct fb_info *info) | 221 | static int w100fb_blank(int blank_mode, struct fb_info *info) |
252 | { | 222 | { |
253 | struct w100fb_par *par; | 223 | struct w100fb_par *par = info->par; |
254 | par=info->par; | 224 | struct w100_tg_info *tg = par->mach->tg; |
255 | 225 | ||
256 | switch(blank_mode) { | 226 | switch(blank_mode) { |
257 | 227 | ||
258 | case FB_BLANK_NORMAL: /* Normal blanking */ | 228 | case FB_BLANK_NORMAL: /* Normal blanking */ |
259 | case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */ | 229 | case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */ |
260 | case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */ | 230 | case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */ |
261 | case FB_BLANK_POWERDOWN: /* Poweroff */ | 231 | case FB_BLANK_POWERDOWN: /* Poweroff */ |
262 | if (par->blanking_flag == 0) { | 232 | if (par->blanked == 0) { |
263 | w100fb_save_buffer(); | 233 | if(tg && tg->suspend) |
264 | lcdtg_suspend(); | 234 | tg->suspend(par); |
265 | par->blanking_flag = 1; | 235 | par->blanked = 1; |
266 | } | 236 | } |
267 | break; | 237 | break; |
268 | 238 | ||
269 | case FB_BLANK_UNBLANK: /* Unblanking */ | 239 | case FB_BLANK_UNBLANK: /* Unblanking */ |
270 | if (par->blanking_flag != 0) { | 240 | if (par->blanked != 0) { |
271 | w100fb_restore_buffer(); | 241 | if(tg && tg->resume) |
272 | lcdtg_resume(); | 242 | tg->resume(par); |
273 | par->blanking_flag = 0; | 243 | par->blanked = 0; |
274 | } | 244 | } |
275 | break; | 245 | break; |
276 | } | 246 | } |
277 | return 0; | 247 | return 0; |
278 | } | 248 | } |
279 | 249 | ||
250 | |||
280 | /* | 251 | /* |
281 | * Change the resolution by calling the appropriate hardware functions | 252 | * Change the resolution by calling the appropriate hardware functions |
282 | */ | 253 | */ |
283 | static void w100fb_changeres(int rotate_mode, u32 mode) | 254 | static void w100fb_activate_var(struct w100fb_par *par) |
284 | { | 255 | { |
285 | u16 rotation=0; | 256 | struct w100_tg_info *tg = par->mach->tg; |
286 | |||
287 | switch(rotate_mode) { | ||
288 | case LCD_MODE_LANDSCAPE: | ||
289 | rotation=(current_par->rotation_flag ? 270 : 90); | ||
290 | break; | ||
291 | case LCD_MODE_PORTRAIT: | ||
292 | rotation=(current_par->rotation_flag ? 180 : 0); | ||
293 | break; | ||
294 | } | ||
295 | 257 | ||
296 | w100_pwm_setup(); | 258 | w100_pwm_setup(par); |
297 | switch(mode) { | 259 | w100_setup_memory(par); |
298 | case LCD_SHARP_QVGA: | 260 | w100_init_clocks(par); |
299 | w100_vsync(); | 261 | w100fb_clear_screen(par); |
300 | w100_suspend(W100_SUSPEND_EXTMEM); | 262 | w100_vsync(); |
301 | w100_init_sharp_lcd(LCD_SHARP_QVGA); | 263 | |
302 | w100_init_qvga_rotation(rotation); | 264 | w100_update_disable(); |
303 | w100_InitExtMem(LCD_SHARP_QVGA); | 265 | w100_init_lcd(par); |
304 | w100fb_clear_screen(LCD_SHARP_QVGA, 0); | 266 | w100_set_dispregs(par); |
305 | lcdtg_lcd_change(LCD_SHARP_QVGA); | 267 | w100_update_enable(); |
306 | break; | 268 | |
307 | case LCD_SHARP_VGA: | 269 | calc_hsync(par); |
308 | w100fb_clear_screen(LCD_SHARP_QVGA, 0); | 270 | |
309 | writel(0xBFFFA000, remapped_regs + mmMC_EXT_MEM_LOCATION); | 271 | if (!par->blanked && tg && tg->change) |
310 | w100_InitExtMem(LCD_SHARP_VGA); | 272 | tg->change(par); |
311 | w100fb_clear_screen(LCD_SHARP_VGA, 0x200000); | ||
312 | w100_vsync(); | ||
313 | w100_init_sharp_lcd(LCD_SHARP_VGA); | ||
314 | if (rotation != 0) | ||
315 | w100_init_vga_rotation(rotation); | ||
316 | lcdtg_lcd_change(LCD_SHARP_VGA); | ||
317 | break; | ||
318 | } | ||
319 | } | 273 | } |
320 | 274 | ||
321 | /* | 275 | |
322 | * Set up the display for the fb subsystem | 276 | /* Select the smallest mode that allows the desired resolution to be |
277 | * displayed. If desired, the x and y parameters can be rounded up to | ||
278 | * match the selected mode. | ||
323 | */ | 279 | */ |
324 | static void w100fb_activate_var(struct fb_info *info) | 280 | static struct w100_mode *w100fb_get_mode(struct w100fb_par *par, unsigned int *x, unsigned int *y, int saveval) |
325 | { | 281 | { |
326 | u32 temp32; | 282 | struct w100_mode *mode = NULL; |
327 | struct w100fb_par *par=info->par; | 283 | struct w100_mode *modelist = par->mach->modelist; |
328 | struct fb_var_screeninfo *var = &info->var; | 284 | unsigned int best_x = 0xffffffff, best_y = 0xffffffff; |
285 | unsigned int i; | ||
286 | |||
287 | for (i = 0 ; i < par->mach->num_modes ; i++) { | ||
288 | if (modelist[i].xres >= *x && modelist[i].yres >= *y && | ||
289 | modelist[i].xres < best_x && modelist[i].yres < best_y) { | ||
290 | best_x = modelist[i].xres; | ||
291 | best_y = modelist[i].yres; | ||
292 | mode = &modelist[i]; | ||
293 | } else if(modelist[i].xres >= *y && modelist[i].yres >= *x && | ||
294 | modelist[i].xres < best_y && modelist[i].yres < best_x) { | ||
295 | best_x = modelist[i].yres; | ||
296 | best_y = modelist[i].xres; | ||
297 | mode = &modelist[i]; | ||
298 | } | ||
299 | } | ||
329 | 300 | ||
330 | /* Set the hardware to 565 */ | 301 | if (mode && saveval) { |
331 | temp32 = readl(remapped_regs + mmDISP_DEBUG2); | 302 | *x = best_x; |
332 | temp32 &= 0xff7fffff; | 303 | *y = best_y; |
333 | temp32 |= 0x00800000; | 304 | } |
334 | writel(temp32, remapped_regs + mmDISP_DEBUG2); | ||
335 | 305 | ||
336 | if (par->lcdMode == LCD_MODE_INIT) { | 306 | return mode; |
337 | w100_init_sharp_lcd(LCD_SHARP_VGA); | ||
338 | w100_init_vga_rotation(par->rotation_flag ? 270 : 90); | ||
339 | par->lcdMode = LCD_MODE_640; | ||
340 | lcdtg_hw_init(LCD_SHARP_VGA); | ||
341 | } else if (var->xres == 320 && var->yres == 240) { | ||
342 | if (par->lcdMode != LCD_MODE_320) { | ||
343 | w100fb_changeres(LCD_MODE_LANDSCAPE, LCD_SHARP_QVGA); | ||
344 | par->lcdMode = LCD_MODE_320; | ||
345 | } | ||
346 | } else if (var->xres == 240 && var->yres == 320) { | ||
347 | if (par->lcdMode != LCD_MODE_240) { | ||
348 | w100fb_changeres(LCD_MODE_PORTRAIT, LCD_SHARP_QVGA); | ||
349 | par->lcdMode = LCD_MODE_240; | ||
350 | } | ||
351 | } else if (var->xres == 640 && var->yres == 480) { | ||
352 | if (par->lcdMode != LCD_MODE_640) { | ||
353 | w100fb_changeres(LCD_MODE_LANDSCAPE, LCD_SHARP_VGA); | ||
354 | par->lcdMode = LCD_MODE_640; | ||
355 | } | ||
356 | } else if (var->xres == 480 && var->yres == 640) { | ||
357 | if (par->lcdMode != LCD_MODE_480) { | ||
358 | w100fb_changeres(LCD_MODE_PORTRAIT, LCD_SHARP_VGA); | ||
359 | par->lcdMode = LCD_MODE_480; | ||
360 | } | ||
361 | } else printk(KERN_ERR "W100FB: Resolution error!\n"); | ||
362 | } | 307 | } |
363 | 308 | ||
364 | 309 | ||
@@ -366,31 +311,19 @@ static void w100fb_activate_var(struct fb_info *info) | |||
366 | * w100fb_check_var(): | 311 | * w100fb_check_var(): |
367 | * Get the video params out of 'var'. If a value doesn't fit, round it up, | 312 | * Get the video params out of 'var'. If a value doesn't fit, round it up, |
368 | * if it's too big, return -EINVAL. | 313 | * if it's too big, return -EINVAL. |
369 | * | ||
370 | */ | 314 | */ |
371 | static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | 315 | static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) |
372 | { | 316 | { |
373 | if (var->xres < var->yres) { /* Portrait mode */ | 317 | struct w100fb_par *par=info->par; |
374 | if ((var->xres > 480) || (var->yres > 640)) { | 318 | |
375 | return -EINVAL; | 319 | if(!w100fb_get_mode(par, &var->xres, &var->yres, 1)) |
376 | } else if ((var->xres > 240) || (var->yres > 320)) { | 320 | return -EINVAL; |
377 | var->xres = 480; | 321 | |
378 | var->yres = 640; | 322 | if (par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (par->mach->mem->size+1))) |
379 | } else { | 323 | return -EINVAL; |
380 | var->xres = 240; | 324 | |
381 | var->yres = 320; | 325 | if (!par->mach->mem && ((var->xres*var->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1))) |
382 | } | 326 | return -EINVAL; |
383 | } else { /* Landscape mode */ | ||
384 | if ((var->xres > 640) || (var->yres > 480)) { | ||
385 | return -EINVAL; | ||
386 | } else if ((var->xres > 320) || (var->yres > 240)) { | ||
387 | var->xres = 640; | ||
388 | var->yres = 480; | ||
389 | } else { | ||
390 | var->xres = 320; | ||
391 | var->yres = 240; | ||
392 | } | ||
393 | } | ||
394 | 327 | ||
395 | var->xres_virtual = max(var->xres_virtual, var->xres); | 328 | var->xres_virtual = max(var->xres_virtual, var->xres); |
396 | var->yres_virtual = max(var->yres_virtual, var->yres); | 329 | var->yres_virtual = max(var->yres_virtual, var->yres); |
@@ -409,13 +342,11 @@ static int w100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
409 | var->transp.offset = var->transp.length = 0; | 342 | var->transp.offset = var->transp.length = 0; |
410 | 343 | ||
411 | var->nonstd = 0; | 344 | var->nonstd = 0; |
412 | |||
413 | var->height = -1; | 345 | var->height = -1; |
414 | var->width = -1; | 346 | var->width = -1; |
415 | var->vmode = FB_VMODE_NONINTERLACED; | 347 | var->vmode = FB_VMODE_NONINTERLACED; |
416 | |||
417 | var->sync = 0; | 348 | var->sync = 0; |
418 | var->pixclock = 0x04; /* 171521; */ | 349 | var->pixclock = 0x04; /* 171521; */ |
419 | 350 | ||
420 | return 0; | 351 | return 0; |
421 | } | 352 | } |
@@ -430,274 +361,286 @@ static int w100fb_set_par(struct fb_info *info) | |||
430 | { | 361 | { |
431 | struct w100fb_par *par=info->par; | 362 | struct w100fb_par *par=info->par; |
432 | 363 | ||
433 | par->xres = info->var.xres; | 364 | if (par->xres != info->var.xres || par->yres != info->var.yres) { |
434 | par->yres = info->var.yres; | 365 | par->xres = info->var.xres; |
435 | 366 | par->yres = info->var.yres; | |
436 | info->fix.visual = FB_VISUAL_TRUECOLOR; | 367 | par->mode = w100fb_get_mode(par, &par->xres, &par->yres, 0); |
437 | |||
438 | info->fix.ypanstep = 0; | ||
439 | info->fix.ywrapstep = 0; | ||
440 | 368 | ||
441 | if (par->blanking_flag) | 369 | info->fix.visual = FB_VISUAL_TRUECOLOR; |
442 | w100fb_clear_buffer(); | 370 | info->fix.ypanstep = 0; |
371 | info->fix.ywrapstep = 0; | ||
372 | info->fix.line_length = par->xres * BITS_PER_PIXEL / 8; | ||
443 | 373 | ||
444 | w100fb_activate_var(info); | 374 | if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) { |
375 | par->extmem_active = 1; | ||
376 | info->fix.smem_len = par->mach->mem->size+1; | ||
377 | } else { | ||
378 | par->extmem_active = 0; | ||
379 | info->fix.smem_len = MEM_INT_SIZE+1; | ||
380 | } | ||
445 | 381 | ||
446 | if (par->lcdMode == LCD_MODE_480) { | 382 | w100fb_activate_var(par); |
447 | info->fix.line_length = (480 * BITS_PER_PIXEL) / 8; | ||
448 | info->fix.smem_len = 0x200000; | ||
449 | } else if (par->lcdMode == LCD_MODE_320) { | ||
450 | info->fix.line_length = (320 * BITS_PER_PIXEL) / 8; | ||
451 | info->fix.smem_len = 0x60000; | ||
452 | } else if (par->lcdMode == LCD_MODE_240) { | ||
453 | info->fix.line_length = (240 * BITS_PER_PIXEL) / 8; | ||
454 | info->fix.smem_len = 0x60000; | ||
455 | } else if (par->lcdMode == LCD_MODE_INIT || par->lcdMode == LCD_MODE_640) { | ||
456 | info->fix.line_length = (640 * BITS_PER_PIXEL) / 8; | ||
457 | info->fix.smem_len = 0x200000; | ||
458 | } | 383 | } |
459 | |||
460 | return 0; | 384 | return 0; |
461 | } | 385 | } |
462 | 386 | ||
463 | 387 | ||
464 | /* | 388 | /* |
465 | * Frame buffer operations | 389 | * Frame buffer operations |
466 | */ | 390 | */ |
467 | static struct fb_ops w100fb_ops = { | 391 | static struct fb_ops w100fb_ops = { |
468 | .owner = THIS_MODULE, | 392 | .owner = THIS_MODULE, |
469 | .fb_check_var = w100fb_check_var, | 393 | .fb_check_var = w100fb_check_var, |
470 | .fb_set_par = w100fb_set_par, | 394 | .fb_set_par = w100fb_set_par, |
471 | .fb_setcolreg = w100fb_setcolreg, | 395 | .fb_setcolreg = w100fb_setcolreg, |
472 | .fb_blank = w100fb_blank, | 396 | .fb_blank = w100fb_blank, |
473 | .fb_fillrect = cfb_fillrect, | 397 | .fb_fillrect = cfb_fillrect, |
474 | .fb_copyarea = cfb_copyarea, | 398 | .fb_copyarea = cfb_copyarea, |
475 | .fb_imageblit = cfb_imageblit, | 399 | .fb_imageblit = cfb_imageblit, |
476 | .fb_cursor = soft_cursor, | 400 | .fb_cursor = soft_cursor, |
477 | }; | 401 | }; |
478 | 402 | ||
479 | 403 | #ifdef CONFIG_PM | |
480 | static void w100fb_clear_screen(u32 mode, long int offset) | 404 | static void w100fb_save_vidmem(struct w100fb_par *par) |
481 | { | 405 | { |
482 | int i, numPix = 0; | 406 | int memsize; |
483 | |||
484 | if (mode == LCD_SHARP_VGA) | ||
485 | numPix = 640 * 480; | ||
486 | else if (mode == LCD_SHARP_QVGA) | ||
487 | numPix = 320 * 240; | ||
488 | 407 | ||
489 | for (i = 0; i < numPix; i++) | 408 | if (par->extmem_active) { |
490 | writew(0xffff, remapped_fbuf + offset + (2*i)); | 409 | memsize=par->mach->mem->size; |
491 | } | 410 | par->saved_extmem = vmalloc(memsize); |
492 | 411 | if (par->saved_extmem) | |
493 | 412 | memcpy_fromio(par->saved_extmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize); | |
494 | /* Need to split up the buffers to stay within the limits of kmalloc */ | ||
495 | #define W100_BUF_NUM 6 | ||
496 | static uint32_t *gSaveImagePtr[W100_BUF_NUM] = { NULL }; | ||
497 | |||
498 | static void w100fb_save_buffer(void) | ||
499 | { | ||
500 | int i, j, bufsize; | ||
501 | |||
502 | bufsize=(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8) / W100_BUF_NUM; | ||
503 | for (i = 0; i < W100_BUF_NUM; i++) { | ||
504 | if (gSaveImagePtr[i] == NULL) | ||
505 | gSaveImagePtr[i] = kmalloc(bufsize, GFP_KERNEL); | ||
506 | if (gSaveImagePtr[i] == NULL) { | ||
507 | w100fb_clear_buffer(); | ||
508 | printk(KERN_WARNING "can't alloc pre-off image buffer %d\n", i); | ||
509 | break; | ||
510 | } | ||
511 | for (j = 0; j < bufsize/4; j++) | ||
512 | *(gSaveImagePtr[i] + j) = readl(remapped_fbuf + (bufsize*i) + j*4); | ||
513 | } | 413 | } |
414 | memsize=MEM_INT_SIZE; | ||
415 | par->saved_intmem = vmalloc(memsize); | ||
416 | if (par->saved_intmem && par->extmem_active) | ||
417 | memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), memsize); | ||
418 | else if (par->saved_intmem) | ||
419 | memcpy_fromio(par->saved_intmem, remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), memsize); | ||
514 | } | 420 | } |
515 | 421 | ||
516 | 422 | static void w100fb_restore_vidmem(struct w100fb_par *par) | |
517 | static void w100fb_restore_buffer(void) | ||
518 | { | 423 | { |
519 | int i, j, bufsize; | 424 | int memsize; |
520 | 425 | ||
521 | bufsize=(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8) / W100_BUF_NUM; | 426 | if (par->extmem_active && par->saved_extmem) { |
522 | for (i = 0; i < W100_BUF_NUM; i++) { | 427 | memsize=par->mach->mem->size; |
523 | if (gSaveImagePtr[i] == NULL) { | 428 | memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_extmem, memsize); |
524 | printk(KERN_WARNING "can't find pre-off image buffer %d\n", i); | 429 | vfree(par->saved_extmem); |
525 | w100fb_clear_buffer(); | ||
526 | break; | ||
527 | } | ||
528 | for (j = 0; j < (bufsize/4); j++) | ||
529 | writel(*(gSaveImagePtr[i] + j),remapped_fbuf + (bufsize*i) + (j*4)); | ||
530 | kfree(gSaveImagePtr[i]); | ||
531 | gSaveImagePtr[i] = NULL; | ||
532 | } | 430 | } |
533 | } | 431 | if (par->saved_intmem) { |
534 | 432 | memsize=MEM_INT_SIZE; | |
535 | 433 | if (par->extmem_active) | |
536 | static void w100fb_clear_buffer(void) | 434 | memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_INT_BASE_VALUE), par->saved_intmem, memsize); |
537 | { | 435 | else |
538 | int i; | 436 | memcpy_toio(remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE), par->saved_intmem, memsize); |
539 | for (i = 0; i < W100_BUF_NUM; i++) { | 437 | vfree(par->saved_intmem); |
540 | kfree(gSaveImagePtr[i]); | ||
541 | gSaveImagePtr[i] = NULL; | ||
542 | } | 438 | } |
543 | } | 439 | } |
544 | 440 | ||
545 | 441 | static int w100fb_suspend(struct device *dev, pm_message_t state, uint32_t level) | |
546 | #ifdef CONFIG_PM | ||
547 | static int w100fb_suspend(struct device *dev, pm_message_t state, u32 level) | ||
548 | { | 442 | { |
549 | if (level == SUSPEND_POWER_DOWN) { | 443 | if (level == SUSPEND_POWER_DOWN) { |
550 | struct fb_info *info = dev_get_drvdata(dev); | 444 | struct fb_info *info = dev_get_drvdata(dev); |
551 | struct w100fb_par *par=info->par; | 445 | struct w100fb_par *par=info->par; |
446 | struct w100_tg_info *tg = par->mach->tg; | ||
552 | 447 | ||
553 | w100fb_save_buffer(); | 448 | w100fb_save_vidmem(par); |
554 | lcdtg_suspend(); | 449 | if(tg && tg->suspend) |
450 | tg->suspend(par); | ||
555 | w100_suspend(W100_SUSPEND_ALL); | 451 | w100_suspend(W100_SUSPEND_ALL); |
556 | par->blanking_flag = 1; | 452 | par->blanked = 1; |
557 | } | 453 | } |
558 | return 0; | 454 | return 0; |
559 | } | 455 | } |
560 | 456 | ||
561 | static int w100fb_resume(struct device *dev, u32 level) | 457 | static int w100fb_resume(struct device *dev, uint32_t level) |
562 | { | 458 | { |
563 | if (level == RESUME_POWER_ON) { | 459 | if (level == RESUME_POWER_ON) { |
564 | struct fb_info *info = dev_get_drvdata(dev); | 460 | struct fb_info *info = dev_get_drvdata(dev); |
565 | struct w100fb_par *par=info->par; | 461 | struct w100fb_par *par=info->par; |
566 | 462 | struct w100_tg_info *tg = par->mach->tg; | |
567 | w100_resume(); | 463 | |
568 | w100fb_restore_buffer(); | 464 | w100_hw_init(par); |
569 | lcdtg_resume(); | 465 | w100fb_activate_var(par); |
570 | par->blanking_flag = 0; | 466 | w100fb_restore_vidmem(par); |
467 | if(tg && tg->resume) | ||
468 | tg->resume(par); | ||
469 | par->blanked = 0; | ||
571 | } | 470 | } |
572 | return 0; | 471 | return 0; |
573 | } | 472 | } |
574 | #else | 473 | #else |
575 | #define w100fb_suspend NULL | 474 | #define w100fb_suspend NULL |
576 | #define w100fb_resume NULL | 475 | #define w100fb_resume NULL |
577 | #endif | 476 | #endif |
578 | 477 | ||
579 | 478 | ||
580 | int __init w100fb_probe(struct device *dev) | 479 | int __init w100fb_probe(struct device *dev) |
581 | { | 480 | { |
481 | int err = -EIO; | ||
582 | struct w100fb_mach_info *inf; | 482 | struct w100fb_mach_info *inf; |
583 | struct fb_info *info; | 483 | struct fb_info *info = NULL; |
584 | struct w100fb_par *par; | 484 | struct w100fb_par *par; |
585 | struct platform_device *pdev = to_platform_device(dev); | 485 | struct platform_device *pdev = to_platform_device(dev); |
586 | struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 486 | struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
487 | unsigned int chip_id; | ||
587 | 488 | ||
588 | if (!mem) | 489 | if (!mem) |
589 | return -EINVAL; | 490 | return -EINVAL; |
590 | 491 | ||
591 | /* remap the areas we're going to use */ | 492 | /* Remap the chip base address */ |
592 | remapped_base = ioremap_nocache(mem->start+W100_CFG_BASE, W100_CFG_LEN); | 493 | remapped_base = ioremap_nocache(mem->start+W100_CFG_BASE, W100_CFG_LEN); |
593 | if (remapped_base == NULL) | 494 | if (remapped_base == NULL) |
594 | return -EIO; | 495 | goto out; |
595 | 496 | ||
497 | /* Map the register space */ | ||
596 | remapped_regs = ioremap_nocache(mem->start+W100_REG_BASE, W100_REG_LEN); | 498 | remapped_regs = ioremap_nocache(mem->start+W100_REG_BASE, W100_REG_LEN); |
597 | if (remapped_regs == NULL) { | 499 | if (remapped_regs == NULL) |
598 | iounmap(remapped_base); | 500 | goto out; |
599 | return -EIO; | 501 | |
502 | /* Identify the chip */ | ||
503 | printk("Found "); | ||
504 | chip_id = readl(remapped_regs + mmCHIP_ID); | ||
505 | switch(chip_id) { | ||
506 | case CHIP_ID_W100: printk("w100"); break; | ||
507 | case CHIP_ID_W3200: printk("w3200"); break; | ||
508 | case CHIP_ID_W3220: printk("w3220"); break; | ||
509 | default: | ||
510 | printk("Unknown imageon chip ID\n"); | ||
511 | err = -ENODEV; | ||
512 | goto out; | ||
600 | } | 513 | } |
514 | printk(" at 0x%08lx.\n", mem->start+W100_CFG_BASE); | ||
601 | 515 | ||
602 | remapped_fbuf = ioremap_nocache(mem->start+MEM_EXT_BASE_VALUE, REMAPPED_FB_LEN); | 516 | /* Remap the framebuffer */ |
603 | if (remapped_fbuf == NULL) { | 517 | remapped_fbuf = ioremap_nocache(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE); |
604 | iounmap(remapped_base); | 518 | if (remapped_fbuf == NULL) |
605 | iounmap(remapped_regs); | 519 | goto out; |
606 | return -EIO; | ||
607 | } | ||
608 | 520 | ||
609 | info=framebuffer_alloc(sizeof(struct w100fb_par), dev); | 521 | info=framebuffer_alloc(sizeof(struct w100fb_par), dev); |
610 | if (!info) { | 522 | if (!info) { |
611 | iounmap(remapped_base); | 523 | err = -ENOMEM; |
612 | iounmap(remapped_regs); | 524 | goto out; |
613 | iounmap(remapped_fbuf); | ||
614 | return -ENOMEM; | ||
615 | } | 525 | } |
616 | 526 | ||
617 | info->device=dev; | ||
618 | par = info->par; | 527 | par = info->par; |
619 | current_par=info->par; | ||
620 | dev_set_drvdata(dev, info); | 528 | dev_set_drvdata(dev, info); |
621 | 529 | ||
622 | inf = dev->platform_data; | 530 | inf = dev->platform_data; |
623 | par->phadadj = inf->phadadj; | 531 | par->chip_id = chip_id; |
624 | par->comadj = inf->comadj; | 532 | par->mach = inf; |
625 | par->fastsysclk_mode = 75; | 533 | par->fastpll_mode = 0; |
626 | par->lcdMode = LCD_MODE_INIT; | 534 | par->blanked = 0; |
627 | par->rotation_flag=0; | 535 | |
628 | par->blanking_flag=0; | 536 | par->pll_table=w100_get_xtal_table(inf->xtal_freq); |
629 | w100fb_ssp_send = inf->w100fb_ssp_send; | 537 | if (!par->pll_table) { |
630 | 538 | printk(KERN_ERR "No matching Xtal definition found\n"); | |
631 | w100_hw_init(); | 539 | err = -EINVAL; |
632 | w100_pwm_setup(); | 540 | goto out; |
541 | } | ||
633 | 542 | ||
634 | info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL); | 543 | info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL); |
635 | if (!info->pseudo_palette) { | 544 | if (!info->pseudo_palette) { |
636 | iounmap(remapped_base); | 545 | err = -ENOMEM; |
637 | iounmap(remapped_regs); | 546 | goto out; |
638 | iounmap(remapped_fbuf); | ||
639 | return -ENOMEM; | ||
640 | } | 547 | } |
641 | 548 | ||
642 | info->fbops = &w100fb_ops; | 549 | info->fbops = &w100fb_ops; |
643 | info->flags = FBINFO_DEFAULT; | 550 | info->flags = FBINFO_DEFAULT; |
644 | info->node = -1; | 551 | info->node = -1; |
645 | info->screen_base = remapped_fbuf; | 552 | info->screen_base = remapped_fbuf + (W100_FB_BASE-MEM_WINDOW_BASE); |
646 | info->screen_size = REMAPPED_FB_LEN; | 553 | info->screen_size = REMAPPED_FB_LEN; |
647 | 554 | ||
648 | info->var.xres = 640; | 555 | strcpy(info->fix.id, "w100fb"); |
556 | info->fix.type = FB_TYPE_PACKED_PIXELS; | ||
557 | info->fix.type_aux = 0; | ||
558 | info->fix.accel = FB_ACCEL_NONE; | ||
559 | info->fix.smem_start = mem->start+W100_FB_BASE; | ||
560 | info->fix.mmio_start = mem->start+W100_REG_BASE; | ||
561 | info->fix.mmio_len = W100_REG_LEN; | ||
562 | |||
563 | if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { | ||
564 | err = -ENOMEM; | ||
565 | goto out; | ||
566 | } | ||
567 | |||
568 | par->mode = &inf->modelist[0]; | ||
569 | if(inf->init_mode & INIT_MODE_ROTATED) { | ||
570 | info->var.xres = par->mode->yres; | ||
571 | info->var.yres = par->mode->xres; | ||
572 | } | ||
573 | else { | ||
574 | info->var.xres = par->mode->xres; | ||
575 | info->var.yres = par->mode->yres; | ||
576 | } | ||
577 | |||
578 | if(inf->init_mode &= INIT_MODE_FLIPPED) | ||
579 | par->flip = 1; | ||
580 | else | ||
581 | par->flip = 0; | ||
582 | |||
649 | info->var.xres_virtual = info->var.xres; | 583 | info->var.xres_virtual = info->var.xres; |
650 | info->var.yres = 480; | ||
651 | info->var.yres_virtual = info->var.yres; | 584 | info->var.yres_virtual = info->var.yres; |
652 | info->var.pixclock = 0x04; /* 171521; */ | 585 | info->var.pixclock = 0x04; /* 171521; */ |
653 | info->var.sync = 0; | 586 | info->var.sync = 0; |
654 | info->var.grayscale = 0; | 587 | info->var.grayscale = 0; |
655 | info->var.xoffset = info->var.yoffset = 0; | 588 | info->var.xoffset = info->var.yoffset = 0; |
656 | info->var.accel_flags = 0; | 589 | info->var.accel_flags = 0; |
657 | info->var.activate = FB_ACTIVATE_NOW; | 590 | info->var.activate = FB_ACTIVATE_NOW; |
658 | 591 | ||
659 | strcpy(info->fix.id, "w100fb"); | 592 | w100_hw_init(par); |
660 | info->fix.type = FB_TYPE_PACKED_PIXELS; | 593 | |
661 | info->fix.type_aux = 0; | 594 | if (w100fb_check_var(&info->var, info) < 0) { |
662 | info->fix.accel = FB_ACCEL_NONE; | 595 | err = -EINVAL; |
663 | info->fix.smem_start = mem->start+MEM_EXT_BASE_VALUE; | 596 | goto out; |
664 | info->fix.mmio_start = mem->start+W100_REG_BASE; | 597 | } |
665 | info->fix.mmio_len = W100_REG_LEN; | ||
666 | 598 | ||
667 | w100fb_check_var(&info->var, info); | ||
668 | w100fb_set_par(info); | 599 | w100fb_set_par(info); |
669 | 600 | ||
670 | if (register_framebuffer(info) < 0) { | 601 | if (register_framebuffer(info) < 0) { |
671 | kfree(info->pseudo_palette); | 602 | err = -EINVAL; |
672 | iounmap(remapped_base); | 603 | goto out; |
673 | iounmap(remapped_regs); | ||
674 | iounmap(remapped_fbuf); | ||
675 | return -EINVAL; | ||
676 | } | 604 | } |
677 | 605 | ||
678 | device_create_file(dev, &dev_attr_fastsysclk); | 606 | device_create_file(dev, &dev_attr_fastpllclk); |
679 | device_create_file(dev, &dev_attr_reg_read); | 607 | device_create_file(dev, &dev_attr_reg_read); |
680 | device_create_file(dev, &dev_attr_reg_write); | 608 | device_create_file(dev, &dev_attr_reg_write); |
681 | device_create_file(dev, &dev_attr_rotation); | 609 | device_create_file(dev, &dev_attr_flip); |
682 | 610 | ||
683 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); | 611 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); |
684 | return 0; | 612 | return 0; |
613 | out: | ||
614 | fb_dealloc_cmap(&info->cmap); | ||
615 | kfree(info->pseudo_palette); | ||
616 | if (remapped_fbuf != NULL) | ||
617 | iounmap(remapped_fbuf); | ||
618 | if (remapped_regs != NULL) | ||
619 | iounmap(remapped_regs); | ||
620 | if (remapped_base != NULL) | ||
621 | iounmap(remapped_base); | ||
622 | if (info) | ||
623 | framebuffer_release(info); | ||
624 | return err; | ||
685 | } | 625 | } |
686 | 626 | ||
687 | 627 | ||
688 | static int w100fb_remove(struct device *dev) | 628 | static int w100fb_remove(struct device *dev) |
689 | { | 629 | { |
690 | struct fb_info *info = dev_get_drvdata(dev); | 630 | struct fb_info *info = dev_get_drvdata(dev); |
631 | struct w100fb_par *par=info->par; | ||
691 | 632 | ||
692 | device_remove_file(dev, &dev_attr_fastsysclk); | 633 | device_remove_file(dev, &dev_attr_fastpllclk); |
693 | device_remove_file(dev, &dev_attr_reg_read); | 634 | device_remove_file(dev, &dev_attr_reg_read); |
694 | device_remove_file(dev, &dev_attr_reg_write); | 635 | device_remove_file(dev, &dev_attr_reg_write); |
695 | device_remove_file(dev, &dev_attr_rotation); | 636 | device_remove_file(dev, &dev_attr_flip); |
696 | 637 | ||
697 | unregister_framebuffer(info); | 638 | unregister_framebuffer(info); |
698 | 639 | ||
699 | w100fb_clear_buffer(); | 640 | vfree(par->saved_intmem); |
641 | vfree(par->saved_extmem); | ||
700 | kfree(info->pseudo_palette); | 642 | kfree(info->pseudo_palette); |
643 | fb_dealloc_cmap(&info->cmap); | ||
701 | 644 | ||
702 | iounmap(remapped_base); | 645 | iounmap(remapped_base); |
703 | iounmap(remapped_regs); | 646 | iounmap(remapped_regs); |
@@ -721,10 +664,54 @@ static void w100_soft_reset(void) | |||
721 | udelay(100); | 664 | udelay(100); |
722 | } | 665 | } |
723 | 666 | ||
667 | static void w100_update_disable(void) | ||
668 | { | ||
669 | union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl; | ||
670 | |||
671 | /* Prevent display updates */ | ||
672 | disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e; | ||
673 | disp_db_buf_wr_cntl.f.update_db_buf = 0; | ||
674 | disp_db_buf_wr_cntl.f.en_db_buf = 0; | ||
675 | writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL); | ||
676 | } | ||
677 | |||
678 | static void w100_update_enable(void) | ||
679 | { | ||
680 | union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl; | ||
681 | |||
682 | /* Enable display updates */ | ||
683 | disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e; | ||
684 | disp_db_buf_wr_cntl.f.update_db_buf = 1; | ||
685 | disp_db_buf_wr_cntl.f.en_db_buf = 1; | ||
686 | writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL); | ||
687 | } | ||
688 | |||
689 | unsigned long w100fb_gpio_read(int port) | ||
690 | { | ||
691 | unsigned long value; | ||
692 | |||
693 | if (port==W100_GPIO_PORT_A) | ||
694 | value = readl(remapped_regs + mmGPIO_DATA); | ||
695 | else | ||
696 | value = readl(remapped_regs + mmGPIO_DATA2); | ||
697 | |||
698 | return value; | ||
699 | } | ||
700 | |||
701 | void w100fb_gpio_write(int port, unsigned long value) | ||
702 | { | ||
703 | if (port==W100_GPIO_PORT_A) | ||
704 | value = writel(value, remapped_regs + mmGPIO_DATA); | ||
705 | else | ||
706 | value = writel(value, remapped_regs + mmGPIO_DATA2); | ||
707 | } | ||
708 | EXPORT_SYMBOL(w100fb_gpio_read); | ||
709 | EXPORT_SYMBOL(w100fb_gpio_write); | ||
710 | |||
724 | /* | 711 | /* |
725 | * Initialization of critical w100 hardware | 712 | * Initialization of critical w100 hardware |
726 | */ | 713 | */ |
727 | static void w100_hw_init(void) | 714 | static void w100_hw_init(struct w100fb_par *par) |
728 | { | 715 | { |
729 | u32 temp32; | 716 | u32 temp32; |
730 | union cif_cntl_u cif_cntl; | 717 | union cif_cntl_u cif_cntl; |
@@ -735,8 +722,8 @@ static void w100_hw_init(void) | |||
735 | union cpu_defaults_u cpu_default; | 722 | union cpu_defaults_u cpu_default; |
736 | union cif_write_dbg_u cif_write_dbg; | 723 | union cif_write_dbg_u cif_write_dbg; |
737 | union wrap_start_dir_u wrap_start_dir; | 724 | union wrap_start_dir_u wrap_start_dir; |
738 | union mc_ext_mem_location_u mc_ext_mem_loc; | ||
739 | union cif_io_u cif_io; | 725 | union cif_io_u cif_io; |
726 | struct w100_gpio_regs *gpio = par->mach->gpio; | ||
740 | 727 | ||
741 | w100_soft_reset(); | 728 | w100_soft_reset(); |
742 | 729 | ||
@@ -791,19 +778,6 @@ static void w100_hw_init(void) | |||
791 | cfgreg_base.f.cfgreg_base = W100_CFG_BASE; | 778 | cfgreg_base.f.cfgreg_base = W100_CFG_BASE; |
792 | writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE); | 779 | writel((u32) (cfgreg_base.val), remapped_regs + mmCFGREG_BASE); |
793 | 780 | ||
794 | /* This location is relative to internal w100 addresses */ | ||
795 | writel(0x15FF1000, remapped_regs + mmMC_FB_LOCATION); | ||
796 | |||
797 | mc_ext_mem_loc.val = defMC_EXT_MEM_LOCATION; | ||
798 | mc_ext_mem_loc.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8; | ||
799 | mc_ext_mem_loc.f.mc_ext_mem_top = MEM_EXT_TOP_VALUE >> 8; | ||
800 | writel((u32) (mc_ext_mem_loc.val), remapped_regs + mmMC_EXT_MEM_LOCATION); | ||
801 | |||
802 | if ((current_par->lcdMode == LCD_MODE_240) || (current_par->lcdMode == LCD_MODE_320)) | ||
803 | w100_InitExtMem(LCD_SHARP_QVGA); | ||
804 | else | ||
805 | w100_InitExtMem(LCD_SHARP_VGA); | ||
806 | |||
807 | wrap_start_dir.val = defWRAP_START_DIR; | 781 | wrap_start_dir.val = defWRAP_START_DIR; |
808 | wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1; | 782 | wrap_start_dir.f.start_addr = WRAP_BUF_BASE_VALUE >> 1; |
809 | writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR); | 783 | writel((u32) (wrap_start_dir.val), remapped_regs + mmWRAP_START_DIR); |
@@ -813,21 +787,24 @@ static void w100_hw_init(void) | |||
813 | writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR); | 787 | writel((u32) (wrap_top_dir.val), remapped_regs + mmWRAP_TOP_DIR); |
814 | 788 | ||
815 | writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL); | 789 | writel((u32) 0x2440, remapped_regs + mmRBBM_CNTL); |
816 | } | ||
817 | 790 | ||
791 | /* Set the hardware to 565 colour */ | ||
792 | temp32 = readl(remapped_regs + mmDISP_DEBUG2); | ||
793 | temp32 &= 0xff7fffff; | ||
794 | temp32 |= 0x00800000; | ||
795 | writel(temp32, remapped_regs + mmDISP_DEBUG2); | ||
818 | 796 | ||
819 | /* | 797 | /* Initialise the GPIO lines */ |
820 | * Types | 798 | if (gpio) { |
821 | */ | 799 | writel(gpio->init_data1, remapped_regs + mmGPIO_DATA); |
800 | writel(gpio->init_data2, remapped_regs + mmGPIO_DATA2); | ||
801 | writel(gpio->gpio_dir1, remapped_regs + mmGPIO_CNTL1); | ||
802 | writel(gpio->gpio_oe1, remapped_regs + mmGPIO_CNTL2); | ||
803 | writel(gpio->gpio_dir2, remapped_regs + mmGPIO_CNTL3); | ||
804 | writel(gpio->gpio_oe2, remapped_regs + mmGPIO_CNTL4); | ||
805 | } | ||
806 | } | ||
822 | 807 | ||
823 | struct pll_parm { | ||
824 | u16 freq; /* desired Fout for PLL */ | ||
825 | u8 M; | ||
826 | u8 N_int; | ||
827 | u8 N_fac; | ||
828 | u8 tfgoal; | ||
829 | u8 lock_time; | ||
830 | }; | ||
831 | 808 | ||
832 | struct power_state { | 809 | struct power_state { |
833 | union clk_pin_cntl_u clk_pin_cntl; | 810 | union clk_pin_cntl_u clk_pin_cntl; |
@@ -835,317 +812,275 @@ struct power_state { | |||
835 | union pll_cntl_u pll_cntl; | 812 | union pll_cntl_u pll_cntl; |
836 | union sclk_cntl_u sclk_cntl; | 813 | union sclk_cntl_u sclk_cntl; |
837 | union pclk_cntl_u pclk_cntl; | 814 | union pclk_cntl_u pclk_cntl; |
838 | union clk_test_cntl_u clk_test_cntl; | ||
839 | union pwrmgt_cntl_u pwrmgt_cntl; | 815 | union pwrmgt_cntl_u pwrmgt_cntl; |
840 | u32 freq; /* Fout for PLL calibration */ | 816 | int auto_mode; /* system clock auto changing? */ |
841 | u8 tf100; /* for pll calibration */ | ||
842 | u8 tf80; /* for pll calibration */ | ||
843 | u8 tf20; /* for pll calibration */ | ||
844 | u8 M; /* for pll calibration */ | ||
845 | u8 N_int; /* for pll calibration */ | ||
846 | u8 N_fac; /* for pll calibration */ | ||
847 | u8 lock_time; /* for pll calibration */ | ||
848 | u8 tfgoal; /* for pll calibration */ | ||
849 | u8 auto_mode; /* hardware auto switch? */ | ||
850 | u8 pwm_mode; /* 0 fast, 1 normal/slow */ | ||
851 | u16 fast_sclk; /* fast clk freq */ | ||
852 | u16 norm_sclk; /* slow clk freq */ | ||
853 | }; | 817 | }; |
854 | 818 | ||
855 | 819 | ||
856 | /* | ||
857 | * Global state variables | ||
858 | */ | ||
859 | |||
860 | static struct power_state w100_pwr_state; | 820 | static struct power_state w100_pwr_state; |
861 | 821 | ||
862 | /* This table is specific for 12.5MHz ref crystal. */ | 822 | /* The PLL Fout is determined by (XtalFreq/(M+1)) * ((N_int+1) + (N_fac/8)) */ |
863 | static struct pll_parm gPLLTable[] = { | 823 | |
864 | /*freq M N_int N_fac tfgoal lock_time */ | 824 | /* 12.5MHz Crystal PLL Table */ |
865 | { 50, 0, 1, 0, 0xE0, 56}, /* 50.00 MHz */ | 825 | static struct w100_pll_info xtal_12500000[] = { |
866 | { 75, 0, 5, 0, 0xDE, 37}, /* 75.00 MHz */ | 826 | /*freq M N_int N_fac tfgoal lock_time */ |
867 | {100, 0, 7, 0, 0xE0, 28}, /* 100.00 MHz */ | 827 | { 50, 0, 1, 0, 0xe0, 56}, /* 50.00 MHz */ |
868 | {125, 0, 9, 0, 0xE0, 22}, /* 125.00 MHz */ | 828 | { 75, 0, 5, 0, 0xde, 37}, /* 75.00 MHz */ |
869 | {150, 0, 11, 0, 0xE0, 17}, /* 150.00 MHz */ | 829 | {100, 0, 7, 0, 0xe0, 28}, /* 100.00 MHz */ |
870 | { 0, 0, 0, 0, 0, 0} /* Terminator */ | 830 | {125, 0, 9, 0, 0xe0, 22}, /* 125.00 MHz */ |
831 | {150, 0, 11, 0, 0xe0, 17}, /* 150.00 MHz */ | ||
832 | { 0, 0, 0, 0, 0, 0}, /* Terminator */ | ||
871 | }; | 833 | }; |
872 | 834 | ||
835 | /* 14.318MHz Crystal PLL Table */ | ||
836 | static struct w100_pll_info xtal_14318000[] = { | ||
837 | /*freq M N_int N_fac tfgoal lock_time */ | ||
838 | { 40, 4, 13, 0, 0xe0, 80}, /* tfgoal guessed */ | ||
839 | { 50, 1, 6, 0, 0xe0, 64}, /* 50.05 MHz */ | ||
840 | { 57, 2, 11, 0, 0xe0, 53}, /* tfgoal guessed */ | ||
841 | { 75, 0, 4, 3, 0xe0, 43}, /* 75.08 MHz */ | ||
842 | {100, 0, 6, 0, 0xe0, 32}, /* 100.10 MHz */ | ||
843 | { 0, 0, 0, 0, 0, 0}, | ||
844 | }; | ||
873 | 845 | ||
874 | static u8 w100_pll_get_testcount(u8 testclk_sel) | 846 | /* 16MHz Crystal PLL Table */ |
847 | static struct w100_pll_info xtal_16000000[] = { | ||
848 | /*freq M N_int N_fac tfgoal lock_time */ | ||
849 | { 72, 1, 8, 0, 0xe0, 48}, /* tfgoal guessed */ | ||
850 | { 95, 1, 10, 7, 0xe0, 38}, /* tfgoal guessed */ | ||
851 | { 96, 1, 11, 0, 0xe0, 36}, /* tfgoal guessed */ | ||
852 | { 0, 0, 0, 0, 0, 0}, | ||
853 | }; | ||
854 | |||
855 | static struct pll_entries { | ||
856 | int xtal_freq; | ||
857 | struct w100_pll_info *pll_table; | ||
858 | } w100_pll_tables[] = { | ||
859 | { 12500000, &xtal_12500000[0] }, | ||
860 | { 14318000, &xtal_14318000[0] }, | ||
861 | { 16000000, &xtal_16000000[0] }, | ||
862 | { 0 }, | ||
863 | }; | ||
864 | |||
865 | struct w100_pll_info *w100_get_xtal_table(unsigned int freq) | ||
875 | { | 866 | { |
867 | struct pll_entries *pll_entry = w100_pll_tables; | ||
868 | |||
869 | do { | ||
870 | if (freq == pll_entry->xtal_freq) | ||
871 | return pll_entry->pll_table; | ||
872 | pll_entry++; | ||
873 | } while (pll_entry->xtal_freq); | ||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | |||
878 | static unsigned int w100_get_testcount(unsigned int testclk_sel) | ||
879 | { | ||
880 | union clk_test_cntl_u clk_test_cntl; | ||
881 | |||
876 | udelay(5); | 882 | udelay(5); |
877 | 883 | ||
878 | w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x0; | 884 | /* Select the test clock source and reset */ |
879 | w100_pwr_state.clk_test_cntl.f.testclk_sel = testclk_sel; | 885 | clk_test_cntl.f.start_check_freq = 0x0; |
880 | w100_pwr_state.clk_test_cntl.f.tstcount_rst = 0x1; /*reset test count */ | 886 | clk_test_cntl.f.testclk_sel = testclk_sel; |
881 | writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL); | 887 | clk_test_cntl.f.tstcount_rst = 0x1; /* set reset */ |
882 | w100_pwr_state.clk_test_cntl.f.tstcount_rst = 0x0; | 888 | writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL); |
883 | writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL); | ||
884 | 889 | ||
885 | w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x1; | 890 | clk_test_cntl.f.tstcount_rst = 0x0; /* clear reset */ |
886 | writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL); | 891 | writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL); |
887 | 892 | ||
893 | /* Run clock test */ | ||
894 | clk_test_cntl.f.start_check_freq = 0x1; | ||
895 | writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL); | ||
896 | |||
897 | /* Give the test time to complete */ | ||
888 | udelay(20); | 898 | udelay(20); |
889 | 899 | ||
890 | w100_pwr_state.clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL); | 900 | /* Return the result */ |
891 | w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x0; | 901 | clk_test_cntl.val = readl(remapped_regs + mmCLK_TEST_CNTL); |
892 | writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL); | 902 | clk_test_cntl.f.start_check_freq = 0x0; |
903 | writel((u32) (clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL); | ||
893 | 904 | ||
894 | return w100_pwr_state.clk_test_cntl.f.test_count; | 905 | return clk_test_cntl.f.test_count; |
895 | } | 906 | } |
896 | 907 | ||
897 | 908 | ||
898 | static u8 w100_pll_adjust(void) | 909 | static int w100_pll_adjust(struct w100_pll_info *pll) |
899 | { | 910 | { |
911 | unsigned int tf80; | ||
912 | unsigned int tf20; | ||
913 | |||
914 | /* Initial Settings */ | ||
915 | w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0; /* power down */ | ||
916 | w100_pwr_state.pll_cntl.f.pll_reset = 0x0; /* not reset */ | ||
917 | w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1; /* Hi-Z */ | ||
918 | w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; /* VCO gain = 0 */ | ||
919 | w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0; /* VCO frequency range control = off */ | ||
920 | w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; /* current offset inside VCO = 0 */ | ||
921 | w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0; | ||
922 | |||
923 | /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V | ||
924 | * therefore, commented out the following lines | ||
925 | * tf80 meant tf100 | ||
926 | */ | ||
900 | do { | 927 | do { |
901 | /* Wai Ming 80 percent of VDD 1.3V gives 1.04V, minimum operating voltage is 1.08V | 928 | /* set VCO input = 0.8 * VDD */ |
902 | * therefore, commented out the following lines | ||
903 | * tf80 meant tf100 | ||
904 | * set VCO input = 0.8 * VDD | ||
905 | */ | ||
906 | w100_pwr_state.pll_cntl.f.pll_dactal = 0xd; | 929 | w100_pwr_state.pll_cntl.f.pll_dactal = 0xd; |
907 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | 930 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); |
908 | 931 | ||
909 | w100_pwr_state.tf80 = w100_pll_get_testcount(0x1); /* PLLCLK */ | 932 | tf80 = w100_get_testcount(TESTCLK_SRC_PLL); |
910 | if (w100_pwr_state.tf80 >= (w100_pwr_state.tfgoal)) { | 933 | if (tf80 >= (pll->tfgoal)) { |
911 | /* set VCO input = 0.2 * VDD */ | 934 | /* set VCO input = 0.2 * VDD */ |
912 | w100_pwr_state.pll_cntl.f.pll_dactal = 0x7; | 935 | w100_pwr_state.pll_cntl.f.pll_dactal = 0x7; |
913 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | 936 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); |
914 | 937 | ||
915 | w100_pwr_state.tf20 = w100_pll_get_testcount(0x1); /* PLLCLK */ | 938 | tf20 = w100_get_testcount(TESTCLK_SRC_PLL); |
916 | if (w100_pwr_state.tf20 <= (w100_pwr_state.tfgoal)) | 939 | if (tf20 <= (pll->tfgoal)) |
917 | return 1; // Success | 940 | return 1; /* Success */ |
918 | 941 | ||
919 | if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) && | 942 | if ((w100_pwr_state.pll_cntl.f.pll_vcofr == 0x0) && |
920 | ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) || | 943 | ((w100_pwr_state.pll_cntl.f.pll_pvg == 0x7) || |
921 | (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) { | 944 | (w100_pwr_state.pll_cntl.f.pll_ioffset == 0x0))) { |
922 | /* slow VCO config */ | 945 | /* slow VCO config */ |
923 | w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1; | 946 | w100_pwr_state.pll_cntl.f.pll_vcofr = 0x1; |
924 | w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; | 947 | w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; |
925 | w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; | 948 | w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; |
926 | writel((u32) (w100_pwr_state.pll_cntl.val), | ||
927 | remapped_regs + mmPLL_CNTL); | ||
928 | continue; | 949 | continue; |
929 | } | 950 | } |
930 | } | 951 | } |
931 | if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) { | 952 | if ((w100_pwr_state.pll_cntl.f.pll_ioffset) < 0x3) { |
932 | w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1; | 953 | w100_pwr_state.pll_cntl.f.pll_ioffset += 0x1; |
933 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | 954 | } else if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) { |
934 | continue; | ||
935 | } | ||
936 | if ((w100_pwr_state.pll_cntl.f.pll_pvg) < 0x7) { | ||
937 | w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; | 955 | w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; |
938 | w100_pwr_state.pll_cntl.f.pll_pvg += 0x1; | 956 | w100_pwr_state.pll_cntl.f.pll_pvg += 0x1; |
939 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | 957 | } else { |
940 | continue; | 958 | return 0; /* Error */ |
941 | } | 959 | } |
942 | return 0; // error | ||
943 | } while(1); | 960 | } while(1); |
944 | } | 961 | } |
945 | 962 | ||
946 | 963 | ||
947 | /* | 964 | /* |
948 | * w100_pll_calibration | 965 | * w100_pll_calibration |
949 | * freq = target frequency of the PLL | ||
950 | * (note: crystal = 14.3MHz) | ||
951 | */ | 966 | */ |
952 | static u8 w100_pll_calibration(u32 freq) | 967 | static int w100_pll_calibration(struct w100_pll_info *pll) |
953 | { | 968 | { |
954 | u8 status; | 969 | int status; |
955 | |||
956 | /* initial setting */ | ||
957 | w100_pwr_state.pll_cntl.f.pll_pwdn = 0x0; /* power down */ | ||
958 | w100_pwr_state.pll_cntl.f.pll_reset = 0x0; /* not reset */ | ||
959 | w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x1; /* Hi-Z */ | ||
960 | w100_pwr_state.pll_cntl.f.pll_pvg = 0x0; /* VCO gain = 0 */ | ||
961 | w100_pwr_state.pll_cntl.f.pll_vcofr = 0x0; /* VCO frequency range control = off */ | ||
962 | w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; /* current offset inside VCO = 0 */ | ||
963 | w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0; | ||
964 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | ||
965 | 970 | ||
966 | /* check for (tf80 >= tfgoal) && (tf20 =< tfgoal) */ | 971 | status = w100_pll_adjust(pll); |
967 | if ((w100_pwr_state.tf80 < w100_pwr_state.tfgoal) || (w100_pwr_state.tf20 > w100_pwr_state.tfgoal)) { | ||
968 | status=w100_pll_adjust(); | ||
969 | } | ||
970 | /* PLL Reset And Lock */ | ||
971 | 972 | ||
973 | /* PLL Reset And Lock */ | ||
972 | /* set VCO input = 0.5 * VDD */ | 974 | /* set VCO input = 0.5 * VDD */ |
973 | w100_pwr_state.pll_cntl.f.pll_dactal = 0xa; | 975 | w100_pwr_state.pll_cntl.f.pll_dactal = 0xa; |
974 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | 976 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); |
975 | 977 | ||
976 | /* reset time */ | 978 | udelay(1); /* reset time */ |
977 | udelay(1); | ||
978 | 979 | ||
979 | /* enable charge pump */ | 980 | /* enable charge pump */ |
980 | w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; /* normal */ | 981 | w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; /* normal */ |
981 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | 982 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); |
982 | 983 | ||
983 | /* set VCO input = Hi-Z */ | 984 | /* set VCO input = Hi-Z, disable DAC */ |
984 | /* disable DAC */ | ||
985 | w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; | 985 | w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; |
986 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | 986 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); |
987 | 987 | ||
988 | /* lock time */ | 988 | udelay(400); /* lock time */ |
989 | udelay(400); /* delay 400 us */ | ||
990 | 989 | ||
991 | /* PLL locked */ | 990 | /* PLL locked */ |
992 | 991 | ||
993 | w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x1; /* PLL clock */ | ||
994 | writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL); | ||
995 | |||
996 | w100_pwr_state.tf100 = w100_pll_get_testcount(0x1); /* PLLCLK */ | ||
997 | |||
998 | return status; | 992 | return status; |
999 | } | 993 | } |
1000 | 994 | ||
1001 | 995 | ||
1002 | static u8 w100_pll_set_clk(void) | 996 | static int w100_pll_set_clk(struct w100_pll_info *pll) |
1003 | { | 997 | { |
1004 | u8 status; | 998 | int status; |
1005 | 999 | ||
1006 | if (w100_pwr_state.auto_mode == 1) /* auto mode */ | 1000 | if (w100_pwr_state.auto_mode == 1) /* auto mode */ |
1007 | { | 1001 | { |
1008 | w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; /* disable fast to normal */ | 1002 | w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; /* disable fast to normal */ |
1009 | w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; /* disable normal to fast */ | 1003 | w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; /* disable normal to fast */ |
1010 | writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL); | 1004 | writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL); |
1011 | } | 1005 | } |
1012 | 1006 | ||
1013 | w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x0; /* crystal clock */ | 1007 | /* Set system clock source to XTAL whilst adjusting the PLL! */ |
1008 | w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL; | ||
1014 | writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL); | 1009 | writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL); |
1015 | 1010 | ||
1016 | w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = w100_pwr_state.M; | 1011 | w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = pll->M; |
1017 | w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = w100_pwr_state.N_int; | 1012 | w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = pll->N_int; |
1018 | w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = w100_pwr_state.N_fac; | 1013 | w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = pll->N_fac; |
1019 | w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = w100_pwr_state.lock_time; | 1014 | w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = pll->lock_time; |
1020 | writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV); | 1015 | writel((u32) (w100_pwr_state.pll_ref_fb_div.val), remapped_regs + mmPLL_REF_FB_DIV); |
1021 | 1016 | ||
1022 | w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0; | 1017 | w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0; |
1023 | writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL); | 1018 | writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL); |
1024 | 1019 | ||
1025 | status = w100_pll_calibration (w100_pwr_state.freq); | 1020 | status = w100_pll_calibration(pll); |
1026 | 1021 | ||
1027 | if (w100_pwr_state.auto_mode == 1) /* auto mode */ | 1022 | if (w100_pwr_state.auto_mode == 1) /* auto mode */ |
1028 | { | 1023 | { |
1029 | w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1; /* reenable fast to normal */ | 1024 | w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x1; /* reenable fast to normal */ |
1030 | w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1; /* reenable normal to fast */ | 1025 | w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x1; /* reenable normal to fast */ |
1031 | writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL); | 1026 | writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL); |
1032 | } | 1027 | } |
1033 | return status; | 1028 | return status; |
1034 | } | 1029 | } |
1035 | 1030 | ||
1036 | 1031 | /* freq = target frequency of the PLL */ | |
1037 | /* assume reference crystal clk is 12.5MHz, | 1032 | static int w100_set_pll_freq(struct w100fb_par *par, unsigned int freq) |
1038 | * and that doubling is not enabled. | ||
1039 | * | ||
1040 | * Freq = 12 == 12.5MHz. | ||
1041 | */ | ||
1042 | static u16 w100_set_slowsysclk(u16 freq) | ||
1043 | { | ||
1044 | if (w100_pwr_state.norm_sclk == freq) | ||
1045 | return freq; | ||
1046 | |||
1047 | if (w100_pwr_state.auto_mode == 1) /* auto mode */ | ||
1048 | return 0; | ||
1049 | |||
1050 | if (freq == 12) { | ||
1051 | w100_pwr_state.norm_sclk = freq; | ||
1052 | w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */ | ||
1053 | w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x0; /* crystal src */ | ||
1054 | |||
1055 | writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL); | ||
1056 | |||
1057 | w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x1; | ||
1058 | writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL); | ||
1059 | |||
1060 | w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x1; | ||
1061 | w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1; | ||
1062 | writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL); | ||
1063 | w100_pwr_state.pwm_mode = 1; /* normal mode */ | ||
1064 | return freq; | ||
1065 | } else | ||
1066 | return 0; | ||
1067 | } | ||
1068 | |||
1069 | |||
1070 | static u16 w100_set_fastsysclk(u16 freq) | ||
1071 | { | 1033 | { |
1072 | u16 pll_freq; | 1034 | struct w100_pll_info *pll = par->pll_table; |
1073 | int i; | ||
1074 | |||
1075 | while(1) { | ||
1076 | pll_freq = (u16) (freq * (w100_pwr_state.sclk_cntl.f.sclk_post_div_fast + 1)); | ||
1077 | i = 0; | ||
1078 | do { | ||
1079 | if (pll_freq == gPLLTable[i].freq) { | ||
1080 | w100_pwr_state.freq = gPLLTable[i].freq * 1000000; | ||
1081 | w100_pwr_state.M = gPLLTable[i].M; | ||
1082 | w100_pwr_state.N_int = gPLLTable[i].N_int; | ||
1083 | w100_pwr_state.N_fac = gPLLTable[i].N_fac; | ||
1084 | w100_pwr_state.tfgoal = gPLLTable[i].tfgoal; | ||
1085 | w100_pwr_state.lock_time = gPLLTable[i].lock_time; | ||
1086 | w100_pwr_state.tf20 = 0xff; /* set highest */ | ||
1087 | w100_pwr_state.tf80 = 0x00; /* set lowest */ | ||
1088 | |||
1089 | w100_pll_set_clk(); | ||
1090 | w100_pwr_state.pwm_mode = 0; /* fast mode */ | ||
1091 | w100_pwr_state.fast_sclk = freq; | ||
1092 | return freq; | ||
1093 | } | ||
1094 | i++; | ||
1095 | } while(gPLLTable[i].freq); | ||
1096 | 1035 | ||
1097 | if (w100_pwr_state.auto_mode == 1) | 1036 | do { |
1098 | break; | 1037 | if (freq == pll->freq) { |
1099 | 1038 | return w100_pll_set_clk(pll); | |
1100 | if (w100_pwr_state.sclk_cntl.f.sclk_post_div_fast == 0) | 1039 | } |
1101 | break; | 1040 | pll++; |
1102 | 1041 | } while(pll->freq); | |
1103 | w100_pwr_state.sclk_cntl.f.sclk_post_div_fast -= 1; | ||
1104 | writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL); | ||
1105 | } | ||
1106 | return 0; | 1042 | return 0; |
1107 | } | 1043 | } |
1108 | 1044 | ||
1109 | |||
1110 | /* Set up an initial state. Some values/fields set | 1045 | /* Set up an initial state. Some values/fields set |
1111 | here will be overwritten. */ | 1046 | here will be overwritten. */ |
1112 | static void w100_pwm_setup(void) | 1047 | static void w100_pwm_setup(struct w100fb_par *par) |
1113 | { | 1048 | { |
1114 | w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1; | 1049 | w100_pwr_state.clk_pin_cntl.f.osc_en = 0x1; |
1115 | w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f; | 1050 | w100_pwr_state.clk_pin_cntl.f.osc_gain = 0x1f; |
1116 | w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0; | 1051 | w100_pwr_state.clk_pin_cntl.f.dont_use_xtalin = 0x0; |
1117 | w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0; | 1052 | w100_pwr_state.clk_pin_cntl.f.xtalin_pm_en = 0x0; |
1118 | w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = 0x0; /* no freq doubling */ | 1053 | w100_pwr_state.clk_pin_cntl.f.xtalin_dbl_en = par->mach->xtal_dbl ? 1 : 0; |
1119 | w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0; | 1054 | w100_pwr_state.clk_pin_cntl.f.cg_debug = 0x0; |
1120 | writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL); | 1055 | writel((u32) (w100_pwr_state.clk_pin_cntl.val), remapped_regs + mmCLK_PIN_CNTL); |
1121 | 1056 | ||
1122 | w100_pwr_state.sclk_cntl.f.sclk_src_sel = 0x0; /* Crystal Clk */ | 1057 | w100_pwr_state.sclk_cntl.f.sclk_src_sel = CLK_SRC_XTAL; |
1123 | w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0; /* Pfast = 1 */ | 1058 | w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = 0x0; /* Pfast = 1 */ |
1124 | w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3; | 1059 | w100_pwr_state.sclk_cntl.f.sclk_clkon_hys = 0x3; |
1125 | w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */ | 1060 | w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = 0x0; /* Pslow = 1 */ |
1126 | w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0; | 1061 | w100_pwr_state.sclk_cntl.f.disp_cg_ok2switch_en = 0x0; |
1127 | w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0; /* Dynamic */ | 1062 | w100_pwr_state.sclk_cntl.f.sclk_force_reg = 0x0; /* Dynamic */ |
1128 | w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0; /* Dynamic */ | 1063 | w100_pwr_state.sclk_cntl.f.sclk_force_disp = 0x0; /* Dynamic */ |
1129 | w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0; /* Dynamic */ | 1064 | w100_pwr_state.sclk_cntl.f.sclk_force_mc = 0x0; /* Dynamic */ |
1130 | w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0; /* Dynamic */ | 1065 | w100_pwr_state.sclk_cntl.f.sclk_force_extmc = 0x0; /* Dynamic */ |
1131 | w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0; /* Dynamic */ | 1066 | w100_pwr_state.sclk_cntl.f.sclk_force_cp = 0x0; /* Dynamic */ |
1132 | w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0; /* Dynamic */ | 1067 | w100_pwr_state.sclk_cntl.f.sclk_force_e2 = 0x0; /* Dynamic */ |
1133 | w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0; /* Dynamic */ | 1068 | w100_pwr_state.sclk_cntl.f.sclk_force_e3 = 0x0; /* Dynamic */ |
1134 | w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0; /* Dynamic */ | 1069 | w100_pwr_state.sclk_cntl.f.sclk_force_idct = 0x0; /* Dynamic */ |
1135 | w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0; /* Dynamic */ | 1070 | w100_pwr_state.sclk_cntl.f.sclk_force_bist = 0x0; /* Dynamic */ |
1136 | w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0; | 1071 | w100_pwr_state.sclk_cntl.f.busy_extend_cp = 0x0; |
1137 | w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0; | 1072 | w100_pwr_state.sclk_cntl.f.busy_extend_e2 = 0x0; |
1138 | w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0; | 1073 | w100_pwr_state.sclk_cntl.f.busy_extend_e3 = 0x0; |
1139 | w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0; | 1074 | w100_pwr_state.sclk_cntl.f.busy_extend_idct = 0x0; |
1140 | writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL); | 1075 | writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL); |
1141 | 1076 | ||
1142 | w100_pwr_state.pclk_cntl.f.pclk_src_sel = 0x0; /* Crystal Clk */ | 1077 | w100_pwr_state.pclk_cntl.f.pclk_src_sel = CLK_SRC_XTAL; |
1143 | w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1; /* P = 2 */ | 1078 | w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x1; /* P = 2 */ |
1144 | w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0; /* Dynamic */ | 1079 | w100_pwr_state.pclk_cntl.f.pclk_force_disp = 0x0; /* Dynamic */ |
1145 | writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL); | 1080 | writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL); |
1146 | 1081 | ||
1147 | w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0; /* M = 1 */ | 1082 | w100_pwr_state.pll_ref_fb_div.f.pll_ref_div = 0x0; /* M = 1 */ |
1148 | w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0; /* N = 1.0 */ | 1083 | w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_int = 0x0; /* N = 1.0 */ |
1149 | w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0; | 1084 | w100_pwr_state.pll_ref_fb_div.f.pll_fb_div_frac = 0x0; |
1150 | w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5; | 1085 | w100_pwr_state.pll_ref_fb_div.f.pll_reset_time = 0x5; |
1151 | w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff; | 1086 | w100_pwr_state.pll_ref_fb_div.f.pll_lock_time = 0xff; |
@@ -1154,7 +1089,7 @@ static void w100_pwm_setup(void) | |||
1154 | w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1; | 1089 | w100_pwr_state.pll_cntl.f.pll_pwdn = 0x1; |
1155 | w100_pwr_state.pll_cntl.f.pll_reset = 0x1; | 1090 | w100_pwr_state.pll_cntl.f.pll_reset = 0x1; |
1156 | w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0; | 1091 | w100_pwr_state.pll_cntl.f.pll_pm_en = 0x0; |
1157 | w100_pwr_state.pll_cntl.f.pll_mode = 0x0; /* uses VCO clock */ | 1092 | w100_pwr_state.pll_cntl.f.pll_mode = 0x0; /* uses VCO clock */ |
1158 | w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0; | 1093 | w100_pwr_state.pll_cntl.f.pll_refclk_sel = 0x0; |
1159 | w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0; | 1094 | w100_pwr_state.pll_cntl.f.pll_fbclk_sel = 0x0; |
1160 | w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; | 1095 | w100_pwr_state.pll_cntl.f.pll_tcpoff = 0x0; |
@@ -1164,220 +1099,275 @@ static void w100_pwm_setup(void) | |||
1164 | w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; | 1099 | w100_pwr_state.pll_cntl.f.pll_ioffset = 0x0; |
1165 | w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0; | 1100 | w100_pwr_state.pll_cntl.f.pll_pecc_mode = 0x0; |
1166 | w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0; | 1101 | w100_pwr_state.pll_cntl.f.pll_pecc_scon = 0x0; |
1167 | w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; /* Hi-Z */ | 1102 | w100_pwr_state.pll_cntl.f.pll_dactal = 0x0; /* Hi-Z */ |
1168 | w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3; | 1103 | w100_pwr_state.pll_cntl.f.pll_cp_clip = 0x3; |
1169 | w100_pwr_state.pll_cntl.f.pll_conf = 0x2; | 1104 | w100_pwr_state.pll_cntl.f.pll_conf = 0x2; |
1170 | w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2; | 1105 | w100_pwr_state.pll_cntl.f.pll_mbctrl = 0x2; |
1171 | w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0; | 1106 | w100_pwr_state.pll_cntl.f.pll_ring_off = 0x0; |
1172 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); | 1107 | writel((u32) (w100_pwr_state.pll_cntl.val), remapped_regs + mmPLL_CNTL); |
1173 | 1108 | ||
1174 | w100_pwr_state.clk_test_cntl.f.testclk_sel = 0x1; /* PLLCLK (for testing) */ | ||
1175 | w100_pwr_state.clk_test_cntl.f.start_check_freq = 0x0; | ||
1176 | w100_pwr_state.clk_test_cntl.f.tstcount_rst = 0x0; | ||
1177 | writel((u32) (w100_pwr_state.clk_test_cntl.val), remapped_regs + mmCLK_TEST_CNTL); | ||
1178 | |||
1179 | w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0; | 1109 | w100_pwr_state.pwrmgt_cntl.f.pwm_enable = 0x0; |
1180 | w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1; /* normal mode (0, 1, 3) */ | 1110 | w100_pwr_state.pwrmgt_cntl.f.pwm_mode_req = 0x1; /* normal mode (0, 1, 3) */ |
1181 | w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0; | 1111 | w100_pwr_state.pwrmgt_cntl.f.pwm_wakeup_cond = 0x0; |
1182 | w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; | 1112 | w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_hw_en = 0x0; |
1183 | w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; | 1113 | w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_hw_en = 0x0; |
1184 | w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1; /* PM4,ENG */ | 1114 | w100_pwr_state.pwrmgt_cntl.f.pwm_fast_noml_cond = 0x1; /* PM4,ENG */ |
1185 | w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1; /* PM4,ENG */ | 1115 | w100_pwr_state.pwrmgt_cntl.f.pwm_noml_fast_cond = 0x1; /* PM4,ENG */ |
1186 | w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF; | 1116 | w100_pwr_state.pwrmgt_cntl.f.pwm_idle_timer = 0xFF; |
1187 | w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF; | 1117 | w100_pwr_state.pwrmgt_cntl.f.pwm_busy_timer = 0xFF; |
1188 | writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL); | 1118 | writel((u32) (w100_pwr_state.pwrmgt_cntl.val), remapped_regs + mmPWRMGT_CNTL); |
1189 | 1119 | ||
1190 | w100_pwr_state.auto_mode = 0; /* manual mode */ | 1120 | w100_pwr_state.auto_mode = 0; /* manual mode */ |
1191 | w100_pwr_state.pwm_mode = 1; /* normal mode (0, 1, 2) */ | ||
1192 | w100_pwr_state.freq = 50000000; /* 50 MHz */ | ||
1193 | w100_pwr_state.M = 3; /* M = 4 */ | ||
1194 | w100_pwr_state.N_int = 6; /* N = 7.0 */ | ||
1195 | w100_pwr_state.N_fac = 0; | ||
1196 | w100_pwr_state.tfgoal = 0xE0; | ||
1197 | w100_pwr_state.lock_time = 56; | ||
1198 | w100_pwr_state.tf20 = 0xff; /* set highest */ | ||
1199 | w100_pwr_state.tf80 = 0x00; /* set lowest */ | ||
1200 | w100_pwr_state.tf100 = 0x00; /* set lowest */ | ||
1201 | w100_pwr_state.fast_sclk = 50; /* 50.0 MHz */ | ||
1202 | w100_pwr_state.norm_sclk = 12; /* 12.5 MHz */ | ||
1203 | } | 1121 | } |
1204 | 1122 | ||
1205 | 1123 | ||
1206 | static void w100_init_sharp_lcd(u32 mode) | 1124 | /* |
1125 | * Setup the w100 clocks for the specified mode | ||
1126 | */ | ||
1127 | static void w100_init_clocks(struct w100fb_par *par) | ||
1207 | { | 1128 | { |
1208 | u32 temp32; | 1129 | struct w100_mode *mode = par->mode; |
1209 | union disp_db_buf_cntl_wr_u disp_db_buf_wr_cntl; | ||
1210 | 1130 | ||
1211 | /* Prevent display updates */ | 1131 | if (mode->pixclk_src == CLK_SRC_PLL || mode->sysclk_src == CLK_SRC_PLL) |
1212 | disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e; | 1132 | w100_set_pll_freq(par, (par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq); |
1213 | disp_db_buf_wr_cntl.f.update_db_buf = 0; | ||
1214 | disp_db_buf_wr_cntl.f.en_db_buf = 0; | ||
1215 | writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL); | ||
1216 | 1133 | ||
1217 | switch(mode) { | 1134 | w100_pwr_state.sclk_cntl.f.sclk_src_sel = mode->sysclk_src; |
1218 | case LCD_SHARP_QVGA: | 1135 | w100_pwr_state.sclk_cntl.f.sclk_post_div_fast = mode->sysclk_divider; |
1219 | w100_set_slowsysclk(12); /* use crystal -- 12.5MHz */ | 1136 | w100_pwr_state.sclk_cntl.f.sclk_post_div_slow = mode->sysclk_divider; |
1220 | /* not use PLL */ | 1137 | writel((u32) (w100_pwr_state.sclk_cntl.val), remapped_regs + mmSCLK_CNTL); |
1221 | 1138 | } | |
1222 | writel(0x7FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION); | 1139 | |
1223 | writel(0x85FF8000, remapped_regs + mmMC_FB_LOCATION); | 1140 | static void w100_init_lcd(struct w100fb_par *par) |
1224 | writel(0x00000003, remapped_regs + mmLCD_FORMAT); | 1141 | { |
1225 | writel(0x00CF1C06, remapped_regs + mmGRAPHIC_CTRL); | 1142 | u32 temp32; |
1226 | writel(0x01410145, remapped_regs + mmCRTC_TOTAL); | 1143 | struct w100_mode *mode = par->mode; |
1227 | writel(0x01170027, remapped_regs + mmACTIVE_H_DISP); | 1144 | struct w100_gen_regs *regs = par->mach->regs; |
1228 | writel(0x01410001, remapped_regs + mmACTIVE_V_DISP); | 1145 | union active_h_disp_u active_h_disp; |
1229 | writel(0x01170027, remapped_regs + mmGRAPHIC_H_DISP); | 1146 | union active_v_disp_u active_v_disp; |
1230 | writel(0x01410001, remapped_regs + mmGRAPHIC_V_DISP); | 1147 | union graphic_h_disp_u graphic_h_disp; |
1231 | writel(0x81170027, remapped_regs + mmCRTC_SS); | 1148 | union graphic_v_disp_u graphic_v_disp; |
1232 | writel(0xA0140000, remapped_regs + mmCRTC_LS); | 1149 | union crtc_total_u crtc_total; |
1233 | writel(0x00400008, remapped_regs + mmCRTC_REV); | 1150 | |
1234 | writel(0xA0000000, remapped_regs + mmCRTC_DCLK); | 1151 | /* w3200 doesnt like undefined bits being set so zero register values first */ |
1235 | writel(0xC0140014, remapped_regs + mmCRTC_GS); | 1152 | |
1236 | writel(0x00010141, remapped_regs + mmCRTC_VPOS_GS); | 1153 | active_h_disp.val = 0; |
1237 | writel(0x8015010F, remapped_regs + mmCRTC_GCLK); | 1154 | active_h_disp.f.active_h_start=mode->left_margin; |
1238 | writel(0x80100110, remapped_regs + mmCRTC_GOE); | 1155 | active_h_disp.f.active_h_end=mode->left_margin + mode->xres; |
1239 | writel(0x00000000, remapped_regs + mmCRTC_FRAME); | 1156 | writel(active_h_disp.val, remapped_regs + mmACTIVE_H_DISP); |
1240 | writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS); | 1157 | |
1241 | writel(0x01CC0000, remapped_regs + mmLCDD_CNTL1); | 1158 | active_v_disp.val = 0; |
1242 | writel(0x0003FFFF, remapped_regs + mmLCDD_CNTL2); | 1159 | active_v_disp.f.active_v_start=mode->upper_margin; |
1243 | writel(0x00FFFF0D, remapped_regs + mmGENLCD_CNTL1); | 1160 | active_v_disp.f.active_v_end=mode->upper_margin + mode->yres; |
1244 | writel(0x003F3003, remapped_regs + mmGENLCD_CNTL2); | 1161 | writel(active_v_disp.val, remapped_regs + mmACTIVE_V_DISP); |
1245 | writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT); | 1162 | |
1246 | writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR); | 1163 | graphic_h_disp.val = 0; |
1247 | writel(0x000102aa, remapped_regs + mmGENLCD_CNTL3); | 1164 | graphic_h_disp.f.graphic_h_start=mode->left_margin; |
1248 | writel(0x00800000, remapped_regs + mmGRAPHIC_OFFSET); | 1165 | graphic_h_disp.f.graphic_h_end=mode->left_margin + mode->xres; |
1249 | writel(0x000001e0, remapped_regs + mmGRAPHIC_PITCH); | 1166 | writel(graphic_h_disp.val, remapped_regs + mmGRAPHIC_H_DISP); |
1250 | writel(0x000000bf, remapped_regs + mmGPIO_DATA); | 1167 | |
1251 | writel(0x03c0feff, remapped_regs + mmGPIO_CNTL2); | 1168 | graphic_v_disp.val = 0; |
1252 | writel(0x00000000, remapped_regs + mmGPIO_CNTL1); | 1169 | graphic_v_disp.f.graphic_v_start=mode->upper_margin; |
1253 | writel(0x41060010, remapped_regs + mmCRTC_PS1_ACTIVE); | 1170 | graphic_v_disp.f.graphic_v_end=mode->upper_margin + mode->yres; |
1254 | break; | 1171 | writel(graphic_v_disp.val, remapped_regs + mmGRAPHIC_V_DISP); |
1255 | case LCD_SHARP_VGA: | 1172 | |
1256 | w100_set_slowsysclk(12); /* use crystal -- 12.5MHz */ | 1173 | crtc_total.val = 0; |
1257 | w100_set_fastsysclk(current_par->fastsysclk_mode); /* use PLL -- 75.0MHz */ | 1174 | crtc_total.f.crtc_h_total=mode->left_margin + mode->xres + mode->right_margin; |
1258 | w100_pwr_state.pclk_cntl.f.pclk_src_sel = 0x1; | 1175 | crtc_total.f.crtc_v_total=mode->upper_margin + mode->yres + mode->lower_margin; |
1259 | w100_pwr_state.pclk_cntl.f.pclk_post_div = 0x2; | 1176 | writel(crtc_total.val, remapped_regs + mmCRTC_TOTAL); |
1260 | writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL); | 1177 | |
1261 | writel(0x15FF1000, remapped_regs + mmMC_FB_LOCATION); | 1178 | writel(mode->crtc_ss, remapped_regs + mmCRTC_SS); |
1262 | writel(0x9FFF8000, remapped_regs + mmMC_EXT_MEM_LOCATION); | 1179 | writel(mode->crtc_ls, remapped_regs + mmCRTC_LS); |
1263 | writel(0x00000003, remapped_regs + mmLCD_FORMAT); | 1180 | writel(mode->crtc_gs, remapped_regs + mmCRTC_GS); |
1264 | writel(0x00DE1D66, remapped_regs + mmGRAPHIC_CTRL); | 1181 | writel(mode->crtc_vpos_gs, remapped_regs + mmCRTC_VPOS_GS); |
1265 | 1182 | writel(mode->crtc_rev, remapped_regs + mmCRTC_REV); | |
1266 | writel(0x0283028B, remapped_regs + mmCRTC_TOTAL); | 1183 | writel(mode->crtc_dclk, remapped_regs + mmCRTC_DCLK); |
1267 | writel(0x02360056, remapped_regs + mmACTIVE_H_DISP); | 1184 | writel(mode->crtc_gclk, remapped_regs + mmCRTC_GCLK); |
1268 | writel(0x02830003, remapped_regs + mmACTIVE_V_DISP); | 1185 | writel(mode->crtc_goe, remapped_regs + mmCRTC_GOE); |
1269 | writel(0x02360056, remapped_regs + mmGRAPHIC_H_DISP); | 1186 | writel(mode->crtc_ps1_active, remapped_regs + mmCRTC_PS1_ACTIVE); |
1270 | writel(0x02830003, remapped_regs + mmGRAPHIC_V_DISP); | 1187 | |
1271 | writel(0x82360056, remapped_regs + mmCRTC_SS); | 1188 | writel(regs->lcd_format, remapped_regs + mmLCD_FORMAT); |
1272 | writel(0xA0280000, remapped_regs + mmCRTC_LS); | 1189 | writel(regs->lcdd_cntl1, remapped_regs + mmLCDD_CNTL1); |
1273 | writel(0x00400008, remapped_regs + mmCRTC_REV); | 1190 | writel(regs->lcdd_cntl2, remapped_regs + mmLCDD_CNTL2); |
1274 | writel(0xA0000000, remapped_regs + mmCRTC_DCLK); | 1191 | writel(regs->genlcd_cntl1, remapped_regs + mmGENLCD_CNTL1); |
1275 | writel(0x80280028, remapped_regs + mmCRTC_GS); | 1192 | writel(regs->genlcd_cntl2, remapped_regs + mmGENLCD_CNTL2); |
1276 | writel(0x02830002, remapped_regs + mmCRTC_VPOS_GS); | 1193 | writel(regs->genlcd_cntl3, remapped_regs + mmGENLCD_CNTL3); |
1277 | writel(0x8015010F, remapped_regs + mmCRTC_GCLK); | 1194 | |
1278 | writel(0x80100110, remapped_regs + mmCRTC_GOE); | 1195 | writel(0x00000000, remapped_regs + mmCRTC_FRAME); |
1279 | writel(0x00000000, remapped_regs + mmCRTC_FRAME); | 1196 | writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS); |
1280 | writel(0x00000000, remapped_regs + mmCRTC_FRAME_VPOS); | 1197 | writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT); |
1281 | writel(0x01CC0000, remapped_regs + mmLCDD_CNTL1); | 1198 | writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR); |
1282 | writel(0x0003FFFF, remapped_regs + mmLCDD_CNTL2); | ||
1283 | writel(0x00FFFF0D, remapped_regs + mmGENLCD_CNTL1); | ||
1284 | writel(0x003F3003, remapped_regs + mmGENLCD_CNTL2); | ||
1285 | writel(0x00000000, remapped_regs + mmCRTC_DEFAULT_COUNT); | ||
1286 | writel(0x0000FF00, remapped_regs + mmLCD_BACKGROUND_COLOR); | ||
1287 | writel(0x000102aa, remapped_regs + mmGENLCD_CNTL3); | ||
1288 | writel(0x00800000, remapped_regs + mmGRAPHIC_OFFSET); | ||
1289 | writel(0x000003C0, remapped_regs + mmGRAPHIC_PITCH); | ||
1290 | writel(0x000000bf, remapped_regs + mmGPIO_DATA); | ||
1291 | writel(0x03c0feff, remapped_regs + mmGPIO_CNTL2); | ||
1292 | writel(0x00000000, remapped_regs + mmGPIO_CNTL1); | ||
1293 | writel(0x41060010, remapped_regs + mmCRTC_PS1_ACTIVE); | ||
1294 | break; | ||
1295 | default: | ||
1296 | break; | ||
1297 | } | ||
1298 | 1199 | ||
1299 | /* Hack for overlay in ext memory */ | 1200 | /* Hack for overlay in ext memory */ |
1300 | temp32 = readl(remapped_regs + mmDISP_DEBUG2); | 1201 | temp32 = readl(remapped_regs + mmDISP_DEBUG2); |
1301 | temp32 |= 0xc0000000; | 1202 | temp32 |= 0xc0000000; |
1302 | writel(temp32, remapped_regs + mmDISP_DEBUG2); | 1203 | writel(temp32, remapped_regs + mmDISP_DEBUG2); |
1303 | |||
1304 | /* Re-enable display updates */ | ||
1305 | disp_db_buf_wr_cntl.f.db_buf_cntl = 0x1e; | ||
1306 | disp_db_buf_wr_cntl.f.update_db_buf = 1; | ||
1307 | disp_db_buf_wr_cntl.f.en_db_buf = 1; | ||
1308 | writel((u32) (disp_db_buf_wr_cntl.val), remapped_regs + mmDISP_DB_BUF_CNTL); | ||
1309 | } | 1204 | } |
1310 | 1205 | ||
1311 | 1206 | ||
1312 | static void w100_set_vga_rotation_regs(u16 divider, unsigned long ctrl, unsigned long offset, unsigned long pitch) | 1207 | static void w100_setup_memory(struct w100fb_par *par) |
1313 | { | 1208 | { |
1314 | w100_pwr_state.pclk_cntl.f.pclk_src_sel = 0x1; | 1209 | union mc_ext_mem_location_u extmem_location; |
1315 | w100_pwr_state.pclk_cntl.f.pclk_post_div = divider; | 1210 | union mc_fb_location_u intmem_location; |
1316 | writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL); | 1211 | struct w100_mem_info *mem = par->mach->mem; |
1212 | struct w100_bm_mem_info *bm_mem = par->mach->bm_mem; | ||
1317 | 1213 | ||
1318 | writel(ctrl, remapped_regs + mmGRAPHIC_CTRL); | 1214 | if (!par->extmem_active) { |
1319 | writel(offset, remapped_regs + mmGRAPHIC_OFFSET); | 1215 | w100_suspend(W100_SUSPEND_EXTMEM); |
1320 | writel(pitch, remapped_regs + mmGRAPHIC_PITCH); | ||
1321 | 1216 | ||
1322 | /* Re-enable display updates */ | 1217 | /* Map Internal Memory at FB Base */ |
1323 | writel(0x0000007b, remapped_regs + mmDISP_DB_BUF_CNTL); | 1218 | intmem_location.f.mc_fb_start = W100_FB_BASE >> 8; |
1324 | } | 1219 | intmem_location.f.mc_fb_top = (W100_FB_BASE+MEM_INT_SIZE) >> 8; |
1220 | writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION); | ||
1325 | 1221 | ||
1222 | /* Unmap External Memory - value is *probably* irrelevant but may have meaning | ||
1223 | to acceleration libraries */ | ||
1224 | extmem_location.f.mc_ext_mem_start = MEM_EXT_BASE_VALUE >> 8; | ||
1225 | extmem_location.f.mc_ext_mem_top = (MEM_EXT_BASE_VALUE-1) >> 8; | ||
1226 | writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION); | ||
1227 | } else { | ||
1228 | /* Map Internal Memory to its default location */ | ||
1229 | intmem_location.f.mc_fb_start = MEM_INT_BASE_VALUE >> 8; | ||
1230 | intmem_location.f.mc_fb_top = (MEM_INT_BASE_VALUE+MEM_INT_SIZE) >> 8; | ||
1231 | writel((u32) (intmem_location.val), remapped_regs + mmMC_FB_LOCATION); | ||
1326 | 1232 | ||
1327 | static void w100_init_vga_rotation(u16 deg) | 1233 | /* Map External Memory at FB Base */ |
1328 | { | 1234 | extmem_location.f.mc_ext_mem_start = W100_FB_BASE >> 8; |
1329 | switch(deg) { | 1235 | extmem_location.f.mc_ext_mem_top = (W100_FB_BASE+par->mach->mem->size) >> 8; |
1330 | case 0: | 1236 | writel((u32) (extmem_location.val), remapped_regs + mmMC_EXT_MEM_LOCATION); |
1331 | w100_set_vga_rotation_regs(0x02, 0x00DE1D66, 0x00800000, 0x000003c0); | 1237 | |
1332 | break; | 1238 | writel(0x00007800, remapped_regs + mmMC_BIST_CTRL); |
1333 | case 90: | 1239 | writel(mem->ext_cntl, remapped_regs + mmMEM_EXT_CNTL); |
1334 | w100_set_vga_rotation_regs(0x06, 0x00DE1D0e, 0x00895b00, 0x00000500); | 1240 | writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG); |
1335 | break; | 1241 | udelay(100); |
1336 | case 180: | 1242 | writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG); |
1337 | w100_set_vga_rotation_regs(0x02, 0x00DE1D7e, 0x00895ffc, 0x000003c0); | 1243 | udelay(100); |
1338 | break; | 1244 | writel(mem->sdram_mode_reg, remapped_regs + mmMEM_SDRAM_MODE_REG); |
1339 | case 270: | 1245 | udelay(100); |
1340 | w100_set_vga_rotation_regs(0x06, 0x00DE1D16, 0x008004fc, 0x00000500); | 1246 | writel(mem->ext_timing_cntl, remapped_regs + mmMEM_EXT_TIMING_CNTL); |
1341 | break; | 1247 | writel(mem->io_cntl, remapped_regs + mmMEM_IO_CNTL); |
1342 | default: | 1248 | if (bm_mem) { |
1343 | /* not-support */ | 1249 | writel(bm_mem->ext_mem_bw, remapped_regs + mmBM_EXT_MEM_BANDWIDTH); |
1344 | break; | 1250 | writel(bm_mem->offset, remapped_regs + mmBM_OFFSET); |
1251 | writel(bm_mem->ext_timing_ctl, remapped_regs + mmBM_MEM_EXT_TIMING_CNTL); | ||
1252 | writel(bm_mem->ext_cntl, remapped_regs + mmBM_MEM_EXT_CNTL); | ||
1253 | writel(bm_mem->mode_reg, remapped_regs + mmBM_MEM_MODE_REG); | ||
1254 | writel(bm_mem->io_cntl, remapped_regs + mmBM_MEM_IO_CNTL); | ||
1255 | writel(bm_mem->config, remapped_regs + mmBM_CONFIG); | ||
1256 | } | ||
1345 | } | 1257 | } |
1346 | } | 1258 | } |
1347 | 1259 | ||
1348 | 1260 | static void w100_set_dispregs(struct w100fb_par *par) | |
1349 | static void w100_set_qvga_rotation_regs(unsigned long ctrl, unsigned long offset, unsigned long pitch) | ||
1350 | { | 1261 | { |
1351 | writel(ctrl, remapped_regs + mmGRAPHIC_CTRL); | 1262 | unsigned long rot=0, divider, offset=0; |
1352 | writel(offset, remapped_regs + mmGRAPHIC_OFFSET); | 1263 | union graphic_ctrl_u graphic_ctrl; |
1353 | writel(pitch, remapped_regs + mmGRAPHIC_PITCH); | 1264 | |
1265 | /* See if the mode has been rotated */ | ||
1266 | if (par->xres == par->mode->xres) { | ||
1267 | if (par->flip) { | ||
1268 | rot=3; /* 180 degree */ | ||
1269 | offset=(par->xres * par->yres) - 1; | ||
1270 | } /* else 0 degree */ | ||
1271 | divider = par->mode->pixclk_divider; | ||
1272 | } else { | ||
1273 | if (par->flip) { | ||
1274 | rot=2; /* 270 degree */ | ||
1275 | offset=par->xres - 1; | ||
1276 | } else { | ||
1277 | rot=1; /* 90 degree */ | ||
1278 | offset=par->xres * (par->yres - 1); | ||
1279 | } | ||
1280 | divider = par->mode->pixclk_divider_rotated; | ||
1281 | } | ||
1354 | 1282 | ||
1355 | /* Re-enable display updates */ | 1283 | graphic_ctrl.val = 0; /* w32xx doesn't like undefined bits */ |
1356 | writel(0x0000007b, remapped_regs + mmDISP_DB_BUF_CNTL); | 1284 | switch (par->chip_id) { |
1285 | case CHIP_ID_W100: | ||
1286 | graphic_ctrl.f_w100.color_depth=6; | ||
1287 | graphic_ctrl.f_w100.en_crtc=1; | ||
1288 | graphic_ctrl.f_w100.en_graphic_req=1; | ||
1289 | graphic_ctrl.f_w100.en_graphic_crtc=1; | ||
1290 | graphic_ctrl.f_w100.lcd_pclk_on=1; | ||
1291 | graphic_ctrl.f_w100.lcd_sclk_on=1; | ||
1292 | graphic_ctrl.f_w100.low_power_on=0; | ||
1293 | graphic_ctrl.f_w100.req_freq=0; | ||
1294 | graphic_ctrl.f_w100.portrait_mode=rot; | ||
1295 | |||
1296 | /* Zaurus needs this */ | ||
1297 | switch(par->xres) { | ||
1298 | case 240: | ||
1299 | case 320: | ||
1300 | default: | ||
1301 | graphic_ctrl.f_w100.total_req_graphic=0xa0; | ||
1302 | break; | ||
1303 | case 480: | ||
1304 | case 640: | ||
1305 | switch(rot) { | ||
1306 | case 0: /* 0 */ | ||
1307 | case 3: /* 180 */ | ||
1308 | graphic_ctrl.f_w100.low_power_on=1; | ||
1309 | graphic_ctrl.f_w100.req_freq=5; | ||
1310 | break; | ||
1311 | case 1: /* 90 */ | ||
1312 | case 2: /* 270 */ | ||
1313 | graphic_ctrl.f_w100.req_freq=4; | ||
1314 | break; | ||
1315 | default: | ||
1316 | break; | ||
1317 | } | ||
1318 | graphic_ctrl.f_w100.total_req_graphic=0xf0; | ||
1319 | break; | ||
1320 | } | ||
1321 | break; | ||
1322 | case CHIP_ID_W3200: | ||
1323 | case CHIP_ID_W3220: | ||
1324 | graphic_ctrl.f_w32xx.color_depth=6; | ||
1325 | graphic_ctrl.f_w32xx.en_crtc=1; | ||
1326 | graphic_ctrl.f_w32xx.en_graphic_req=1; | ||
1327 | graphic_ctrl.f_w32xx.en_graphic_crtc=1; | ||
1328 | graphic_ctrl.f_w32xx.lcd_pclk_on=1; | ||
1329 | graphic_ctrl.f_w32xx.lcd_sclk_on=1; | ||
1330 | graphic_ctrl.f_w32xx.low_power_on=0; | ||
1331 | graphic_ctrl.f_w32xx.req_freq=0; | ||
1332 | graphic_ctrl.f_w32xx.total_req_graphic=par->mode->xres >> 1; /* panel xres, not mode */ | ||
1333 | graphic_ctrl.f_w32xx.portrait_mode=rot; | ||
1334 | break; | ||
1335 | } | ||
1336 | |||
1337 | /* Set the pixel clock source and divider */ | ||
1338 | w100_pwr_state.pclk_cntl.f.pclk_src_sel = par->mode->pixclk_src; | ||
1339 | w100_pwr_state.pclk_cntl.f.pclk_post_div = divider; | ||
1340 | writel((u32) (w100_pwr_state.pclk_cntl.val), remapped_regs + mmPCLK_CNTL); | ||
1341 | |||
1342 | writel(graphic_ctrl.val, remapped_regs + mmGRAPHIC_CTRL); | ||
1343 | writel(W100_FB_BASE + ((offset * BITS_PER_PIXEL/8)&~0x03UL), remapped_regs + mmGRAPHIC_OFFSET); | ||
1344 | writel((par->xres*BITS_PER_PIXEL/8), remapped_regs + mmGRAPHIC_PITCH); | ||
1357 | } | 1345 | } |
1358 | 1346 | ||
1359 | 1347 | ||
1360 | static void w100_init_qvga_rotation(u16 deg) | 1348 | /* |
1349 | * Work out how long the sync pulse lasts | ||
1350 | * Value is 1/(time in seconds) | ||
1351 | */ | ||
1352 | static void calc_hsync(struct w100fb_par *par) | ||
1361 | { | 1353 | { |
1362 | switch(deg) { | 1354 | unsigned long hsync; |
1363 | case 0: | 1355 | struct w100_mode *mode = par->mode; |
1364 | w100_set_qvga_rotation_regs(0x00d41c06, 0x00800000, 0x000001e0); | 1356 | union crtc_ss_u crtc_ss; |
1365 | break; | 1357 | |
1366 | case 90: | 1358 | if (mode->pixclk_src == CLK_SRC_XTAL) |
1367 | w100_set_qvga_rotation_regs(0x00d41c0E, 0x00825580, 0x00000280); | 1359 | hsync=par->mach->xtal_freq; |
1368 | break; | 1360 | else |
1369 | case 180: | 1361 | hsync=((par->fastpll_mode && mode->fast_pll_freq) ? mode->fast_pll_freq : mode->pll_freq)*100000; |
1370 | w100_set_qvga_rotation_regs(0x00d41c1e, 0x008257fc, 0x000001e0); | ||
1371 | break; | ||
1372 | case 270: | ||
1373 | w100_set_qvga_rotation_regs(0x00d41c16, 0x0080027c, 0x00000280); | ||
1374 | break; | ||
1375 | default: | ||
1376 | /* not-support */ | ||
1377 | break; | ||
1378 | } | ||
1379 | } | ||
1380 | 1362 | ||
1363 | hsync /= (w100_pwr_state.pclk_cntl.f.pclk_post_div + 1); | ||
1364 | |||
1365 | crtc_ss.val = readl(remapped_regs + mmCRTC_SS); | ||
1366 | if (crtc_ss.val) | ||
1367 | par->hsync_len = hsync / (crtc_ss.f.ss_end-crtc_ss.f.ss_start); | ||
1368 | else | ||
1369 | par->hsync_len = 0; | ||
1370 | } | ||
1381 | 1371 | ||
1382 | static void w100_suspend(u32 mode) | 1372 | static void w100_suspend(u32 mode) |
1383 | { | 1373 | { |
@@ -1387,30 +1377,28 @@ static void w100_suspend(u32 mode) | |||
1387 | writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL); | 1377 | writel(0x00FF0000, remapped_regs + mmMC_PERF_MON_CNTL); |
1388 | 1378 | ||
1389 | val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL); | 1379 | val = readl(remapped_regs + mmMEM_EXT_TIMING_CNTL); |
1390 | val &= ~(0x00100000); /* bit20=0 */ | 1380 | val &= ~(0x00100000); /* bit20=0 */ |
1391 | val |= 0xFF000000; /* bit31:24=0xff */ | 1381 | val |= 0xFF000000; /* bit31:24=0xff */ |
1392 | writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL); | 1382 | writel(val, remapped_regs + mmMEM_EXT_TIMING_CNTL); |
1393 | 1383 | ||
1394 | val = readl(remapped_regs + mmMEM_EXT_CNTL); | 1384 | val = readl(remapped_regs + mmMEM_EXT_CNTL); |
1395 | val &= ~(0x00040000); /* bit18=0 */ | 1385 | val &= ~(0x00040000); /* bit18=0 */ |
1396 | val |= 0x00080000; /* bit19=1 */ | 1386 | val |= 0x00080000; /* bit19=1 */ |
1397 | writel(val, remapped_regs + mmMEM_EXT_CNTL); | 1387 | writel(val, remapped_regs + mmMEM_EXT_CNTL); |
1398 | 1388 | ||
1399 | udelay(1); /* wait 1us */ | 1389 | udelay(1); /* wait 1us */ |
1400 | 1390 | ||
1401 | if (mode == W100_SUSPEND_EXTMEM) { | 1391 | if (mode == W100_SUSPEND_EXTMEM) { |
1402 | |||
1403 | /* CKE: Tri-State */ | 1392 | /* CKE: Tri-State */ |
1404 | val = readl(remapped_regs + mmMEM_EXT_CNTL); | 1393 | val = readl(remapped_regs + mmMEM_EXT_CNTL); |
1405 | val |= 0x40000000; /* bit30=1 */ | 1394 | val |= 0x40000000; /* bit30=1 */ |
1406 | writel(val, remapped_regs + mmMEM_EXT_CNTL); | 1395 | writel(val, remapped_regs + mmMEM_EXT_CNTL); |
1407 | 1396 | ||
1408 | /* CLK: Stop */ | 1397 | /* CLK: Stop */ |
1409 | val = readl(remapped_regs + mmMEM_EXT_CNTL); | 1398 | val = readl(remapped_regs + mmMEM_EXT_CNTL); |
1410 | val &= ~(0x00000001); /* bit0=0 */ | 1399 | val &= ~(0x00000001); /* bit0=0 */ |
1411 | writel(val, remapped_regs + mmMEM_EXT_CNTL); | 1400 | writel(val, remapped_regs + mmMEM_EXT_CNTL); |
1412 | } else { | 1401 | } else { |
1413 | |||
1414 | writel(0x00000000, remapped_regs + mmSCLK_CNTL); | 1402 | writel(0x00000000, remapped_regs + mmSCLK_CNTL); |
1415 | writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL); | 1403 | writel(0x000000BF, remapped_regs + mmCLK_PIN_CNTL); |
1416 | writel(0x00000015, remapped_regs + mmPWRMGT_CNTL); | 1404 | writel(0x00000015, remapped_regs + mmPWRMGT_CNTL); |
@@ -1418,43 +1406,16 @@ static void w100_suspend(u32 mode) | |||
1418 | udelay(5); | 1406 | udelay(5); |
1419 | 1407 | ||
1420 | val = readl(remapped_regs + mmPLL_CNTL); | 1408 | val = readl(remapped_regs + mmPLL_CNTL); |
1421 | val |= 0x00000004; /* bit2=1 */ | 1409 | val |= 0x00000004; /* bit2=1 */ |
1422 | writel(val, remapped_regs + mmPLL_CNTL); | 1410 | writel(val, remapped_regs + mmPLL_CNTL); |
1423 | writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL); | 1411 | writel(0x0000001d, remapped_regs + mmPWRMGT_CNTL); |
1424 | } | 1412 | } |
1425 | } | 1413 | } |
1426 | 1414 | ||
1427 | |||
1428 | static void w100_resume(void) | ||
1429 | { | ||
1430 | u32 temp32; | ||
1431 | |||
1432 | w100_hw_init(); | ||
1433 | w100_pwm_setup(); | ||
1434 | |||
1435 | temp32 = readl(remapped_regs + mmDISP_DEBUG2); | ||
1436 | temp32 &= 0xff7fffff; | ||
1437 | temp32 |= 0x00800000; | ||
1438 | writel(temp32, remapped_regs + mmDISP_DEBUG2); | ||
1439 | |||
1440 | if (current_par->lcdMode == LCD_MODE_480 || current_par->lcdMode == LCD_MODE_640) { | ||
1441 | w100_init_sharp_lcd(LCD_SHARP_VGA); | ||
1442 | if (current_par->lcdMode == LCD_MODE_640) { | ||
1443 | w100_init_vga_rotation(current_par->rotation_flag ? 270 : 90); | ||
1444 | } | ||
1445 | } else { | ||
1446 | w100_init_sharp_lcd(LCD_SHARP_QVGA); | ||
1447 | if (current_par->lcdMode == LCD_MODE_320) { | ||
1448 | w100_init_qvga_rotation(current_par->rotation_flag ? 270 : 90); | ||
1449 | } | ||
1450 | } | ||
1451 | } | ||
1452 | |||
1453 | |||
1454 | static void w100_vsync(void) | 1415 | static void w100_vsync(void) |
1455 | { | 1416 | { |
1456 | u32 tmp; | 1417 | u32 tmp; |
1457 | int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */ | 1418 | int timeout = 30000; /* VSync timeout = 30[ms] > 16.8[ms] */ |
1458 | 1419 | ||
1459 | tmp = readl(remapped_regs + mmACTIVE_V_DISP); | 1420 | tmp = readl(remapped_regs + mmACTIVE_V_DISP); |
1460 | 1421 | ||
@@ -1490,363 +1451,6 @@ static void w100_vsync(void) | |||
1490 | writel(0x00000002, remapped_regs + mmGEN_INT_STATUS); | 1451 | writel(0x00000002, remapped_regs + mmGEN_INT_STATUS); |
1491 | } | 1452 | } |
1492 | 1453 | ||
1493 | |||
1494 | static void w100_InitExtMem(u32 mode) | ||
1495 | { | ||
1496 | switch(mode) { | ||
1497 | case LCD_SHARP_QVGA: | ||
1498 | /* QVGA doesn't use external memory | ||
1499 | nothing to do, really. */ | ||
1500 | break; | ||
1501 | case LCD_SHARP_VGA: | ||
1502 | writel(0x00007800, remapped_regs + mmMC_BIST_CTRL); | ||
1503 | writel(0x00040003, remapped_regs + mmMEM_EXT_CNTL); | ||
1504 | writel(0x00200021, remapped_regs + mmMEM_SDRAM_MODE_REG); | ||
1505 | udelay(100); | ||
1506 | writel(0x80200021, remapped_regs + mmMEM_SDRAM_MODE_REG); | ||
1507 | udelay(100); | ||
1508 | writel(0x00650021, remapped_regs + mmMEM_SDRAM_MODE_REG); | ||
1509 | udelay(100); | ||
1510 | writel(0x10002a4a, remapped_regs + mmMEM_EXT_TIMING_CNTL); | ||
1511 | writel(0x7ff87012, remapped_regs + mmMEM_IO_CNTL); | ||
1512 | break; | ||
1513 | default: | ||
1514 | break; | ||
1515 | } | ||
1516 | } | ||
1517 | |||
1518 | |||
1519 | #define RESCTL_ADRS 0x00 | ||
1520 | #define PHACTRL_ADRS 0x01 | ||
1521 | #define DUTYCTRL_ADRS 0x02 | ||
1522 | #define POWERREG0_ADRS 0x03 | ||
1523 | #define POWERREG1_ADRS 0x04 | ||
1524 | #define GPOR3_ADRS 0x05 | ||
1525 | #define PICTRL_ADRS 0x06 | ||
1526 | #define POLCTRL_ADRS 0x07 | ||
1527 | |||
1528 | #define RESCTL_QVGA 0x01 | ||
1529 | #define RESCTL_VGA 0x00 | ||
1530 | |||
1531 | #define POWER1_VW_ON 0x01 /* VW Supply FET ON */ | ||
1532 | #define POWER1_GVSS_ON 0x02 /* GVSS(-8V) Power Supply ON */ | ||
1533 | #define POWER1_VDD_ON 0x04 /* VDD(8V),SVSS(-4V) Power Supply ON */ | ||
1534 | |||
1535 | #define POWER1_VW_OFF 0x00 /* VW Supply FET OFF */ | ||
1536 | #define POWER1_GVSS_OFF 0x00 /* GVSS(-8V) Power Supply OFF */ | ||
1537 | #define POWER1_VDD_OFF 0x00 /* VDD(8V),SVSS(-4V) Power Supply OFF */ | ||
1538 | |||
1539 | #define POWER0_COM_DCLK 0x01 /* COM Voltage DC Bias DAC Serial Data Clock */ | ||
1540 | #define POWER0_COM_DOUT 0x02 /* COM Voltage DC Bias DAC Serial Data Out */ | ||
1541 | #define POWER0_DAC_ON 0x04 /* DAC Power Supply ON */ | ||
1542 | #define POWER0_COM_ON 0x08 /* COM Powewr Supply ON */ | ||
1543 | #define POWER0_VCC5_ON 0x10 /* VCC5 Power Supply ON */ | ||
1544 | |||
1545 | #define POWER0_DAC_OFF 0x00 /* DAC Power Supply OFF */ | ||
1546 | #define POWER0_COM_OFF 0x00 /* COM Powewr Supply OFF */ | ||
1547 | #define POWER0_VCC5_OFF 0x00 /* VCC5 Power Supply OFF */ | ||
1548 | |||
1549 | #define PICTRL_INIT_STATE 0x01 | ||
1550 | #define PICTRL_INIOFF 0x02 | ||
1551 | #define PICTRL_POWER_DOWN 0x04 | ||
1552 | #define PICTRL_COM_SIGNAL_OFF 0x08 | ||
1553 | #define PICTRL_DAC_SIGNAL_OFF 0x10 | ||
1554 | |||
1555 | #define PICTRL_POWER_ACTIVE (0) | ||
1556 | |||
1557 | #define POLCTRL_SYNC_POL_FALL 0x01 | ||
1558 | #define POLCTRL_EN_POL_FALL 0x02 | ||
1559 | #define POLCTRL_DATA_POL_FALL 0x04 | ||
1560 | #define POLCTRL_SYNC_ACT_H 0x08 | ||
1561 | #define POLCTRL_EN_ACT_L 0x10 | ||
1562 | |||
1563 | #define POLCTRL_SYNC_POL_RISE 0x00 | ||
1564 | #define POLCTRL_EN_POL_RISE 0x00 | ||
1565 | #define POLCTRL_DATA_POL_RISE 0x00 | ||
1566 | #define POLCTRL_SYNC_ACT_L 0x00 | ||
1567 | #define POLCTRL_EN_ACT_H 0x00 | ||
1568 | |||
1569 | #define PHACTRL_PHASE_MANUAL 0x01 | ||
1570 | |||
1571 | #define PHAD_QVGA_DEFAULT_VAL (9) | ||
1572 | #define COMADJ_DEFAULT (125) | ||
1573 | |||
1574 | static void lcdtg_ssp_send(u8 adrs, u8 data) | ||
1575 | { | ||
1576 | w100fb_ssp_send(adrs,data); | ||
1577 | } | ||
1578 | |||
1579 | /* | ||
1580 | * This is only a psuedo I2C interface. We can't use the standard kernel | ||
1581 | * routines as the interface is write only. We just assume the data is acked... | ||
1582 | */ | ||
1583 | static void lcdtg_ssp_i2c_send(u8 data) | ||
1584 | { | ||
1585 | lcdtg_ssp_send(POWERREG0_ADRS, data); | ||
1586 | udelay(10); | ||
1587 | } | ||
1588 | |||
1589 | static void lcdtg_i2c_send_bit(u8 data) | ||
1590 | { | ||
1591 | lcdtg_ssp_i2c_send(data); | ||
1592 | lcdtg_ssp_i2c_send(data | POWER0_COM_DCLK); | ||
1593 | lcdtg_ssp_i2c_send(data); | ||
1594 | } | ||
1595 | |||
1596 | static void lcdtg_i2c_send_start(u8 base) | ||
1597 | { | ||
1598 | lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT); | ||
1599 | lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK); | ||
1600 | lcdtg_ssp_i2c_send(base); | ||
1601 | } | ||
1602 | |||
1603 | static void lcdtg_i2c_send_stop(u8 base) | ||
1604 | { | ||
1605 | lcdtg_ssp_i2c_send(base); | ||
1606 | lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK); | ||
1607 | lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT); | ||
1608 | } | ||
1609 | |||
1610 | static void lcdtg_i2c_send_byte(u8 base, u8 data) | ||
1611 | { | ||
1612 | int i; | ||
1613 | for (i = 0; i < 8; i++) { | ||
1614 | if (data & 0x80) | ||
1615 | lcdtg_i2c_send_bit(base | POWER0_COM_DOUT); | ||
1616 | else | ||
1617 | lcdtg_i2c_send_bit(base); | ||
1618 | data <<= 1; | ||
1619 | } | ||
1620 | } | ||
1621 | |||
1622 | static void lcdtg_i2c_wait_ack(u8 base) | ||
1623 | { | ||
1624 | lcdtg_i2c_send_bit(base); | ||
1625 | } | ||
1626 | |||
1627 | static void lcdtg_set_common_voltage(u8 base_data, u8 data) | ||
1628 | { | ||
1629 | /* Set Common Voltage to M62332FP via I2C */ | ||
1630 | lcdtg_i2c_send_start(base_data); | ||
1631 | lcdtg_i2c_send_byte(base_data, 0x9c); | ||
1632 | lcdtg_i2c_wait_ack(base_data); | ||
1633 | lcdtg_i2c_send_byte(base_data, 0x00); | ||
1634 | lcdtg_i2c_wait_ack(base_data); | ||
1635 | lcdtg_i2c_send_byte(base_data, data); | ||
1636 | lcdtg_i2c_wait_ack(base_data); | ||
1637 | lcdtg_i2c_send_stop(base_data); | ||
1638 | } | ||
1639 | |||
1640 | static struct lcdtg_register_setting { | ||
1641 | u8 adrs; | ||
1642 | u8 data; | ||
1643 | u32 wait; | ||
1644 | } lcdtg_power_on_table[] = { | ||
1645 | |||
1646 | /* Initialize Internal Logic & Port */ | ||
1647 | { PICTRL_ADRS, | ||
1648 | PICTRL_POWER_DOWN | PICTRL_INIOFF | PICTRL_INIT_STATE | | ||
1649 | PICTRL_COM_SIGNAL_OFF | PICTRL_DAC_SIGNAL_OFF, | ||
1650 | 0 }, | ||
1651 | |||
1652 | { POWERREG0_ADRS, | ||
1653 | POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_OFF | POWER0_COM_OFF | | ||
1654 | POWER0_VCC5_OFF, | ||
1655 | 0 }, | ||
1656 | |||
1657 | { POWERREG1_ADRS, | ||
1658 | POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF, | ||
1659 | 0 }, | ||
1660 | |||
1661 | /* VDD(+8V),SVSS(-4V) ON */ | ||
1662 | { POWERREG1_ADRS, | ||
1663 | POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON /* VDD ON */, | ||
1664 | 3000 }, | ||
1665 | |||
1666 | /* DAC ON */ | ||
1667 | { POWERREG0_ADRS, | ||
1668 | POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON /* DAC ON */ | | ||
1669 | POWER0_COM_OFF | POWER0_VCC5_OFF, | ||
1670 | 0 }, | ||
1671 | |||
1672 | /* INIB = H, INI = L */ | ||
1673 | { PICTRL_ADRS, | ||
1674 | /* PICTL[0] = H , PICTL[1] = PICTL[2] = PICTL[4] = L */ | ||
1675 | PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF, | ||
1676 | 0 }, | ||
1677 | |||
1678 | /* Set Common Voltage */ | ||
1679 | { 0xfe, 0, 0 }, | ||
1680 | |||
1681 | /* VCC5 ON */ | ||
1682 | { POWERREG0_ADRS, | ||
1683 | POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON /* DAC ON */ | | ||
1684 | POWER0_COM_OFF | POWER0_VCC5_ON /* VCC5 ON */, | ||
1685 | 0 }, | ||
1686 | |||
1687 | /* GVSS(-8V) ON */ | ||
1688 | { POWERREG1_ADRS, | ||
1689 | POWER1_VW_OFF | POWER1_GVSS_ON /* GVSS ON */ | | ||
1690 | POWER1_VDD_ON /* VDD ON */, | ||
1691 | 2000 }, | ||
1692 | |||
1693 | /* COM SIGNAL ON (PICTL[3] = L) */ | ||
1694 | { PICTRL_ADRS, | ||
1695 | PICTRL_INIT_STATE, | ||
1696 | 0 }, | ||
1697 | |||
1698 | /* COM ON */ | ||
1699 | { POWERREG0_ADRS, | ||
1700 | POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON /* DAC ON */ | | ||
1701 | POWER0_COM_ON /* COM ON */ | POWER0_VCC5_ON /* VCC5_ON */, | ||
1702 | 0 }, | ||
1703 | |||
1704 | /* VW ON */ | ||
1705 | { POWERREG1_ADRS, | ||
1706 | POWER1_VW_ON /* VW ON */ | POWER1_GVSS_ON /* GVSS ON */ | | ||
1707 | POWER1_VDD_ON /* VDD ON */, | ||
1708 | 0 /* Wait 100ms */ }, | ||
1709 | |||
1710 | /* Signals output enable */ | ||
1711 | { PICTRL_ADRS, | ||
1712 | 0 /* Signals output enable */, | ||
1713 | 0 }, | ||
1714 | |||
1715 | { PHACTRL_ADRS, | ||
1716 | PHACTRL_PHASE_MANUAL, | ||
1717 | 0 }, | ||
1718 | |||
1719 | /* Initialize for Input Signals from ATI */ | ||
1720 | { POLCTRL_ADRS, | ||
1721 | POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE | POLCTRL_DATA_POL_RISE | | ||
1722 | POLCTRL_SYNC_ACT_L | POLCTRL_EN_ACT_H, | ||
1723 | 1000 /*100000*/ /* Wait 100ms */ }, | ||
1724 | |||
1725 | /* end mark */ | ||
1726 | { 0xff, 0, 0 } | ||
1727 | }; | ||
1728 | |||
1729 | static void lcdtg_resume(void) | ||
1730 | { | ||
1731 | if (current_par->lcdMode == LCD_MODE_480 || current_par->lcdMode == LCD_MODE_640) { | ||
1732 | lcdtg_hw_init(LCD_SHARP_VGA); | ||
1733 | } else { | ||
1734 | lcdtg_hw_init(LCD_SHARP_QVGA); | ||
1735 | } | ||
1736 | } | ||
1737 | |||
1738 | static void lcdtg_suspend(void) | ||
1739 | { | ||
1740 | int i; | ||
1741 | |||
1742 | for (i = 0; i < (current_par->xres * current_par->yres); i++) { | ||
1743 | writew(0xffff, remapped_fbuf + (2*i)); | ||
1744 | } | ||
1745 | |||
1746 | /* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */ | ||
1747 | mdelay(34); | ||
1748 | |||
1749 | /* (1)VW OFF */ | ||
1750 | lcdtg_ssp_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON); | ||
1751 | |||
1752 | /* (2)COM OFF */ | ||
1753 | lcdtg_ssp_send(PICTRL_ADRS, PICTRL_COM_SIGNAL_OFF); | ||
1754 | lcdtg_ssp_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON); | ||
1755 | |||
1756 | /* (3)Set Common Voltage Bias 0V */ | ||
1757 | lcdtg_set_common_voltage(POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON, 0); | ||
1758 | |||
1759 | /* (4)GVSS OFF */ | ||
1760 | lcdtg_ssp_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON); | ||
1761 | |||
1762 | /* (5)VCC5 OFF */ | ||
1763 | lcdtg_ssp_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF); | ||
1764 | |||
1765 | /* (6)Set PDWN, INIOFF, DACOFF */ | ||
1766 | lcdtg_ssp_send(PICTRL_ADRS, PICTRL_INIOFF | PICTRL_DAC_SIGNAL_OFF | | ||
1767 | PICTRL_POWER_DOWN | PICTRL_COM_SIGNAL_OFF); | ||
1768 | |||
1769 | /* (7)DAC OFF */ | ||
1770 | lcdtg_ssp_send(POWERREG0_ADRS, POWER0_DAC_OFF | POWER0_COM_OFF | POWER0_VCC5_OFF); | ||
1771 | |||
1772 | /* (8)VDD OFF */ | ||
1773 | lcdtg_ssp_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF); | ||
1774 | |||
1775 | } | ||
1776 | |||
1777 | static void lcdtg_set_phadadj(u32 mode) | ||
1778 | { | ||
1779 | int adj; | ||
1780 | |||
1781 | if (mode == LCD_SHARP_VGA) { | ||
1782 | /* Setting for VGA */ | ||
1783 | adj = current_par->phadadj; | ||
1784 | if (adj < 0) { | ||
1785 | adj = PHACTRL_PHASE_MANUAL; | ||
1786 | } else { | ||
1787 | adj = ((adj & 0x0f) << 1) | PHACTRL_PHASE_MANUAL; | ||
1788 | } | ||
1789 | } else { | ||
1790 | /* Setting for QVGA */ | ||
1791 | adj = (PHAD_QVGA_DEFAULT_VAL << 1) | PHACTRL_PHASE_MANUAL; | ||
1792 | } | ||
1793 | lcdtg_ssp_send(PHACTRL_ADRS, adj); | ||
1794 | } | ||
1795 | |||
1796 | static void lcdtg_hw_init(u32 mode) | ||
1797 | { | ||
1798 | int i; | ||
1799 | int comadj; | ||
1800 | |||
1801 | i = 0; | ||
1802 | while(lcdtg_power_on_table[i].adrs != 0xff) { | ||
1803 | if (lcdtg_power_on_table[i].adrs == 0xfe) { | ||
1804 | /* Set Common Voltage */ | ||
1805 | comadj = current_par->comadj; | ||
1806 | if (comadj < 0) { | ||
1807 | comadj = COMADJ_DEFAULT; | ||
1808 | } | ||
1809 | lcdtg_set_common_voltage((POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF), comadj); | ||
1810 | } else if (lcdtg_power_on_table[i].adrs == PHACTRL_ADRS) { | ||
1811 | /* Set Phase Adjuct */ | ||
1812 | lcdtg_set_phadadj(mode); | ||
1813 | } else { | ||
1814 | /* Other */ | ||
1815 | lcdtg_ssp_send(lcdtg_power_on_table[i].adrs, lcdtg_power_on_table[i].data); | ||
1816 | } | ||
1817 | if (lcdtg_power_on_table[i].wait != 0) | ||
1818 | udelay(lcdtg_power_on_table[i].wait); | ||
1819 | i++; | ||
1820 | } | ||
1821 | |||
1822 | switch(mode) { | ||
1823 | case LCD_SHARP_QVGA: | ||
1824 | /* Set Lcd Resolution (QVGA) */ | ||
1825 | lcdtg_ssp_send(RESCTL_ADRS, RESCTL_QVGA); | ||
1826 | break; | ||
1827 | case LCD_SHARP_VGA: | ||
1828 | /* Set Lcd Resolution (VGA) */ | ||
1829 | lcdtg_ssp_send(RESCTL_ADRS, RESCTL_VGA); | ||
1830 | break; | ||
1831 | default: | ||
1832 | break; | ||
1833 | } | ||
1834 | } | ||
1835 | |||
1836 | static void lcdtg_lcd_change(u32 mode) | ||
1837 | { | ||
1838 | /* Set Phase Adjuct */ | ||
1839 | lcdtg_set_phadadj(mode); | ||
1840 | |||
1841 | if (mode == LCD_SHARP_VGA) | ||
1842 | /* Set Lcd Resolution (VGA) */ | ||
1843 | lcdtg_ssp_send(RESCTL_ADRS, RESCTL_VGA); | ||
1844 | else if (mode == LCD_SHARP_QVGA) | ||
1845 | /* Set Lcd Resolution (QVGA) */ | ||
1846 | lcdtg_ssp_send(RESCTL_ADRS, RESCTL_QVGA); | ||
1847 | } | ||
1848 | |||
1849 | |||
1850 | static struct device_driver w100fb_driver = { | 1454 | static struct device_driver w100fb_driver = { |
1851 | .name = "w100fb", | 1455 | .name = "w100fb", |
1852 | .bus = &platform_bus_type, | 1456 | .bus = &platform_bus_type, |
@@ -1870,4 +1474,4 @@ module_init(w100fb_init); | |||
1870 | module_exit(w100fb_cleanup); | 1474 | module_exit(w100fb_cleanup); |
1871 | 1475 | ||
1872 | MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver"); | 1476 | MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver"); |
1873 | MODULE_LICENSE("GPLv2"); | 1477 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/video/w100fb.h b/drivers/video/w100fb.h index 41624f961237..7a58a1e3e427 100644 --- a/drivers/video/w100fb.h +++ b/drivers/video/w100fb.h | |||
@@ -5,9 +5,12 @@ | |||
5 | * | 5 | * |
6 | * Copyright (C) 2002, ATI Corp. | 6 | * Copyright (C) 2002, ATI Corp. |
7 | * Copyright (C) 2004-2005 Richard Purdie | 7 | * Copyright (C) 2004-2005 Richard Purdie |
8 | * Copyright (c) 2005 Ian Molton <spyro@f2s.com> | ||
8 | * | 9 | * |
9 | * Modified to work with 2.6 by Richard Purdie <rpurdie@rpsys.net> | 10 | * Modified to work with 2.6 by Richard Purdie <rpurdie@rpsys.net> |
10 | * | 11 | * |
12 | * w32xx support by Ian Molton | ||
13 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | 14 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 15 | * it under the terms of the GNU General Public License version 2 as |
13 | * published by the Free Software Foundation. | 16 | * published by the Free Software Foundation. |
@@ -19,7 +22,7 @@ | |||
19 | 22 | ||
20 | /* Block CIF Start: */ | 23 | /* Block CIF Start: */ |
21 | #define mmCHIP_ID 0x0000 | 24 | #define mmCHIP_ID 0x0000 |
22 | #define mmREVISION_ID 0x0004 | 25 | #define mmREVISION_ID 0x0004 |
23 | #define mmWRAP_BUF_A 0x0008 | 26 | #define mmWRAP_BUF_A 0x0008 |
24 | #define mmWRAP_BUF_B 0x000C | 27 | #define mmWRAP_BUF_B 0x000C |
25 | #define mmWRAP_TOP_DIR 0x0010 | 28 | #define mmWRAP_TOP_DIR 0x0010 |
@@ -88,7 +91,7 @@ | |||
88 | #define mmDISP_DEBUG 0x04D4 | 91 | #define mmDISP_DEBUG 0x04D4 |
89 | #define mmDISP_DB_BUF_CNTL 0x04D8 | 92 | #define mmDISP_DB_BUF_CNTL 0x04D8 |
90 | #define mmDISP_CRC_SIG 0x04DC | 93 | #define mmDISP_CRC_SIG 0x04DC |
91 | #define mmCRTC_DEFAULT_COUNT 0x04E0 | 94 | #define mmCRTC_DEFAULT_COUNT 0x04E0 |
92 | #define mmLCD_BACKGROUND_COLOR 0x04E4 | 95 | #define mmLCD_BACKGROUND_COLOR 0x04E4 |
93 | #define mmCRTC_PS2 0x04E8 | 96 | #define mmCRTC_PS2 0x04E8 |
94 | #define mmCRTC_PS2_VPOS 0x04EC | 97 | #define mmCRTC_PS2_VPOS 0x04EC |
@@ -119,17 +122,17 @@ | |||
119 | /* Block DISPLAY End: */ | 122 | /* Block DISPLAY End: */ |
120 | 123 | ||
121 | /* Block GFX Start: */ | 124 | /* Block GFX Start: */ |
122 | #define mmBRUSH_OFFSET 0x108C | 125 | #define mmBRUSH_OFFSET 0x108C |
123 | #define mmBRUSH_Y_X 0x1074 | 126 | #define mmBRUSH_Y_X 0x1074 |
124 | #define mmDEFAULT_PITCH_OFFSET 0x10A0 | 127 | #define mmDEFAULT_PITCH_OFFSET 0x10A0 |
125 | #define mmDEFAULT_SC_BOTTOM_RIGHT 0x10A8 | 128 | #define mmDEFAULT_SC_BOTTOM_RIGHT 0x10A8 |
126 | #define mmDEFAULT2_SC_BOTTOM_RIGHT 0x10AC | 129 | #define mmDEFAULT2_SC_BOTTOM_RIGHT 0x10AC |
127 | #define mmGLOBAL_ALPHA 0x1210 | 130 | #define mmGLOBAL_ALPHA 0x1210 |
128 | #define mmFILTER_COEF 0x1214 | 131 | #define mmFILTER_COEF 0x1214 |
129 | #define mmMVC_CNTL_START 0x11E0 | 132 | #define mmMVC_CNTL_START 0x11E0 |
130 | #define mmE2_ARITHMETIC_CNTL 0x1220 | 133 | #define mmE2_ARITHMETIC_CNTL 0x1220 |
131 | #define mmENG_CNTL 0x13E8 | 134 | #define mmENG_CNTL 0x13E8 |
132 | #define mmENG_PERF_CNT 0x13F0 | 135 | #define mmENG_PERF_CNT 0x13F0 |
133 | /* Block GFX End: */ | 136 | /* Block GFX End: */ |
134 | 137 | ||
135 | /* Block IDCT Start: */ | 138 | /* Block IDCT Start: */ |
@@ -141,22 +144,38 @@ | |||
141 | /* Block IDCT End: */ | 144 | /* Block IDCT End: */ |
142 | 145 | ||
143 | /* Block MC Start: */ | 146 | /* Block MC Start: */ |
144 | #define mmMEM_CNTL 0x0180 | 147 | #define mmMEM_CNTL 0x0180 |
145 | #define mmMEM_ARB 0x0184 | 148 | #define mmMEM_ARB 0x0184 |
146 | #define mmMC_FB_LOCATION 0x0188 | 149 | #define mmMC_FB_LOCATION 0x0188 |
147 | #define mmMEM_EXT_CNTL 0x018C | 150 | #define mmMEM_EXT_CNTL 0x018C |
148 | #define mmMC_EXT_MEM_LOCATION 0x0190 | 151 | #define mmMC_EXT_MEM_LOCATION 0x0190 |
149 | #define mmMEM_EXT_TIMING_CNTL 0x0194 | 152 | #define mmMEM_EXT_TIMING_CNTL 0x0194 |
150 | #define mmMEM_SDRAM_MODE_REG 0x0198 | 153 | #define mmMEM_SDRAM_MODE_REG 0x0198 |
151 | #define mmMEM_IO_CNTL 0x019C | 154 | #define mmMEM_IO_CNTL 0x019C |
152 | #define mmMC_DEBUG 0x01A0 | 155 | #define mmMC_DEBUG 0x01A0 |
153 | #define mmMC_BIST_CTRL 0x01A4 | 156 | #define mmMC_BIST_CTRL 0x01A4 |
154 | #define mmMC_BIST_COLLAR_READ 0x01A8 | 157 | #define mmMC_BIST_COLLAR_READ 0x01A8 |
155 | #define mmTC_MISMATCH 0x01AC | 158 | #define mmTC_MISMATCH 0x01AC |
156 | #define mmMC_PERF_MON_CNTL 0x01B0 | 159 | #define mmMC_PERF_MON_CNTL 0x01B0 |
157 | #define mmMC_PERF_COUNTERS 0x01B4 | 160 | #define mmMC_PERF_COUNTERS 0x01B4 |
158 | /* Block MC End: */ | 161 | /* Block MC End: */ |
159 | 162 | ||
163 | /* Block BM Start: */ | ||
164 | #define mmBM_EXT_MEM_BANDWIDTH 0x0A00 | ||
165 | #define mmBM_OFFSET 0x0A04 | ||
166 | #define mmBM_MEM_EXT_TIMING_CNTL 0x0A08 | ||
167 | #define mmBM_MEM_EXT_CNTL 0x0A0C | ||
168 | #define mmBM_MEM_MODE_REG 0x0A10 | ||
169 | #define mmBM_MEM_IO_CNTL 0x0A18 | ||
170 | #define mmBM_CONFIG 0x0A1C | ||
171 | #define mmBM_STATUS 0x0A20 | ||
172 | #define mmBM_DEBUG 0x0A24 | ||
173 | #define mmBM_PERF_MON_CNTL 0x0A28 | ||
174 | #define mmBM_PERF_COUNTERS 0x0A2C | ||
175 | #define mmBM_PERF2_MON_CNTL 0x0A30 | ||
176 | #define mmBM_PERF2_COUNTERS 0x0A34 | ||
177 | /* Block BM End: */ | ||
178 | |||
160 | /* Block RBBM Start: */ | 179 | /* Block RBBM Start: */ |
161 | #define mmWAIT_UNTIL 0x1400 | 180 | #define mmWAIT_UNTIL 0x1400 |
162 | #define mmISYNC_CNTL 0x1404 | 181 | #define mmISYNC_CNTL 0x1404 |
@@ -176,439 +195,575 @@ | |||
176 | /* Block CG End: */ | 195 | /* Block CG End: */ |
177 | 196 | ||
178 | /* default value definitions */ | 197 | /* default value definitions */ |
179 | #define defWRAP_TOP_DIR 0x00000000 | 198 | #define defWRAP_TOP_DIR 0x00000000 |
180 | #define defWRAP_START_DIR 0x00000000 | 199 | #define defWRAP_START_DIR 0x00000000 |
181 | #define defCFGREG_BASE 0x00000000 | 200 | #define defCFGREG_BASE 0x00000000 |
182 | #define defCIF_IO 0x000C0902 | 201 | #define defCIF_IO 0x000C0902 |
183 | #define defINTF_CNTL 0x00000011 | 202 | #define defINTF_CNTL 0x00000011 |
184 | #define defCPU_DEFAULTS 0x00000006 | 203 | #define defCPU_DEFAULTS 0x00000006 |
185 | #define defHW_INT 0x00000000 | 204 | #define defHW_INT 0x00000000 |
186 | #define defMC_EXT_MEM_LOCATION 0x07ff0000 | 205 | #define defMC_EXT_MEM_LOCATION 0x07ff0000 |
187 | #define defTC_MISMATCH 0x00000000 | 206 | #define defTC_MISMATCH 0x00000000 |
188 | 207 | ||
189 | #define W100_CFG_BASE 0x0 | 208 | #define W100_CFG_BASE 0x0 |
190 | #define W100_CFG_LEN 0x10 | 209 | #define W100_CFG_LEN 0x10 |
191 | #define W100_REG_BASE 0x10000 | 210 | #define W100_REG_BASE 0x10000 |
192 | #define W100_REG_LEN 0x2000 | 211 | #define W100_REG_LEN 0x2000 |
193 | #define MEM_INT_BASE_VALUE 0x100000 | 212 | #define MEM_INT_BASE_VALUE 0x100000 |
194 | #define MEM_INT_TOP_VALUE_W100 0x15ffff | ||
195 | #define MEM_EXT_BASE_VALUE 0x800000 | 213 | #define MEM_EXT_BASE_VALUE 0x800000 |
196 | #define MEM_EXT_TOP_VALUE 0x9fffff | 214 | #define MEM_INT_SIZE 0x05ffff |
215 | #define MEM_WINDOW_BASE 0x100000 | ||
216 | #define MEM_WINDOW_SIZE 0xf00000 | ||
217 | |||
197 | #define WRAP_BUF_BASE_VALUE 0x80000 | 218 | #define WRAP_BUF_BASE_VALUE 0x80000 |
198 | #define WRAP_BUF_TOP_VALUE 0xbffff | 219 | #define WRAP_BUF_TOP_VALUE 0xbffff |
199 | 220 | ||
221 | #define CHIP_ID_W100 0x57411002 | ||
222 | #define CHIP_ID_W3200 0x56441002 | ||
223 | #define CHIP_ID_W3220 0x57441002 | ||
200 | 224 | ||
201 | /* data structure definitions */ | 225 | /* Register structure definitions */ |
202 | 226 | ||
203 | struct wrap_top_dir_t { | 227 | struct wrap_top_dir_t { |
204 | unsigned long top_addr : 23; | 228 | unsigned long top_addr : 23; |
205 | unsigned long : 9; | 229 | unsigned long : 9; |
206 | } __attribute__((packed)); | 230 | } __attribute__((packed)); |
207 | 231 | ||
208 | union wrap_top_dir_u { | 232 | union wrap_top_dir_u { |
209 | unsigned long val : 32; | 233 | unsigned long val : 32; |
210 | struct wrap_top_dir_t f; | 234 | struct wrap_top_dir_t f; |
211 | } __attribute__((packed)); | 235 | } __attribute__((packed)); |
212 | 236 | ||
213 | struct wrap_start_dir_t { | 237 | struct wrap_start_dir_t { |
214 | unsigned long start_addr : 23; | 238 | unsigned long start_addr : 23; |
215 | unsigned long : 9; | 239 | unsigned long : 9; |
216 | } __attribute__((packed)); | 240 | } __attribute__((packed)); |
217 | 241 | ||
218 | union wrap_start_dir_u { | 242 | union wrap_start_dir_u { |
219 | unsigned long val : 32; | 243 | unsigned long val : 32; |
220 | struct wrap_start_dir_t f; | 244 | struct wrap_start_dir_t f; |
221 | } __attribute__((packed)); | 245 | } __attribute__((packed)); |
222 | 246 | ||
223 | struct cif_cntl_t { | 247 | struct cif_cntl_t { |
224 | unsigned long swap_reg : 2; | 248 | unsigned long swap_reg : 2; |
225 | unsigned long swap_fbuf_1 : 2; | 249 | unsigned long swap_fbuf_1 : 2; |
226 | unsigned long swap_fbuf_2 : 2; | 250 | unsigned long swap_fbuf_2 : 2; |
227 | unsigned long swap_fbuf_3 : 2; | 251 | unsigned long swap_fbuf_3 : 2; |
228 | unsigned long pmi_int_disable : 1; | 252 | unsigned long pmi_int_disable : 1; |
229 | unsigned long pmi_schmen_disable : 1; | 253 | unsigned long pmi_schmen_disable : 1; |
230 | unsigned long intb_oe : 1; | 254 | unsigned long intb_oe : 1; |
231 | unsigned long en_wait_to_compensate_dq_prop_dly : 1; | 255 | unsigned long en_wait_to_compensate_dq_prop_dly : 1; |
232 | unsigned long compensate_wait_rd_size : 2; | 256 | unsigned long compensate_wait_rd_size : 2; |
233 | unsigned long wait_asserted_timeout_val : 2; | 257 | unsigned long wait_asserted_timeout_val : 2; |
234 | unsigned long wait_masked_val : 2; | 258 | unsigned long wait_masked_val : 2; |
235 | unsigned long en_wait_timeout : 1; | 259 | unsigned long en_wait_timeout : 1; |
236 | unsigned long en_one_clk_setup_before_wait : 1; | 260 | unsigned long en_one_clk_setup_before_wait : 1; |
237 | unsigned long interrupt_active_high : 1; | 261 | unsigned long interrupt_active_high : 1; |
238 | unsigned long en_overwrite_straps : 1; | 262 | unsigned long en_overwrite_straps : 1; |
239 | unsigned long strap_wait_active_hi : 1; | 263 | unsigned long strap_wait_active_hi : 1; |
240 | unsigned long lat_busy_count : 2; | 264 | unsigned long lat_busy_count : 2; |
241 | unsigned long lat_rd_pm4_sclk_busy : 1; | 265 | unsigned long lat_rd_pm4_sclk_busy : 1; |
242 | unsigned long dis_system_bits : 1; | 266 | unsigned long dis_system_bits : 1; |
243 | unsigned long dis_mr : 1; | 267 | unsigned long dis_mr : 1; |
244 | unsigned long cif_spare_1 : 4; | 268 | unsigned long cif_spare_1 : 4; |
245 | } __attribute__((packed)); | 269 | } __attribute__((packed)); |
246 | 270 | ||
247 | union cif_cntl_u { | 271 | union cif_cntl_u { |
248 | unsigned long val : 32; | 272 | unsigned long val : 32; |
249 | struct cif_cntl_t f; | 273 | struct cif_cntl_t f; |
250 | } __attribute__((packed)); | 274 | } __attribute__((packed)); |
251 | 275 | ||
252 | struct cfgreg_base_t { | 276 | struct cfgreg_base_t { |
253 | unsigned long cfgreg_base : 24; | 277 | unsigned long cfgreg_base : 24; |
254 | unsigned long : 8; | 278 | unsigned long : 8; |
255 | } __attribute__((packed)); | 279 | } __attribute__((packed)); |
256 | 280 | ||
257 | union cfgreg_base_u { | 281 | union cfgreg_base_u { |
258 | unsigned long val : 32; | 282 | unsigned long val : 32; |
259 | struct cfgreg_base_t f; | 283 | struct cfgreg_base_t f; |
260 | } __attribute__((packed)); | 284 | } __attribute__((packed)); |
261 | 285 | ||
262 | struct cif_io_t { | 286 | struct cif_io_t { |
263 | unsigned long dq_srp : 1; | 287 | unsigned long dq_srp : 1; |
264 | unsigned long dq_srn : 1; | 288 | unsigned long dq_srn : 1; |
265 | unsigned long dq_sp : 4; | 289 | unsigned long dq_sp : 4; |
266 | unsigned long dq_sn : 4; | 290 | unsigned long dq_sn : 4; |
267 | unsigned long waitb_srp : 1; | 291 | unsigned long waitb_srp : 1; |
268 | unsigned long waitb_srn : 1; | 292 | unsigned long waitb_srn : 1; |
269 | unsigned long waitb_sp : 4; | 293 | unsigned long waitb_sp : 4; |
270 | unsigned long waitb_sn : 4; | 294 | unsigned long waitb_sn : 4; |
271 | unsigned long intb_srp : 1; | 295 | unsigned long intb_srp : 1; |
272 | unsigned long intb_srn : 1; | 296 | unsigned long intb_srn : 1; |
273 | unsigned long intb_sp : 4; | 297 | unsigned long intb_sp : 4; |
274 | unsigned long intb_sn : 4; | 298 | unsigned long intb_sn : 4; |
275 | unsigned long : 2; | 299 | unsigned long : 2; |
276 | } __attribute__((packed)); | 300 | } __attribute__((packed)); |
277 | 301 | ||
278 | union cif_io_u { | 302 | union cif_io_u { |
279 | unsigned long val : 32; | 303 | unsigned long val : 32; |
280 | struct cif_io_t f; | 304 | struct cif_io_t f; |
281 | } __attribute__((packed)); | 305 | } __attribute__((packed)); |
282 | 306 | ||
283 | struct cif_read_dbg_t { | 307 | struct cif_read_dbg_t { |
284 | unsigned long unpacker_pre_fetch_trig_gen : 2; | 308 | unsigned long unpacker_pre_fetch_trig_gen : 2; |
285 | unsigned long dly_second_rd_fetch_trig : 1; | 309 | unsigned long dly_second_rd_fetch_trig : 1; |
286 | unsigned long rst_rd_burst_id : 1; | 310 | unsigned long rst_rd_burst_id : 1; |
287 | unsigned long dis_rd_burst_id : 1; | 311 | unsigned long dis_rd_burst_id : 1; |
288 | unsigned long en_block_rd_when_packer_is_not_emp : 1; | 312 | unsigned long en_block_rd_when_packer_is_not_emp : 1; |
289 | unsigned long dis_pre_fetch_cntl_sm : 1; | 313 | unsigned long dis_pre_fetch_cntl_sm : 1; |
290 | unsigned long rbbm_chrncy_dis : 1; | 314 | unsigned long rbbm_chrncy_dis : 1; |
291 | unsigned long rbbm_rd_after_wr_lat : 2; | 315 | unsigned long rbbm_rd_after_wr_lat : 2; |
292 | unsigned long dis_be_during_rd : 1; | 316 | unsigned long dis_be_during_rd : 1; |
293 | unsigned long one_clk_invalidate_pulse : 1; | 317 | unsigned long one_clk_invalidate_pulse : 1; |
294 | unsigned long dis_chnl_priority : 1; | 318 | unsigned long dis_chnl_priority : 1; |
295 | unsigned long rst_read_path_a_pls : 1; | 319 | unsigned long rst_read_path_a_pls : 1; |
296 | unsigned long rst_read_path_b_pls : 1; | 320 | unsigned long rst_read_path_b_pls : 1; |
297 | unsigned long dis_reg_rd_fetch_trig : 1; | 321 | unsigned long dis_reg_rd_fetch_trig : 1; |
298 | unsigned long dis_rd_fetch_trig_from_ind_addr : 1; | 322 | unsigned long dis_rd_fetch_trig_from_ind_addr : 1; |
299 | unsigned long dis_rd_same_byte_to_trig_fetch : 1; | 323 | unsigned long dis_rd_same_byte_to_trig_fetch : 1; |
300 | unsigned long dis_dir_wrap : 1; | 324 | unsigned long dis_dir_wrap : 1; |
301 | unsigned long dis_ring_buf_to_force_dec : 1; | 325 | unsigned long dis_ring_buf_to_force_dec : 1; |
302 | unsigned long dis_addr_comp_in_16bit : 1; | 326 | unsigned long dis_addr_comp_in_16bit : 1; |
303 | unsigned long clr_w : 1; | 327 | unsigned long clr_w : 1; |
304 | unsigned long err_rd_tag_is_3 : 1; | 328 | unsigned long err_rd_tag_is_3 : 1; |
305 | unsigned long err_load_when_ful_a : 1; | 329 | unsigned long err_load_when_ful_a : 1; |
306 | unsigned long err_load_when_ful_b : 1; | 330 | unsigned long err_load_when_ful_b : 1; |
307 | unsigned long : 7; | 331 | unsigned long : 7; |
308 | } __attribute__((packed)); | 332 | } __attribute__((packed)); |
309 | 333 | ||
310 | union cif_read_dbg_u { | 334 | union cif_read_dbg_u { |
311 | unsigned long val : 32; | 335 | unsigned long val : 32; |
312 | struct cif_read_dbg_t f; | 336 | struct cif_read_dbg_t f; |
313 | } __attribute__((packed)); | 337 | } __attribute__((packed)); |
314 | 338 | ||
315 | struct cif_write_dbg_t { | 339 | struct cif_write_dbg_t { |
316 | unsigned long packer_timeout_count : 2; | 340 | unsigned long packer_timeout_count : 2; |
317 | unsigned long en_upper_load_cond : 1; | 341 | unsigned long en_upper_load_cond : 1; |
318 | unsigned long en_chnl_change_cond : 1; | 342 | unsigned long en_chnl_change_cond : 1; |
319 | unsigned long dis_addr_comp_cond : 1; | 343 | unsigned long dis_addr_comp_cond : 1; |
320 | unsigned long dis_load_same_byte_addr_cond : 1; | 344 | unsigned long dis_load_same_byte_addr_cond : 1; |
321 | unsigned long dis_timeout_cond : 1; | 345 | unsigned long dis_timeout_cond : 1; |
322 | unsigned long dis_timeout_during_rbbm : 1; | 346 | unsigned long dis_timeout_during_rbbm : 1; |
323 | unsigned long dis_packer_ful_during_rbbm_timeout : 1; | 347 | unsigned long dis_packer_ful_during_rbbm_timeout : 1; |
324 | unsigned long en_dword_split_to_rbbm : 1; | 348 | unsigned long en_dword_split_to_rbbm : 1; |
325 | unsigned long en_dummy_val : 1; | 349 | unsigned long en_dummy_val : 1; |
326 | unsigned long dummy_val_sel : 1; | 350 | unsigned long dummy_val_sel : 1; |
327 | unsigned long mask_pm4_wrptr_dec : 1; | 351 | unsigned long mask_pm4_wrptr_dec : 1; |
328 | unsigned long dis_mc_clean_cond : 1; | 352 | unsigned long dis_mc_clean_cond : 1; |
329 | unsigned long err_two_reqi_during_ful : 1; | 353 | unsigned long err_two_reqi_during_ful : 1; |
330 | unsigned long err_reqi_during_idle_clk : 1; | 354 | unsigned long err_reqi_during_idle_clk : 1; |
331 | unsigned long err_global : 1; | 355 | unsigned long err_global : 1; |
332 | unsigned long en_wr_buf_dbg_load : 1; | 356 | unsigned long en_wr_buf_dbg_load : 1; |
333 | unsigned long en_wr_buf_dbg_path : 1; | 357 | unsigned long en_wr_buf_dbg_path : 1; |
334 | unsigned long sel_wr_buf_byte : 3; | 358 | unsigned long sel_wr_buf_byte : 3; |
335 | unsigned long dis_rd_flush_wr : 1; | 359 | unsigned long dis_rd_flush_wr : 1; |
336 | unsigned long dis_packer_ful_cond : 1; | 360 | unsigned long dis_packer_ful_cond : 1; |
337 | unsigned long dis_invalidate_by_ops_chnl : 1; | 361 | unsigned long dis_invalidate_by_ops_chnl : 1; |
338 | unsigned long en_halt_when_reqi_err : 1; | 362 | unsigned long en_halt_when_reqi_err : 1; |
339 | unsigned long cif_spare_2 : 5; | 363 | unsigned long cif_spare_2 : 5; |
340 | unsigned long : 1; | 364 | unsigned long : 1; |
341 | } __attribute__((packed)); | 365 | } __attribute__((packed)); |
342 | 366 | ||
343 | union cif_write_dbg_u { | 367 | union cif_write_dbg_u { |
344 | unsigned long val : 32; | 368 | unsigned long val : 32; |
345 | struct cif_write_dbg_t f; | 369 | struct cif_write_dbg_t f; |
346 | } __attribute__((packed)); | 370 | } __attribute__((packed)); |
347 | 371 | ||
348 | 372 | ||
349 | struct intf_cntl_t { | 373 | struct intf_cntl_t { |
350 | unsigned char ad_inc_a : 1; | 374 | unsigned char ad_inc_a : 1; |
351 | unsigned char ring_buf_a : 1; | 375 | unsigned char ring_buf_a : 1; |
352 | unsigned char rd_fetch_trigger_a : 1; | 376 | unsigned char rd_fetch_trigger_a : 1; |
353 | unsigned char rd_data_rdy_a : 1; | 377 | unsigned char rd_data_rdy_a : 1; |
354 | unsigned char ad_inc_b : 1; | 378 | unsigned char ad_inc_b : 1; |
355 | unsigned char ring_buf_b : 1; | 379 | unsigned char ring_buf_b : 1; |
356 | unsigned char rd_fetch_trigger_b : 1; | 380 | unsigned char rd_fetch_trigger_b : 1; |
357 | unsigned char rd_data_rdy_b : 1; | 381 | unsigned char rd_data_rdy_b : 1; |
358 | } __attribute__((packed)); | 382 | } __attribute__((packed)); |
359 | 383 | ||
360 | union intf_cntl_u { | 384 | union intf_cntl_u { |
361 | unsigned char val : 8; | 385 | unsigned char val : 8; |
362 | struct intf_cntl_t f; | 386 | struct intf_cntl_t f; |
363 | } __attribute__((packed)); | 387 | } __attribute__((packed)); |
364 | 388 | ||
365 | struct cpu_defaults_t { | 389 | struct cpu_defaults_t { |
366 | unsigned char unpack_rd_data : 1; | 390 | unsigned char unpack_rd_data : 1; |
367 | unsigned char access_ind_addr_a: 1; | 391 | unsigned char access_ind_addr_a : 1; |
368 | unsigned char access_ind_addr_b: 1; | 392 | unsigned char access_ind_addr_b : 1; |
369 | unsigned char access_scratch_reg : 1; | 393 | unsigned char access_scratch_reg : 1; |
370 | unsigned char pack_wr_data : 1; | 394 | unsigned char pack_wr_data : 1; |
371 | unsigned char transition_size : 1; | 395 | unsigned char transition_size : 1; |
372 | unsigned char en_read_buf_mode : 1; | 396 | unsigned char en_read_buf_mode : 1; |
373 | unsigned char rd_fetch_scratch : 1; | 397 | unsigned char rd_fetch_scratch : 1; |
374 | } __attribute__((packed)); | 398 | } __attribute__((packed)); |
375 | 399 | ||
376 | union cpu_defaults_u { | 400 | union cpu_defaults_u { |
377 | unsigned char val : 8; | 401 | unsigned char val : 8; |
378 | struct cpu_defaults_t f; | 402 | struct cpu_defaults_t f; |
403 | } __attribute__((packed)); | ||
404 | |||
405 | struct crtc_total_t { | ||
406 | unsigned long crtc_h_total : 10; | ||
407 | unsigned long : 6; | ||
408 | unsigned long crtc_v_total : 10; | ||
409 | unsigned long : 6; | ||
410 | } __attribute__((packed)); | ||
411 | |||
412 | union crtc_total_u { | ||
413 | unsigned long val : 32; | ||
414 | struct crtc_total_t f; | ||
415 | } __attribute__((packed)); | ||
416 | |||
417 | struct crtc_ss_t { | ||
418 | unsigned long ss_start : 10; | ||
419 | unsigned long : 6; | ||
420 | unsigned long ss_end : 10; | ||
421 | unsigned long : 2; | ||
422 | unsigned long ss_align : 1; | ||
423 | unsigned long ss_pol : 1; | ||
424 | unsigned long ss_run_mode : 1; | ||
425 | unsigned long ss_en : 1; | ||
426 | } __attribute__((packed)); | ||
427 | |||
428 | union crtc_ss_u { | ||
429 | unsigned long val : 32; | ||
430 | struct crtc_ss_t f; | ||
431 | } __attribute__((packed)); | ||
432 | |||
433 | struct active_h_disp_t { | ||
434 | unsigned long active_h_start : 10; | ||
435 | unsigned long : 6; | ||
436 | unsigned long active_h_end : 10; | ||
437 | unsigned long : 6; | ||
438 | } __attribute__((packed)); | ||
439 | |||
440 | union active_h_disp_u { | ||
441 | unsigned long val : 32; | ||
442 | struct active_h_disp_t f; | ||
443 | } __attribute__((packed)); | ||
444 | |||
445 | struct active_v_disp_t { | ||
446 | unsigned long active_v_start : 10; | ||
447 | unsigned long : 6; | ||
448 | unsigned long active_v_end : 10; | ||
449 | unsigned long : 6; | ||
450 | } __attribute__((packed)); | ||
451 | |||
452 | union active_v_disp_u { | ||
453 | unsigned long val : 32; | ||
454 | struct active_v_disp_t f; | ||
455 | } __attribute__((packed)); | ||
456 | |||
457 | struct graphic_h_disp_t { | ||
458 | unsigned long graphic_h_start : 10; | ||
459 | unsigned long : 6; | ||
460 | unsigned long graphic_h_end : 10; | ||
461 | unsigned long : 6; | ||
462 | } __attribute__((packed)); | ||
463 | |||
464 | union graphic_h_disp_u { | ||
465 | unsigned long val : 32; | ||
466 | struct graphic_h_disp_t f; | ||
467 | } __attribute__((packed)); | ||
468 | |||
469 | struct graphic_v_disp_t { | ||
470 | unsigned long graphic_v_start : 10; | ||
471 | unsigned long : 6; | ||
472 | unsigned long graphic_v_end : 10; | ||
473 | unsigned long : 6; | ||
474 | } __attribute__((packed)); | ||
475 | |||
476 | union graphic_v_disp_u{ | ||
477 | unsigned long val : 32; | ||
478 | struct graphic_v_disp_t f; | ||
479 | } __attribute__((packed)); | ||
480 | |||
481 | struct graphic_ctrl_t_w100 { | ||
482 | unsigned long color_depth : 3; | ||
483 | unsigned long portrait_mode : 2; | ||
484 | unsigned long low_power_on : 1; | ||
485 | unsigned long req_freq : 4; | ||
486 | unsigned long en_crtc : 1; | ||
487 | unsigned long en_graphic_req : 1; | ||
488 | unsigned long en_graphic_crtc : 1; | ||
489 | unsigned long total_req_graphic : 9; | ||
490 | unsigned long lcd_pclk_on : 1; | ||
491 | unsigned long lcd_sclk_on : 1; | ||
492 | unsigned long pclk_running : 1; | ||
493 | unsigned long sclk_running : 1; | ||
494 | unsigned long : 6; | ||
495 | } __attribute__((packed)); | ||
496 | |||
497 | struct graphic_ctrl_t_w32xx { | ||
498 | unsigned long color_depth : 3; | ||
499 | unsigned long portrait_mode : 2; | ||
500 | unsigned long low_power_on : 1; | ||
501 | unsigned long req_freq : 4; | ||
502 | unsigned long en_crtc : 1; | ||
503 | unsigned long en_graphic_req : 1; | ||
504 | unsigned long en_graphic_crtc : 1; | ||
505 | unsigned long total_req_graphic : 10; | ||
506 | unsigned long lcd_pclk_on : 1; | ||
507 | unsigned long lcd_sclk_on : 1; | ||
508 | unsigned long pclk_running : 1; | ||
509 | unsigned long sclk_running : 1; | ||
510 | unsigned long : 5; | ||
511 | } __attribute__((packed)); | ||
512 | |||
513 | union graphic_ctrl_u { | ||
514 | unsigned long val : 32; | ||
515 | struct graphic_ctrl_t_w100 f_w100; | ||
516 | struct graphic_ctrl_t_w32xx f_w32xx; | ||
379 | } __attribute__((packed)); | 517 | } __attribute__((packed)); |
380 | 518 | ||
381 | struct video_ctrl_t { | 519 | struct video_ctrl_t { |
382 | unsigned long video_mode : 1; | 520 | unsigned long video_mode : 1; |
383 | unsigned long keyer_en : 1; | 521 | unsigned long keyer_en : 1; |
384 | unsigned long en_video_req : 1; | 522 | unsigned long en_video_req : 1; |
385 | unsigned long en_graphic_req_video : 1; | 523 | unsigned long en_graphic_req_video : 1; |
386 | unsigned long en_video_crtc : 1; | 524 | unsigned long en_video_crtc : 1; |
387 | unsigned long video_hor_exp : 2; | 525 | unsigned long video_hor_exp : 2; |
388 | unsigned long video_ver_exp : 2; | 526 | unsigned long video_ver_exp : 2; |
389 | unsigned long uv_combine : 1; | 527 | unsigned long uv_combine : 1; |
390 | unsigned long total_req_video : 9; | 528 | unsigned long total_req_video : 9; |
391 | unsigned long video_ch_sel : 1; | 529 | unsigned long video_ch_sel : 1; |
392 | unsigned long video_portrait : 2; | 530 | unsigned long video_portrait : 2; |
393 | unsigned long yuv2rgb_en : 1; | 531 | unsigned long yuv2rgb_en : 1; |
394 | unsigned long yuv2rgb_option : 1; | 532 | unsigned long yuv2rgb_option : 1; |
395 | unsigned long video_inv_hor : 1; | 533 | unsigned long video_inv_hor : 1; |
396 | unsigned long video_inv_ver : 1; | 534 | unsigned long video_inv_ver : 1; |
397 | unsigned long gamma_sel : 2; | 535 | unsigned long gamma_sel : 2; |
398 | unsigned long dis_limit : 1; | 536 | unsigned long dis_limit : 1; |
399 | unsigned long en_uv_hblend : 1; | 537 | unsigned long en_uv_hblend : 1; |
400 | unsigned long rgb_gamma_sel : 2; | 538 | unsigned long rgb_gamma_sel : 2; |
401 | } __attribute__((packed)); | 539 | } __attribute__((packed)); |
402 | 540 | ||
403 | union video_ctrl_u { | 541 | union video_ctrl_u { |
404 | unsigned long val : 32; | 542 | unsigned long val : 32; |
405 | struct video_ctrl_t f; | 543 | struct video_ctrl_t f; |
406 | } __attribute__((packed)); | 544 | } __attribute__((packed)); |
407 | 545 | ||
408 | struct disp_db_buf_cntl_rd_t { | 546 | struct disp_db_buf_cntl_rd_t { |
409 | unsigned long en_db_buf : 1; | 547 | unsigned long en_db_buf : 1; |
410 | unsigned long update_db_buf_done : 1; | 548 | unsigned long update_db_buf_done : 1; |
411 | unsigned long db_buf_cntl : 6; | 549 | unsigned long db_buf_cntl : 6; |
412 | unsigned long : 24; | 550 | unsigned long : 24; |
413 | } __attribute__((packed)); | 551 | } __attribute__((packed)); |
414 | 552 | ||
415 | union disp_db_buf_cntl_rd_u { | 553 | union disp_db_buf_cntl_rd_u { |
416 | unsigned long val : 32; | 554 | unsigned long val : 32; |
417 | struct disp_db_buf_cntl_rd_t f; | 555 | struct disp_db_buf_cntl_rd_t f; |
418 | } __attribute__((packed)); | 556 | } __attribute__((packed)); |
419 | 557 | ||
420 | struct disp_db_buf_cntl_wr_t { | 558 | struct disp_db_buf_cntl_wr_t { |
421 | unsigned long en_db_buf : 1; | 559 | unsigned long en_db_buf : 1; |
422 | unsigned long update_db_buf : 1; | 560 | unsigned long update_db_buf : 1; |
423 | unsigned long db_buf_cntl : 6; | 561 | unsigned long db_buf_cntl : 6; |
424 | unsigned long : 24; | 562 | unsigned long : 24; |
425 | } __attribute__((packed)); | 563 | } __attribute__((packed)); |
426 | 564 | ||
427 | union disp_db_buf_cntl_wr_u { | 565 | union disp_db_buf_cntl_wr_u { |
428 | unsigned long val : 32; | 566 | unsigned long val : 32; |
429 | struct disp_db_buf_cntl_wr_t f; | 567 | struct disp_db_buf_cntl_wr_t f; |
430 | } __attribute__((packed)); | 568 | } __attribute__((packed)); |
431 | 569 | ||
432 | struct gamma_value1_t { | 570 | struct gamma_value1_t { |
433 | unsigned long gamma1 : 8; | 571 | unsigned long gamma1 : 8; |
434 | unsigned long gamma2 : 8; | 572 | unsigned long gamma2 : 8; |
435 | unsigned long gamma3 : 8; | 573 | unsigned long gamma3 : 8; |
436 | unsigned long gamma4 : 8; | 574 | unsigned long gamma4 : 8; |
437 | } __attribute__((packed)); | 575 | } __attribute__((packed)); |
438 | 576 | ||
439 | union gamma_value1_u { | 577 | union gamma_value1_u { |
440 | unsigned long val : 32; | 578 | unsigned long val : 32; |
441 | struct gamma_value1_t f; | 579 | struct gamma_value1_t f; |
442 | } __attribute__((packed)); | 580 | } __attribute__((packed)); |
443 | 581 | ||
444 | struct gamma_value2_t { | 582 | struct gamma_value2_t { |
445 | unsigned long gamma5 : 8; | 583 | unsigned long gamma5 : 8; |
446 | unsigned long gamma6 : 8; | 584 | unsigned long gamma6 : 8; |
447 | unsigned long gamma7 : 8; | 585 | unsigned long gamma7 : 8; |
448 | unsigned long gamma8 : 8; | 586 | unsigned long gamma8 : 8; |
449 | } __attribute__((packed)); | 587 | } __attribute__((packed)); |
450 | 588 | ||
451 | union gamma_value2_u { | 589 | union gamma_value2_u { |
452 | unsigned long val : 32; | 590 | unsigned long val : 32; |
453 | struct gamma_value2_t f; | 591 | struct gamma_value2_t f; |
454 | } __attribute__((packed)); | 592 | } __attribute__((packed)); |
455 | 593 | ||
456 | struct gamma_slope_t { | 594 | struct gamma_slope_t { |
457 | unsigned long slope1 : 3; | 595 | unsigned long slope1 : 3; |
458 | unsigned long slope2 : 3; | 596 | unsigned long slope2 : 3; |
459 | unsigned long slope3 : 3; | 597 | unsigned long slope3 : 3; |
460 | unsigned long slope4 : 3; | 598 | unsigned long slope4 : 3; |
461 | unsigned long slope5 : 3; | 599 | unsigned long slope5 : 3; |
462 | unsigned long slope6 : 3; | 600 | unsigned long slope6 : 3; |
463 | unsigned long slope7 : 3; | 601 | unsigned long slope7 : 3; |
464 | unsigned long slope8 : 3; | 602 | unsigned long slope8 : 3; |
465 | unsigned long : 8; | 603 | unsigned long : 8; |
466 | } __attribute__((packed)); | 604 | } __attribute__((packed)); |
467 | 605 | ||
468 | union gamma_slope_u { | 606 | union gamma_slope_u { |
469 | unsigned long val : 32; | 607 | unsigned long val : 32; |
470 | struct gamma_slope_t f; | 608 | struct gamma_slope_t f; |
471 | } __attribute__((packed)); | 609 | } __attribute__((packed)); |
472 | 610 | ||
473 | struct mc_ext_mem_location_t { | 611 | struct mc_ext_mem_location_t { |
474 | unsigned long mc_ext_mem_start : 16; | 612 | unsigned long mc_ext_mem_start : 16; |
475 | unsigned long mc_ext_mem_top : 16; | 613 | unsigned long mc_ext_mem_top : 16; |
476 | } __attribute__((packed)); | 614 | } __attribute__((packed)); |
477 | 615 | ||
478 | union mc_ext_mem_location_u { | 616 | union mc_ext_mem_location_u { |
479 | unsigned long val : 32; | 617 | unsigned long val : 32; |
480 | struct mc_ext_mem_location_t f; | 618 | struct mc_ext_mem_location_t f; |
619 | } __attribute__((packed)); | ||
620 | |||
621 | struct mc_fb_location_t { | ||
622 | unsigned long mc_fb_start : 16; | ||
623 | unsigned long mc_fb_top : 16; | ||
624 | } __attribute__((packed)); | ||
625 | |||
626 | union mc_fb_location_u { | ||
627 | unsigned long val : 32; | ||
628 | struct mc_fb_location_t f; | ||
481 | } __attribute__((packed)); | 629 | } __attribute__((packed)); |
482 | 630 | ||
483 | struct clk_pin_cntl_t { | 631 | struct clk_pin_cntl_t { |
484 | unsigned long osc_en : 1; | 632 | unsigned long osc_en : 1; |
485 | unsigned long osc_gain : 5; | 633 | unsigned long osc_gain : 5; |
486 | unsigned long dont_use_xtalin : 1; | 634 | unsigned long dont_use_xtalin : 1; |
487 | unsigned long xtalin_pm_en : 1; | 635 | unsigned long xtalin_pm_en : 1; |
488 | unsigned long xtalin_dbl_en : 1; | 636 | unsigned long xtalin_dbl_en : 1; |
489 | unsigned long : 7; | 637 | unsigned long : 7; |
490 | unsigned long cg_debug : 16; | 638 | unsigned long cg_debug : 16; |
491 | } __attribute__((packed)); | 639 | } __attribute__((packed)); |
492 | 640 | ||
493 | union clk_pin_cntl_u { | 641 | union clk_pin_cntl_u { |
494 | unsigned long val : 32; | 642 | unsigned long val : 32; |
495 | struct clk_pin_cntl_t f; | 643 | struct clk_pin_cntl_t f; |
496 | } __attribute__((packed)); | 644 | } __attribute__((packed)); |
497 | 645 | ||
498 | struct pll_ref_fb_div_t { | 646 | struct pll_ref_fb_div_t { |
499 | unsigned long pll_ref_div : 4; | 647 | unsigned long pll_ref_div : 4; |
500 | unsigned long : 4; | 648 | unsigned long : 4; |
501 | unsigned long pll_fb_div_int : 6; | 649 | unsigned long pll_fb_div_int : 6; |
502 | unsigned long : 2; | 650 | unsigned long : 2; |
503 | unsigned long pll_fb_div_frac : 3; | 651 | unsigned long pll_fb_div_frac : 3; |
504 | unsigned long : 1; | 652 | unsigned long : 1; |
505 | unsigned long pll_reset_time : 4; | 653 | unsigned long pll_reset_time : 4; |
506 | unsigned long pll_lock_time : 8; | 654 | unsigned long pll_lock_time : 8; |
507 | } __attribute__((packed)); | 655 | } __attribute__((packed)); |
508 | 656 | ||
509 | union pll_ref_fb_div_u { | 657 | union pll_ref_fb_div_u { |
510 | unsigned long val : 32; | 658 | unsigned long val : 32; |
511 | struct pll_ref_fb_div_t f; | 659 | struct pll_ref_fb_div_t f; |
512 | } __attribute__((packed)); | 660 | } __attribute__((packed)); |
513 | 661 | ||
514 | struct pll_cntl_t { | 662 | struct pll_cntl_t { |
515 | unsigned long pll_pwdn : 1; | 663 | unsigned long pll_pwdn : 1; |
516 | unsigned long pll_reset : 1; | 664 | unsigned long pll_reset : 1; |
517 | unsigned long pll_pm_en : 1; | 665 | unsigned long pll_pm_en : 1; |
518 | unsigned long pll_mode : 1; | 666 | unsigned long pll_mode : 1; |
519 | unsigned long pll_refclk_sel : 1; | 667 | unsigned long pll_refclk_sel : 1; |
520 | unsigned long pll_fbclk_sel : 1; | 668 | unsigned long pll_fbclk_sel : 1; |
521 | unsigned long pll_tcpoff : 1; | 669 | unsigned long pll_tcpoff : 1; |
522 | unsigned long pll_pcp : 3; | 670 | unsigned long pll_pcp : 3; |
523 | unsigned long pll_pvg : 3; | 671 | unsigned long pll_pvg : 3; |
524 | unsigned long pll_vcofr : 1; | 672 | unsigned long pll_vcofr : 1; |
525 | unsigned long pll_ioffset : 2; | 673 | unsigned long pll_ioffset : 2; |
526 | unsigned long pll_pecc_mode : 2; | 674 | unsigned long pll_pecc_mode : 2; |
527 | unsigned long pll_pecc_scon : 2; | 675 | unsigned long pll_pecc_scon : 2; |
528 | unsigned long pll_dactal : 4; | 676 | unsigned long pll_dactal : 4; |
529 | unsigned long pll_cp_clip : 2; | 677 | unsigned long pll_cp_clip : 2; |
530 | unsigned long pll_conf : 3; | 678 | unsigned long pll_conf : 3; |
531 | unsigned long pll_mbctrl : 2; | 679 | unsigned long pll_mbctrl : 2; |
532 | unsigned long pll_ring_off : 1; | 680 | unsigned long pll_ring_off : 1; |
533 | } __attribute__((packed)); | 681 | } __attribute__((packed)); |
534 | 682 | ||
535 | union pll_cntl_u { | 683 | union pll_cntl_u { |
536 | unsigned long val : 32; | 684 | unsigned long val : 32; |
537 | struct pll_cntl_t f; | 685 | struct pll_cntl_t f; |
538 | } __attribute__((packed)); | 686 | } __attribute__((packed)); |
539 | 687 | ||
540 | struct sclk_cntl_t { | 688 | struct sclk_cntl_t { |
541 | unsigned long sclk_src_sel : 2; | 689 | unsigned long sclk_src_sel : 2; |
542 | unsigned long : 2; | 690 | unsigned long : 2; |
543 | unsigned long sclk_post_div_fast : 4; | 691 | unsigned long sclk_post_div_fast : 4; |
544 | unsigned long sclk_clkon_hys : 3; | 692 | unsigned long sclk_clkon_hys : 3; |
545 | unsigned long sclk_post_div_slow : 4; | 693 | unsigned long sclk_post_div_slow : 4; |
546 | unsigned long disp_cg_ok2switch_en : 1; | 694 | unsigned long disp_cg_ok2switch_en : 1; |
547 | unsigned long sclk_force_reg : 1; | 695 | unsigned long sclk_force_reg : 1; |
548 | unsigned long sclk_force_disp : 1; | 696 | unsigned long sclk_force_disp : 1; |
549 | unsigned long sclk_force_mc : 1; | 697 | unsigned long sclk_force_mc : 1; |
550 | unsigned long sclk_force_extmc : 1; | 698 | unsigned long sclk_force_extmc : 1; |
551 | unsigned long sclk_force_cp : 1; | 699 | unsigned long sclk_force_cp : 1; |
552 | unsigned long sclk_force_e2 : 1; | 700 | unsigned long sclk_force_e2 : 1; |
553 | unsigned long sclk_force_e3 : 1; | 701 | unsigned long sclk_force_e3 : 1; |
554 | unsigned long sclk_force_idct : 1; | 702 | unsigned long sclk_force_idct : 1; |
555 | unsigned long sclk_force_bist : 1; | 703 | unsigned long sclk_force_bist : 1; |
556 | unsigned long busy_extend_cp : 1; | 704 | unsigned long busy_extend_cp : 1; |
557 | unsigned long busy_extend_e2 : 1; | 705 | unsigned long busy_extend_e2 : 1; |
558 | unsigned long busy_extend_e3 : 1; | 706 | unsigned long busy_extend_e3 : 1; |
559 | unsigned long busy_extend_idct : 1; | 707 | unsigned long busy_extend_idct : 1; |
560 | unsigned long : 3; | 708 | unsigned long : 3; |
561 | } __attribute__((packed)); | 709 | } __attribute__((packed)); |
562 | 710 | ||
563 | union sclk_cntl_u { | 711 | union sclk_cntl_u { |
564 | unsigned long val : 32; | 712 | unsigned long val : 32; |
565 | struct sclk_cntl_t f; | 713 | struct sclk_cntl_t f; |
566 | } __attribute__((packed)); | 714 | } __attribute__((packed)); |
567 | 715 | ||
568 | struct pclk_cntl_t { | 716 | struct pclk_cntl_t { |
569 | unsigned long pclk_src_sel : 2; | 717 | unsigned long pclk_src_sel : 2; |
570 | unsigned long : 2; | 718 | unsigned long : 2; |
571 | unsigned long pclk_post_div : 4; | 719 | unsigned long pclk_post_div : 4; |
572 | unsigned long : 8; | 720 | unsigned long : 8; |
573 | unsigned long pclk_force_disp : 1; | 721 | unsigned long pclk_force_disp : 1; |
574 | unsigned long : 15; | 722 | unsigned long : 15; |
575 | } __attribute__((packed)); | 723 | } __attribute__((packed)); |
576 | 724 | ||
577 | union pclk_cntl_u { | 725 | union pclk_cntl_u { |
578 | unsigned long val : 32; | 726 | unsigned long val : 32; |
579 | struct pclk_cntl_t f; | 727 | struct pclk_cntl_t f; |
580 | } __attribute__((packed)); | 728 | } __attribute__((packed)); |
581 | 729 | ||
730 | |||
731 | #define TESTCLK_SRC_PLL 0x01 | ||
732 | #define TESTCLK_SRC_SCLK 0x02 | ||
733 | #define TESTCLK_SRC_PCLK 0x03 | ||
734 | /* 4 and 5 seem to by XTAL/M */ | ||
735 | #define TESTCLK_SRC_XTAL 0x06 | ||
736 | |||
582 | struct clk_test_cntl_t { | 737 | struct clk_test_cntl_t { |
583 | unsigned long testclk_sel : 4; | 738 | unsigned long testclk_sel : 4; |
584 | unsigned long : 3; | 739 | unsigned long : 3; |
585 | unsigned long start_check_freq : 1; | 740 | unsigned long start_check_freq : 1; |
586 | unsigned long tstcount_rst : 1; | 741 | unsigned long tstcount_rst : 1; |
587 | unsigned long : 15; | 742 | unsigned long : 15; |
588 | unsigned long test_count : 8; | 743 | unsigned long test_count : 8; |
589 | } __attribute__((packed)); | 744 | } __attribute__((packed)); |
590 | 745 | ||
591 | union clk_test_cntl_u { | 746 | union clk_test_cntl_u { |
592 | unsigned long val : 32; | 747 | unsigned long val : 32; |
593 | struct clk_test_cntl_t f; | 748 | struct clk_test_cntl_t f; |
594 | } __attribute__((packed)); | 749 | } __attribute__((packed)); |
595 | 750 | ||
596 | struct pwrmgt_cntl_t { | 751 | struct pwrmgt_cntl_t { |
597 | unsigned long pwm_enable : 1; | 752 | unsigned long pwm_enable : 1; |
598 | unsigned long : 1; | 753 | unsigned long : 1; |
599 | unsigned long pwm_mode_req : 2; | 754 | unsigned long pwm_mode_req : 2; |
600 | unsigned long pwm_wakeup_cond : 2; | 755 | unsigned long pwm_wakeup_cond : 2; |
601 | unsigned long pwm_fast_noml_hw_en : 1; | 756 | unsigned long pwm_fast_noml_hw_en : 1; |
602 | unsigned long pwm_noml_fast_hw_en : 1; | 757 | unsigned long pwm_noml_fast_hw_en : 1; |
603 | unsigned long pwm_fast_noml_cond : 4; | 758 | unsigned long pwm_fast_noml_cond : 4; |
604 | unsigned long pwm_noml_fast_cond : 4; | 759 | unsigned long pwm_noml_fast_cond : 4; |
605 | unsigned long pwm_idle_timer : 8; | 760 | unsigned long pwm_idle_timer : 8; |
606 | unsigned long pwm_busy_timer : 8; | 761 | unsigned long pwm_busy_timer : 8; |
607 | } __attribute__((packed)); | 762 | } __attribute__((packed)); |
608 | 763 | ||
609 | union pwrmgt_cntl_u { | 764 | union pwrmgt_cntl_u { |
610 | unsigned long val : 32; | 765 | unsigned long val : 32; |
611 | struct pwrmgt_cntl_t f; | 766 | struct pwrmgt_cntl_t f; |
612 | } __attribute__((packed)); | 767 | } __attribute__((packed)); |
613 | 768 | ||
614 | #endif | 769 | #endif |