X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fchar%2Fhvc_vio.c;h=79711aa4b41d4ae85de49cf8bddad9a0c50ded18;hb=8888735fcaac7681dbcca67fbcc88cf627c47b3a;hp=d2928f90ab5149d3f64f4ad2404d90040aa5115b;hpb=acad9559f1054487292eb10d7bb81f256e9d8f2d;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index d2928f9..79711aa 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c @@ -31,18 +31,57 @@ #include #include + #include #include #include +#include + +#include "hvc_console.h" char hvc_driver_name[] = "hvc_console"; static struct vio_device_id hvc_driver_table[] __devinitdata = { {"serial", "hvterm1"}, - { NULL, } + { "", "" } }; MODULE_DEVICE_TABLE(vio, hvc_driver_table); +static int filtered_get_chars(uint32_t vtermno, char *buf, int count) +{ + unsigned long got; + int i; + + /* + * Vio firmware will read up to SIZE_VIO_GET_CHARS at its own discretion + * so we play safe and avoid the situation where got > count which could + * overload the flip buffer. + */ + if (count < SIZE_VIO_GET_CHARS) + return -EAGAIN; + + got = hvc_get_chars(vtermno, buf, count); + + /* + * Work around a HV bug where it gives us a null + * after every \r. -- paulus + */ + for (i = 1; i < got; ++i) { + if (buf[i] == 0 && buf[i-1] == '\r') { + --got; + if (i < got) + memmove(&buf[i], &buf[i+1], + got - i); + } + } + return got; +} + +static struct hv_ops hvc_get_put_ops = { + .get_chars = filtered_get_chars, + .put_chars = hvc_put_chars, +}; + static int __devinit hvc_vio_probe(struct vio_dev *vdev, const struct vio_device_id *id) { @@ -52,7 +91,8 @@ static int __devinit hvc_vio_probe(struct vio_dev *vdev, if (!vdev || !id) return -EPERM; - hp = hvc_alloc(vdev->unit_address, vdev->irq); + hp = hvc_alloc(vdev->unit_address, vdev->irq, &hvc_get_put_ops, + MAX_VIO_PUT_CHARS); if (IS_ERR(hp)) return PTR_ERR(hp); dev_set_drvdata(&vdev->dev, hp); @@ -68,11 +108,11 @@ static int __devexit hvc_vio_remove(struct vio_dev *vdev) } static struct vio_driver hvc_vio_driver = { - .name = hvc_driver_name, .id_table = hvc_driver_table, .probe = hvc_vio_probe, .remove = hvc_vio_remove, .driver = { + .name = hvc_driver_name, .owner = THIS_MODULE, } }; @@ -81,6 +121,9 @@ static int hvc_vio_init(void) { int rc; + if (firmware_has_feature(FW_FEATURE_ISERIES)) + return -EIO; + /* Register as a vio device to receive callbacks */ rc = vio_register_driver(&hvc_vio_driver); @@ -102,7 +145,7 @@ static int hvc_find_vtys(void) for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL; vty = of_find_node_by_name(vty, "vty")) { - uint32_t *vtermno; + const uint32_t *vtermno; /* We have statically defined space for only a certain number * of console adapters. @@ -110,12 +153,12 @@ static int hvc_find_vtys(void) if (num_found >= MAX_NR_HVC_CONSOLES) break; - vtermno = (uint32_t *)get_property(vty, "reg", NULL); + vtermno = of_get_property(vty, "reg", NULL); if (!vtermno) continue; - if (device_is_compatible(vty, "hvterm1")) { - hvc_instantiate(*vtermno, num_found); + if (of_device_is_compatible(vty, "hvterm1")) { + hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops); ++num_found; } }