Jan Kiszka wrote:
> CHABAL David wrote:
>> Le 11/5/2007, "Jan Kiszka" <[EMAIL PROTECTED]> a écrit:
>>
>>> Maksym Veremeyenko wrote:
>>>> CHABAL David пишет:
>>>>
>>>>> I met some trouble with the 16550A driver provided in Xenomai 2.3.1
>>>>> and my Moxa cards (PCI / 8 * RS232 / 168U ).
>>>>>
>>>>> It was a problem of baudrate computation before setting the LCR_DLAB
>>>>> register.
>>>>>
>>>>> The formula implemented by the Xenomai driver is different from the one
>>>>> provided by Moxa. So I copy/paste the formula from the mxser.c file
>>>>> (present in the
>>>>> kernel distro), and it seems to work fine.
>>>>>
>>>>> I think it's Moxa card dependant, may be caused by the high default baud
>>>>> rate of this card.
>>>> I have two Moxa boards with no problem, possible you need to specify 
>>>> 'baud_base' param.
>>>>
>>>> I my case :
>>>>
>>>> # 8 ports board:
>>>> /sbin/modprobe xeno_16550A \
>>>> ioaddr=0x1000,0x1008,0x1010,0x1018,0x1020,0x1028,0x1030,0x1038 \
>>>> irq=9,9,9,9,9,9,9,9 \
>>>> baud_base=921600,921600,921600,921600,921600,921600,921600,921600
>>>>
>>>> # 2 ports board + onboards:
>>>> /sbin/modprobe xeno_16550A ioaddr=0x3f8,0x2f8,0xdf00,0xdf08 
>>>> irq=4,3,11,11 baud_base=115200,115200,921600,921600
>>>>
>>> Interesting. That would leave us just with the generic fix to catch
>>> baud_rate==0. Far more attractive. :)
>>>
>>> David, can you confirm this? Weren't you just aware of the baud_base
>>> parameter?
>> I'm not totally convinced because if I compute by hand the DLAB register
>> with the 19200 value (my config):
>>
>> With the moxa driver:
>>   baud_div = 912.600 / 19.200 = 47
>>
>> With the Xeno driver:
>>   baud_div = (912.600 - 9600) / 19.200 = 47
>>
>> Grrr, it's ok here because the rounded values are the same because the
>> baud base is biggest than the speed requested, but I think a problem can
>> occur with 115200 or more, example:
>>
>> moxa: 912.600/115.200 = 8
>> xeno: = 7
> 
> Yeah, hard arguments. This really cries for a moxa tweak. (The
> alternative would be to pass an artificially increased baud_base - but
> that would be _really_ ugly and we could also ask the user for the
> divider directly...)

Here we go. This patch should add the most essential changes of your
patch to SVN trunk (backport not officially planned, but it should not
be tricky). The idea is to pass "variant=1" to xeno_16550A on load.
That will kick out rounding on divider calculation and even switches
the default baud base.

Comments/test reports welcome.

Jan


Index: ksrc/drivers/serial/16550A.c
===================================================================
--- ksrc/drivers/serial/16550A.c        (Revision 2433)
+++ ksrc/drivers/serial/16550A.c        (Arbeitskopie)
@@ -28,10 +28,14 @@
 
 #define MAX_DEVICES            8
 
+#define VARIANT_STANDARD       0
+#define VARIANT_MOXA           1
+
 #define IN_BUFFER_SIZE         4096
 #define OUT_BUFFER_SIZE                4096
 
 #define DEFAULT_BAUD_BASE      115200
+#define DEFAULT_BAUD_BASE_MOXA 921600
 #define DEFAULT_TX_FIFO                16
 
 #define PARITY_MASK            0x03
@@ -121,11 +125,13 @@ static struct rtdm_device *device[MAX_DE
 static unsigned int irq[MAX_DEVICES];
 static unsigned int baud_base[MAX_DEVICES];
 static int tx_fifo[MAX_DEVICES];
+static int variant[MAX_DEVICES];
 static unsigned int start_index;
 
 compat_module_param_array(irq, uint, MAX_DEVICES, 0400);
 compat_module_param_array(baud_base, uint, MAX_DEVICES, 0400);
 compat_module_param_array(tx_fifo, int, MAX_DEVICES, 0400);
+compat_module_param_array(variant, int, MAX_DEVICES, 0400);
 
 MODULE_PARM_DESC(irq, "IRQ numbers of the serial devices");
 MODULE_PARM_DESC(baud_base, "Maximum baud rate of the serial device "
@@ -302,20 +308,24 @@ static int rt_16550_set_config(struct rt
        rtdm_lockctx_t lock_ctx;
        unsigned long base = ctx->base_addr;
        int mode = rt_16550_io_mode_from_ctx(ctx);
-       int dev_id;
        int err = 0;
-       int baud_div = 0;
 
        /* make line configuration atomic and IRQ-safe */
        rtdm_lock_get_irqsave(&ctx->lock, lock_ctx);
 
        if (testbits(config->config_mask, RTSER_SET_BAUD)) {
-               dev_id = container_of(((void *)ctx), struct rtdm_dev_context,
-                                     dev_private)->device->device_id;
+               int dev_id = container_of(((void *)ctx),
+                                         struct rtdm_dev_context,
+                                         dev_private)->device->device_id;
+               int rounding = ctx->config.baud_rate >> 1;
+               int baud_div = 0;
+
+               if (variant[dev_id] == VARIANT_MOXA)
+                       rounding = 0;
 
                ctx->config.baud_rate = config->baud_rate;
-               baud_div = (baud_base[dev_id] + (ctx->config.baud_rate >> 1)) /
-                   ctx->config.baud_rate;
+               baud_div = (baud_base[dev_id] + rounding) /
+                       ctx->config.baud_rate;
                rt_16550_reg_out(mode, base, LCR, LCR_DLAB);
                rt_16550_reg_out(mode, base, DLL, baud_div & 0xff);
                rt_16550_reg_out(mode, base, DLM, baud_div >> 8);
@@ -595,10 +605,10 @@ int rt_16550_ioctl(struct rtdm_dev_conte
 
                if (testbits(config->config_mask, RTSER_SET_BAUD) &&
                    (config->baud_rate >
-                    baud_base[context->device->device_id])) {
-                       /* the baudrate is to high for this port */
+                    baud_base[context->device->device_id] ||
+                    config->baud_rate <= 0))
+                       /* invalid baudrate for this port */
                        return -EINVAL;
-               }
 
                if (testbits(config->config_mask,
                             RTSER_SET_TIMESTAMP_HISTORY)) {
@@ -1164,7 +1174,8 @@ int __init rt_16550_init(void)
                        goto kfree_out;
 
                if (baud_base[i] == 0)
-                       baud_base[i] = DEFAULT_BAUD_BASE;
+                       baud_base[i] = (variant[i] == VARIANT_MOXA) ?
+                               DEFAULT_BAUD_BASE_MOXA : DEFAULT_BAUD_BASE;
 
                if (tx_fifo[i] == 0)
                        tx_fifo[i] = DEFAULT_TX_FIFO;

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Xenomai-core mailing list
Xenomai-core@gna.org
https://mail.gna.org/listinfo/xenomai-core

Reply via email to