diff options
Diffstat (limited to 'drivers/char/synclink_gt.c')
-rw-r--r-- | drivers/char/synclink_gt.c | 119 |
1 files changed, 78 insertions, 41 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index b4d1f4eea435..4e35d4181224 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -101,6 +101,7 @@ MODULE_LICENSE("GPL"); | |||
101 | 101 | ||
102 | static struct pci_device_id pci_table[] = { | 102 | static struct pci_device_id pci_table[] = { |
103 | {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, | 103 | {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, |
104 | {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT2_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, | ||
104 | {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, | 105 | {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, |
105 | {PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, | 106 | {PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, |
106 | {0,}, /* terminate list */ | 107 | {0,}, /* terminate list */ |
@@ -870,7 +871,7 @@ static int write(struct tty_struct *tty, | |||
870 | goto cleanup; | 871 | goto cleanup; |
871 | DBGINFO(("%s write count=%d\n", info->device_name, count)); | 872 | DBGINFO(("%s write count=%d\n", info->device_name, count)); |
872 | 873 | ||
873 | if (!tty || !info->tx_buf) | 874 | if (!info->tx_buf) |
874 | goto cleanup; | 875 | goto cleanup; |
875 | 876 | ||
876 | if (count > info->max_frame_size) { | 877 | if (count > info->max_frame_size) { |
@@ -924,7 +925,7 @@ static void put_char(struct tty_struct *tty, unsigned char ch) | |||
924 | if (sanity_check(info, tty->name, "put_char")) | 925 | if (sanity_check(info, tty->name, "put_char")) |
925 | return; | 926 | return; |
926 | DBGINFO(("%s put_char(%d)\n", info->device_name, ch)); | 927 | DBGINFO(("%s put_char(%d)\n", info->device_name, ch)); |
927 | if (!tty || !info->tx_buf) | 928 | if (!info->tx_buf) |
928 | return; | 929 | return; |
929 | spin_lock_irqsave(&info->lock,flags); | 930 | spin_lock_irqsave(&info->lock,flags); |
930 | if (!info->tx_active && (info->tx_count < info->max_frame_size)) | 931 | if (!info->tx_active && (info->tx_count < info->max_frame_size)) |
@@ -2515,7 +2516,8 @@ static int set_txidle(struct slgt_info *info, int idle_mode) | |||
2515 | DBGINFO(("%s set_txidle(%d)\n", info->device_name, idle_mode)); | 2516 | DBGINFO(("%s set_txidle(%d)\n", info->device_name, idle_mode)); |
2516 | spin_lock_irqsave(&info->lock,flags); | 2517 | spin_lock_irqsave(&info->lock,flags); |
2517 | info->idle_mode = idle_mode; | 2518 | info->idle_mode = idle_mode; |
2518 | tx_set_idle(info); | 2519 | if (info->params.mode != MGSL_MODE_ASYNC) |
2520 | tx_set_idle(info); | ||
2519 | spin_unlock_irqrestore(&info->lock,flags); | 2521 | spin_unlock_irqrestore(&info->lock,flags); |
2520 | return 0; | 2522 | return 0; |
2521 | } | 2523 | } |
@@ -3076,7 +3078,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3076 | 3078 | ||
3077 | static int alloc_tmp_rbuf(struct slgt_info *info) | 3079 | static int alloc_tmp_rbuf(struct slgt_info *info) |
3078 | { | 3080 | { |
3079 | info->tmp_rbuf = kmalloc(info->max_frame_size, GFP_KERNEL); | 3081 | info->tmp_rbuf = kmalloc(info->max_frame_size + 5, GFP_KERNEL); |
3080 | if (info->tmp_rbuf == NULL) | 3082 | if (info->tmp_rbuf == NULL) |
3081 | return -ENOMEM; | 3083 | return -ENOMEM; |
3082 | return 0; | 3084 | return 0; |
@@ -3276,6 +3278,9 @@ static void add_device(struct slgt_info *info) | |||
3276 | case SYNCLINK_GT_DEVICE_ID: | 3278 | case SYNCLINK_GT_DEVICE_ID: |
3277 | devstr = "GT"; | 3279 | devstr = "GT"; |
3278 | break; | 3280 | break; |
3281 | case SYNCLINK_GT2_DEVICE_ID: | ||
3282 | devstr = "GT2"; | ||
3283 | break; | ||
3279 | case SYNCLINK_GT4_DEVICE_ID: | 3284 | case SYNCLINK_GT4_DEVICE_ID: |
3280 | devstr = "GT4"; | 3285 | devstr = "GT4"; |
3281 | break; | 3286 | break; |
@@ -3353,7 +3358,9 @@ static void device_init(int adapter_num, struct pci_dev *pdev) | |||
3353 | int i; | 3358 | int i; |
3354 | int port_count = 1; | 3359 | int port_count = 1; |
3355 | 3360 | ||
3356 | if (pdev->device == SYNCLINK_GT4_DEVICE_ID) | 3361 | if (pdev->device == SYNCLINK_GT2_DEVICE_ID) |
3362 | port_count = 2; | ||
3363 | else if (pdev->device == SYNCLINK_GT4_DEVICE_ID) | ||
3357 | port_count = 4; | 3364 | port_count = 4; |
3358 | 3365 | ||
3359 | /* allocate device instances for all ports */ | 3366 | /* allocate device instances for all ports */ |
@@ -3940,8 +3947,6 @@ static void async_mode(struct slgt_info *info) | |||
3940 | 3947 | ||
3941 | msc_set_vcr(info); | 3948 | msc_set_vcr(info); |
3942 | 3949 | ||
3943 | tx_set_idle(info); | ||
3944 | |||
3945 | /* SCR (serial control) | 3950 | /* SCR (serial control) |
3946 | * | 3951 | * |
3947 | * 15 1=tx req on FIFO half empty | 3952 | * 15 1=tx req on FIFO half empty |
@@ -4012,7 +4017,7 @@ static void hdlc_mode(struct slgt_info *info) | |||
4012 | case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; | 4017 | case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; |
4013 | } | 4018 | } |
4014 | 4019 | ||
4015 | switch (info->params.crc_type) | 4020 | switch (info->params.crc_type & HDLC_CRC_MASK) |
4016 | { | 4021 | { |
4017 | case HDLC_CRC_16_CCITT: val |= BIT9; break; | 4022 | case HDLC_CRC_16_CCITT: val |= BIT9; break; |
4018 | case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; | 4023 | case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; |
@@ -4073,7 +4078,7 @@ static void hdlc_mode(struct slgt_info *info) | |||
4073 | case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; | 4078 | case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; |
4074 | } | 4079 | } |
4075 | 4080 | ||
4076 | switch (info->params.crc_type) | 4081 | switch (info->params.crc_type & HDLC_CRC_MASK) |
4077 | { | 4082 | { |
4078 | case HDLC_CRC_16_CCITT: val |= BIT9; break; | 4083 | case HDLC_CRC_16_CCITT: val |= BIT9; break; |
4079 | case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; | 4084 | case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; |
@@ -4175,17 +4180,38 @@ static void hdlc_mode(struct slgt_info *info) | |||
4175 | */ | 4180 | */ |
4176 | static void tx_set_idle(struct slgt_info *info) | 4181 | static void tx_set_idle(struct slgt_info *info) |
4177 | { | 4182 | { |
4178 | unsigned char val = 0xff; | 4183 | unsigned char val; |
4184 | unsigned short tcr; | ||
4179 | 4185 | ||
4180 | switch(info->idle_mode) | 4186 | /* if preamble enabled (tcr[6] == 1) then tx idle size = 8 bits |
4181 | { | 4187 | * else tcr[5:4] = tx idle size: 00 = 8 bits, 01 = 16 bits |
4182 | case HDLC_TXIDLE_FLAGS: val = 0x7e; break; | 4188 | */ |
4183 | case HDLC_TXIDLE_ALT_ZEROS_ONES: val = 0xaa; break; | 4189 | tcr = rd_reg16(info, TCR); |
4184 | case HDLC_TXIDLE_ZEROS: val = 0x00; break; | 4190 | if (info->idle_mode & HDLC_TXIDLE_CUSTOM_16) { |
4185 | case HDLC_TXIDLE_ONES: val = 0xff; break; | 4191 | /* disable preamble, set idle size to 16 bits */ |
4186 | case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break; | 4192 | tcr = (tcr & ~(BIT6 + BIT5)) | BIT4; |
4187 | case HDLC_TXIDLE_SPACE: val = 0x00; break; | 4193 | /* MSB of 16 bit idle specified in tx preamble register (TPR) */ |
4188 | case HDLC_TXIDLE_MARK: val = 0xff; break; | 4194 | wr_reg8(info, TPR, (unsigned char)((info->idle_mode >> 8) & 0xff)); |
4195 | } else if (!(tcr & BIT6)) { | ||
4196 | /* preamble is disabled, set idle size to 8 bits */ | ||
4197 | tcr &= ~(BIT5 + BIT4); | ||
4198 | } | ||
4199 | wr_reg16(info, TCR, tcr); | ||
4200 | |||
4201 | if (info->idle_mode & (HDLC_TXIDLE_CUSTOM_8 | HDLC_TXIDLE_CUSTOM_16)) { | ||
4202 | /* LSB of custom tx idle specified in tx idle register */ | ||
4203 | val = (unsigned char)(info->idle_mode & 0xff); | ||
4204 | } else { | ||
4205 | /* standard 8 bit idle patterns */ | ||
4206 | switch(info->idle_mode) | ||
4207 | { | ||
4208 | case HDLC_TXIDLE_FLAGS: val = 0x7e; break; | ||
4209 | case HDLC_TXIDLE_ALT_ZEROS_ONES: | ||
4210 | case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break; | ||
4211 | case HDLC_TXIDLE_ZEROS: | ||
4212 | case HDLC_TXIDLE_SPACE: val = 0x00; break; | ||
4213 | default: val = 0xff; | ||
4214 | } | ||
4189 | } | 4215 | } |
4190 | 4216 | ||
4191 | wr_reg8(info, TIR, val); | 4217 | wr_reg8(info, TIR, val); |
@@ -4313,6 +4339,12 @@ static int rx_get_frame(struct slgt_info *info) | |||
4313 | unsigned long flags; | 4339 | unsigned long flags; |
4314 | struct tty_struct *tty = info->tty; | 4340 | struct tty_struct *tty = info->tty; |
4315 | unsigned char addr_field = 0xff; | 4341 | unsigned char addr_field = 0xff; |
4342 | unsigned int crc_size = 0; | ||
4343 | |||
4344 | switch (info->params.crc_type & HDLC_CRC_MASK) { | ||
4345 | case HDLC_CRC_16_CCITT: crc_size = 2; break; | ||
4346 | case HDLC_CRC_32_CCITT: crc_size = 4; break; | ||
4347 | } | ||
4316 | 4348 | ||
4317 | check_again: | 4349 | check_again: |
4318 | 4350 | ||
@@ -4357,7 +4389,7 @@ check_again: | |||
4357 | status = desc_status(info->rbufs[end]); | 4389 | status = desc_status(info->rbufs[end]); |
4358 | 4390 | ||
4359 | /* ignore CRC bit if not using CRC (bit is undefined) */ | 4391 | /* ignore CRC bit if not using CRC (bit is undefined) */ |
4360 | if (info->params.crc_type == HDLC_CRC_NONE) | 4392 | if ((info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_NONE) |
4361 | status &= ~BIT1; | 4393 | status &= ~BIT1; |
4362 | 4394 | ||
4363 | if (framesize == 0 || | 4395 | if (framesize == 0 || |
@@ -4366,34 +4398,34 @@ check_again: | |||
4366 | goto check_again; | 4398 | goto check_again; |
4367 | } | 4399 | } |
4368 | 4400 | ||
4369 | if (framesize < 2 || status & (BIT1+BIT0)) { | 4401 | if (framesize < (2 + crc_size) || status & BIT0) { |
4370 | if (framesize < 2 || (status & BIT0)) | 4402 | info->icount.rxshort++; |
4371 | info->icount.rxshort++; | ||
4372 | else | ||
4373 | info->icount.rxcrc++; | ||
4374 | framesize = 0; | 4403 | framesize = 0; |
4404 | } else if (status & BIT1) { | ||
4405 | info->icount.rxcrc++; | ||
4406 | if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) | ||
4407 | framesize = 0; | ||
4408 | } | ||
4375 | 4409 | ||
4376 | #ifdef CONFIG_HDLC | 4410 | #ifdef CONFIG_HDLC |
4377 | { | 4411 | if (framesize == 0) { |
4378 | struct net_device_stats *stats = hdlc_stats(info->netdev); | 4412 | struct net_device_stats *stats = hdlc_stats(info->netdev); |
4379 | stats->rx_errors++; | 4413 | stats->rx_errors++; |
4380 | stats->rx_frame_errors++; | 4414 | stats->rx_frame_errors++; |
4381 | } | ||
4382 | #endif | ||
4383 | } else { | ||
4384 | /* adjust frame size for CRC, if any */ | ||
4385 | if (info->params.crc_type == HDLC_CRC_16_CCITT) | ||
4386 | framesize -= 2; | ||
4387 | else if (info->params.crc_type == HDLC_CRC_32_CCITT) | ||
4388 | framesize -= 4; | ||
4389 | } | 4415 | } |
4416 | #endif | ||
4390 | 4417 | ||
4391 | DBGBH(("%s rx frame status=%04X size=%d\n", | 4418 | DBGBH(("%s rx frame status=%04X size=%d\n", |
4392 | info->device_name, status, framesize)); | 4419 | info->device_name, status, framesize)); |
4393 | DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx"); | 4420 | DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx"); |
4394 | 4421 | ||
4395 | if (framesize) { | 4422 | if (framesize) { |
4396 | if (framesize > info->max_frame_size) | 4423 | if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) { |
4424 | framesize -= crc_size; | ||
4425 | crc_size = 0; | ||
4426 | } | ||
4427 | |||
4428 | if (framesize > info->max_frame_size + crc_size) | ||
4397 | info->icount.rxlong++; | 4429 | info->icount.rxlong++; |
4398 | else { | 4430 | else { |
4399 | /* copy dma buffer(s) to contiguous temp buffer */ | 4431 | /* copy dma buffer(s) to contiguous temp buffer */ |
@@ -4413,6 +4445,11 @@ check_again: | |||
4413 | i = 0; | 4445 | i = 0; |
4414 | } | 4446 | } |
4415 | 4447 | ||
4448 | if (info->params.crc_type & HDLC_CRC_RETURN_EX) { | ||
4449 | *p = (status & BIT1) ? RX_CRC_ERROR : RX_OK; | ||
4450 | framesize++; | ||
4451 | } | ||
4452 | |||
4416 | #ifdef CONFIG_HDLC | 4453 | #ifdef CONFIG_HDLC |
4417 | if (info->netcount) | 4454 | if (info->netcount) |
4418 | hdlcdev_rx(info,info->tmp_rbuf, framesize); | 4455 | hdlcdev_rx(info,info->tmp_rbuf, framesize); |
@@ -4671,13 +4708,13 @@ static int loopback_test(struct slgt_info *info) | |||
4671 | static int adapter_test(struct slgt_info *info) | 4708 | static int adapter_test(struct slgt_info *info) |
4672 | { | 4709 | { |
4673 | DBGINFO(("testing %s\n", info->device_name)); | 4710 | DBGINFO(("testing %s\n", info->device_name)); |
4674 | if ((info->init_error = register_test(info)) < 0) { | 4711 | if (register_test(info) < 0) { |
4675 | printk("register test failure %s addr=%08X\n", | 4712 | printk("register test failure %s addr=%08X\n", |
4676 | info->device_name, info->phys_reg_addr); | 4713 | info->device_name, info->phys_reg_addr); |
4677 | } else if ((info->init_error = irq_test(info)) < 0) { | 4714 | } else if (irq_test(info) < 0) { |
4678 | printk("IRQ test failure %s IRQ=%d\n", | 4715 | printk("IRQ test failure %s IRQ=%d\n", |
4679 | info->device_name, info->irq_level); | 4716 | info->device_name, info->irq_level); |
4680 | } else if ((info->init_error = loopback_test(info)) < 0) { | 4717 | } else if (loopback_test(info) < 0) { |
4681 | printk("loopback test failure %s\n", info->device_name); | 4718 | printk("loopback test failure %s\n", info->device_name); |
4682 | } | 4719 | } |
4683 | return info->init_error; | 4720 | return info->init_error; |