diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/cyclades.c | 142 |
1 files changed, 69 insertions, 73 deletions
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index c6a12bad70f5..7fe4bb60f690 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -722,11 +722,6 @@ module_param_array(irq, int, NULL, 0); | |||
722 | */ | 722 | */ |
723 | static struct cyclades_card cy_card[NR_CARDS]; | 723 | static struct cyclades_card cy_card[NR_CARDS]; |
724 | 724 | ||
725 | /* This is the per-channel data structure containing pointers, flags | ||
726 | and variables for the port. This driver supports a maximum of NR_PORTS. | ||
727 | */ | ||
728 | static struct cyclades_port cy_port[NR_PORTS]; | ||
729 | |||
730 | static int cy_next_channel; /* next minor available */ | 725 | static int cy_next_channel; /* next minor available */ |
731 | 726 | ||
732 | /* | 727 | /* |
@@ -855,13 +850,6 @@ static inline int serial_paranoia_check(struct cyclades_port *info, | |||
855 | return 1; | 850 | return 1; |
856 | } | 851 | } |
857 | 852 | ||
858 | if ((long)info < (long)(&cy_port[0]) || | ||
859 | (long)(&cy_port[NR_PORTS]) < (long)info) { | ||
860 | printk(KERN_WARNING "cyc Warning: cyclades_port out of range " | ||
861 | "for (%s) in %s\n", name, routine); | ||
862 | return 1; | ||
863 | } | ||
864 | |||
865 | if (info->magic != CYCLADES_MAGIC) { | 853 | if (info->magic != CYCLADES_MAGIC) { |
866 | printk(KERN_WARNING "cyc Warning: bad magic number for serial " | 854 | printk(KERN_WARNING "cyc Warning: bad magic number for serial " |
867 | "struct (%s) in %s\n", name, routine); | 855 | "struct (%s) in %s\n", name, routine); |
@@ -1025,7 +1013,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, | |||
1025 | struct cyclades_port *info; | 1013 | struct cyclades_port *info; |
1026 | struct tty_struct *tty; | 1014 | struct tty_struct *tty; |
1027 | int char_count; | 1015 | int char_count; |
1028 | int i, j, len, mdm_change, mdm_status, outch; | 1016 | int j, len, mdm_change, mdm_status, outch; |
1029 | int save_xir, channel, save_car; | 1017 | int save_xir, channel, save_car; |
1030 | char data; | 1018 | char data; |
1031 | 1019 | ||
@@ -1037,8 +1025,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, | |||
1037 | spin_lock(&cinfo->card_lock); | 1025 | spin_lock(&cinfo->card_lock); |
1038 | save_xir = (u_char) readb(base_addr + (CyRIR << index)); | 1026 | save_xir = (u_char) readb(base_addr + (CyRIR << index)); |
1039 | channel = (u_short) (save_xir & CyIRChannel); | 1027 | channel = (u_short) (save_xir & CyIRChannel); |
1040 | i = channel + chip * 4 + cinfo->first_line; | 1028 | info = &cinfo->ports[channel + chip * 4]; |
1041 | info = &cy_port[i]; | ||
1042 | save_car = readb(base_addr + (CyCAR << index)); | 1029 | save_car = readb(base_addr + (CyCAR << index)); |
1043 | cy_writeb(base_addr + (CyCAR << index), save_xir); | 1030 | cy_writeb(base_addr + (CyCAR << index), save_xir); |
1044 | 1031 | ||
@@ -1202,18 +1189,17 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, | |||
1202 | spin_lock(&cinfo->card_lock); | 1189 | spin_lock(&cinfo->card_lock); |
1203 | save_xir = (u_char) readb(base_addr + (CyTIR << index)); | 1190 | save_xir = (u_char) readb(base_addr + (CyTIR << index)); |
1204 | channel = (u_short) (save_xir & CyIRChannel); | 1191 | channel = (u_short) (save_xir & CyIRChannel); |
1205 | i = channel + chip * 4 + cinfo->first_line; | ||
1206 | save_car = readb(base_addr + (CyCAR << index)); | 1192 | save_car = readb(base_addr + (CyCAR << index)); |
1207 | cy_writeb(base_addr + (CyCAR << index), save_xir); | 1193 | cy_writeb(base_addr + (CyCAR << index), save_xir); |
1208 | 1194 | ||
1209 | /* validate the port# (as configured and open) */ | 1195 | /* validate the port# (as configured and open) */ |
1210 | if ((i < 0) || (NR_PORTS <= i)) { | 1196 | if (channel + chip * 4 >= cinfo->nports) { |
1211 | cy_writeb(base_addr + (CySRER << index), | 1197 | cy_writeb(base_addr + (CySRER << index), |
1212 | readb(base_addr + (CySRER << index)) & | 1198 | readb(base_addr + (CySRER << index)) & |
1213 | ~CyTxRdy); | 1199 | ~CyTxRdy); |
1214 | goto txend; | 1200 | goto txend; |
1215 | } | 1201 | } |
1216 | info = &cy_port[i]; | 1202 | info = &cinfo->ports[channel + chip * 4]; |
1217 | if (info->tty == NULL) { | 1203 | if (info->tty == NULL) { |
1218 | cy_writeb(base_addr + (CySRER << index), | 1204 | cy_writeb(base_addr + (CySRER << index), |
1219 | readb(base_addr + (CySRER << index)) & | 1205 | readb(base_addr + (CySRER << index)) & |
@@ -1325,7 +1311,7 @@ txend: | |||
1325 | spin_lock(&cinfo->card_lock); | 1311 | spin_lock(&cinfo->card_lock); |
1326 | save_xir = (u_char) readb(base_addr + (CyMIR << index)); | 1312 | save_xir = (u_char) readb(base_addr + (CyMIR << index)); |
1327 | channel = (u_short) (save_xir & CyIRChannel); | 1313 | channel = (u_short) (save_xir & CyIRChannel); |
1328 | info = &cy_port[channel + chip * 4 + cinfo->first_line]; | 1314 | info = &cinfo->ports[channel + chip * 4]; |
1329 | save_car = readb(base_addr + (CyCAR << index)); | 1315 | save_car = readb(base_addr + (CyCAR << index)); |
1330 | cy_writeb(base_addr + (CyCAR << index), save_xir); | 1316 | cy_writeb(base_addr + (CyCAR << index), save_xir); |
1331 | 1317 | ||
@@ -1726,7 +1712,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) | |||
1726 | while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { | 1712 | while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { |
1727 | special_count = 0; | 1713 | special_count = 0; |
1728 | delta_count = 0; | 1714 | delta_count = 0; |
1729 | info = &cy_port[channel + cinfo->first_line]; | 1715 | info = &cinfo->ports[channel]; |
1730 | if ((tty = info->tty) == NULL) | 1716 | if ((tty = info->tty) == NULL) |
1731 | continue; | 1717 | continue; |
1732 | 1718 | ||
@@ -1896,7 +1882,7 @@ static void cyz_poll(unsigned long arg) | |||
1896 | cyz_handle_cmd(cinfo); | 1882 | cyz_handle_cmd(cinfo); |
1897 | 1883 | ||
1898 | for (port = 0; port < cinfo->nports; port++) { | 1884 | for (port = 0; port < cinfo->nports; port++) { |
1899 | info = &cy_port[port + cinfo->first_line]; | 1885 | info = &cinfo->ports[port]; |
1900 | tty = info->tty; | 1886 | tty = info->tty; |
1901 | ch_ctrl = &(zfw_ctrl->ch_ctrl[port]); | 1887 | ch_ctrl = &(zfw_ctrl->ch_ctrl[port]); |
1902 | buf_ctrl = &(zfw_ctrl->buf_ctrl[port]); | 1888 | buf_ctrl = &(zfw_ctrl->buf_ctrl[port]); |
@@ -2468,13 +2454,20 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2468 | static int cy_open(struct tty_struct *tty, struct file *filp) | 2454 | static int cy_open(struct tty_struct *tty, struct file *filp) |
2469 | { | 2455 | { |
2470 | struct cyclades_port *info; | 2456 | struct cyclades_port *info; |
2457 | unsigned int i; | ||
2471 | int retval, line; | 2458 | int retval, line; |
2472 | 2459 | ||
2473 | line = tty->index; | 2460 | line = tty->index; |
2474 | if ((line < 0) || (NR_PORTS <= line)) { | 2461 | if ((line < 0) || (NR_PORTS <= line)) { |
2475 | return -ENODEV; | 2462 | return -ENODEV; |
2476 | } | 2463 | } |
2477 | info = &cy_port[line]; | 2464 | for (i = 0; i < NR_CARDS; i++) |
2465 | if (line < cy_card[i].first_line + cy_card[i].nports && | ||
2466 | line >= cy_card[i].first_line) | ||
2467 | break; | ||
2468 | if (i >= NR_CARDS) | ||
2469 | return -ENODEV; | ||
2470 | info = &cy_card[i].ports[line - cy_card[i].first_line]; | ||
2478 | if (info->line < 0) { | 2471 | if (info->line < 0) { |
2479 | return -ENODEV; | 2472 | return -ENODEV; |
2480 | } | 2473 | } |
@@ -4437,7 +4430,7 @@ static void cy_hangup(struct tty_struct *tty) | |||
4437 | * --------------------------------------------------------------------- | 4430 | * --------------------------------------------------------------------- |
4438 | */ | 4431 | */ |
4439 | 4432 | ||
4440 | static void __devinit cy_init_card(struct cyclades_card *cinfo) | 4433 | static int __devinit cy_init_card(struct cyclades_card *cinfo) |
4441 | { | 4434 | { |
4442 | struct cyclades_port *info; | 4435 | struct cyclades_port *info; |
4443 | u32 mailbox; | 4436 | u32 mailbox; |
@@ -4459,10 +4452,15 @@ static void __devinit cy_init_card(struct cyclades_card *cinfo) | |||
4459 | nports = cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips; | 4452 | nports = cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips; |
4460 | } | 4453 | } |
4461 | 4454 | ||
4455 | cinfo->ports = kzalloc(sizeof(*cinfo->ports) * nports, GFP_KERNEL); | ||
4456 | if (cinfo->ports == NULL) { | ||
4457 | printk(KERN_ERR "Cyclades: cannot allocate ports\n"); | ||
4458 | return -ENOMEM; | ||
4459 | } | ||
4460 | |||
4462 | for (port = cinfo->first_line; port < cinfo->first_line + nports; | 4461 | for (port = cinfo->first_line; port < cinfo->first_line + nports; |
4463 | port++) { | 4462 | port++) { |
4464 | info = &cy_port[port]; | 4463 | info = &cinfo->ports[port - cinfo->first_line]; |
4465 | memset(info, 0, sizeof(*info)); | ||
4466 | info->magic = CYCLADES_MAGIC; | 4464 | info->magic = CYCLADES_MAGIC; |
4467 | info->card = cinfo; | 4465 | info->card = cinfo; |
4468 | info->line = port; | 4466 | info->line = port; |
@@ -4525,6 +4523,7 @@ static void __devinit cy_init_card(struct cyclades_card *cinfo) | |||
4525 | #endif | 4523 | #endif |
4526 | } | 4524 | } |
4527 | #endif | 4525 | #endif |
4526 | return 0; | ||
4528 | } | 4527 | } |
4529 | 4528 | ||
4530 | /* initialize chips on Cyclom-Y card -- return number of valid | 4529 | /* initialize chips on Cyclom-Y card -- return number of valid |
@@ -5094,13 +5093,11 @@ static void __devexit cy_pci_remove(struct pci_dev *pdev) | |||
5094 | pci_release_regions(pdev); | 5093 | pci_release_regions(pdev); |
5095 | 5094 | ||
5096 | cinfo->base_addr = NULL; | 5095 | cinfo->base_addr = NULL; |
5097 | for (i = cinfo->first_line; i < cinfo->first_line + cinfo->nports; i++){ | ||
5098 | cy_port[i].line = -1; | ||
5099 | cy_port[i].magic = -1; | ||
5100 | } | ||
5101 | for (i = cinfo->first_line; i < cinfo->first_line + | 5096 | for (i = cinfo->first_line; i < cinfo->first_line + |
5102 | cinfo->nports; i++) | 5097 | cinfo->nports; i++) |
5103 | tty_unregister_device(cy_serial_driver, i); | 5098 | tty_unregister_device(cy_serial_driver, i); |
5099 | cinfo->nports = 0; | ||
5100 | kfree(cinfo->ports); | ||
5104 | } | 5101 | } |
5105 | 5102 | ||
5106 | static struct pci_driver cy_pci_driver = { | 5103 | static struct pci_driver cy_pci_driver = { |
@@ -5116,7 +5113,7 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, | |||
5116 | int *eof, void *data) | 5113 | int *eof, void *data) |
5117 | { | 5114 | { |
5118 | struct cyclades_port *info; | 5115 | struct cyclades_port *info; |
5119 | int i; | 5116 | unsigned int i, j; |
5120 | int len = 0; | 5117 | int len = 0; |
5121 | off_t begin = 0; | 5118 | off_t begin = 0; |
5122 | off_t pos = 0; | 5119 | off_t pos = 0; |
@@ -5130,33 +5127,34 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, | |||
5130 | len += size; | 5127 | len += size; |
5131 | 5128 | ||
5132 | /* Output one line for each known port */ | 5129 | /* Output one line for each known port */ |
5133 | for (i = 0; i < NR_PORTS && cy_port[i].line >= 0; i++) { | 5130 | for (i = 0; i < NR_CARDS; i++) |
5134 | info = &cy_port[i]; | 5131 | for (j = 0; j < cy_card[i].nports; j++) { |
5135 | 5132 | info = &cy_card[i].ports[j]; | |
5136 | if (info->count) | 5133 | |
5137 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu " | 5134 | if (info->count) |
5138 | "%8lu %9lu %6ld\n", info->line, | 5135 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu " |
5139 | (cur_jifs - info->idle_stats.in_use) / HZ, | 5136 | "%10lu %8lu %9lu %6ld\n", info->line, |
5140 | info->idle_stats.xmit_bytes, | 5137 | (cur_jifs - info->idle_stats.in_use) / |
5141 | (cur_jifs - info->idle_stats.xmit_idle) / HZ, | 5138 | HZ, info->idle_stats.xmit_bytes, |
5142 | info->idle_stats.recv_bytes, | 5139 | (cur_jifs - info->idle_stats.xmit_idle)/ |
5143 | (cur_jifs - info->idle_stats.recv_idle) / HZ, | 5140 | HZ, info->idle_stats.recv_bytes, |
5144 | info->idle_stats.overruns, | 5141 | (cur_jifs - info->idle_stats.recv_idle)/ |
5145 | (long)info->tty->ldisc.num); | 5142 | HZ, info->idle_stats.overruns, |
5146 | else | 5143 | (long)info->tty->ldisc.num); |
5147 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu " | 5144 | else |
5148 | "%8lu %9lu %6ld\n", | 5145 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu " |
5149 | info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); | 5146 | "%10lu %8lu %9lu %6ld\n", |
5150 | len += size; | 5147 | info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); |
5151 | pos = begin + len; | 5148 | len += size; |
5152 | 5149 | pos = begin + len; | |
5153 | if (pos < offset) { | 5150 | |
5154 | len = 0; | 5151 | if (pos < offset) { |
5155 | begin = pos; | 5152 | len = 0; |
5153 | begin = pos; | ||
5154 | } | ||
5155 | if (pos > offset + length) | ||
5156 | goto done; | ||
5156 | } | 5157 | } |
5157 | if (pos > offset + length) | ||
5158 | goto done; | ||
5159 | } | ||
5160 | *eof = 1; | 5158 | *eof = 1; |
5161 | done: | 5159 | done: |
5162 | *start = buf + (offset - begin); /* Start of wanted data */ | 5160 | *start = buf + (offset - begin); /* Start of wanted data */ |
@@ -5211,7 +5209,7 @@ static const struct tty_operations cy_ops = { | |||
5211 | 5209 | ||
5212 | static int __init cy_init(void) | 5210 | static int __init cy_init(void) |
5213 | { | 5211 | { |
5214 | unsigned int i, nboards; | 5212 | unsigned int nboards; |
5215 | int retval = -ENOMEM; | 5213 | int retval = -ENOMEM; |
5216 | 5214 | ||
5217 | cy_serial_driver = alloc_tty_driver(NR_PORTS); | 5215 | cy_serial_driver = alloc_tty_driver(NR_PORTS); |
@@ -5242,11 +5240,6 @@ static int __init cy_init(void) | |||
5242 | goto err_frtty; | 5240 | goto err_frtty; |
5243 | } | 5241 | } |
5244 | 5242 | ||
5245 | for (i = 0; i < NR_PORTS; i++) { | ||
5246 | cy_port[i].line = -1; | ||
5247 | cy_port[i].magic = -1; | ||
5248 | } | ||
5249 | |||
5250 | /* the code below is responsible to find the boards. Each different | 5243 | /* the code below is responsible to find the boards. Each different |
5251 | type of board has its own detection routine. If a board is found, | 5244 | type of board has its own detection routine. If a board is found, |
5252 | the next cy_card structure available is set by the detection | 5245 | the next cy_card structure available is set by the detection |
@@ -5275,6 +5268,7 @@ err: | |||
5275 | 5268 | ||
5276 | static void __exit cy_cleanup_module(void) | 5269 | static void __exit cy_cleanup_module(void) |
5277 | { | 5270 | { |
5271 | struct cyclades_card *card; | ||
5278 | int i, e1; | 5272 | int i, e1; |
5279 | 5273 | ||
5280 | #ifndef CONFIG_CYZ_INTR | 5274 | #ifndef CONFIG_CYZ_INTR |
@@ -5290,22 +5284,24 @@ static void __exit cy_cleanup_module(void) | |||
5290 | #endif | 5284 | #endif |
5291 | 5285 | ||
5292 | for (i = 0; i < NR_CARDS; i++) { | 5286 | for (i = 0; i < NR_CARDS; i++) { |
5293 | if (cy_card[i].base_addr) { | 5287 | card = &cy_card[i]; |
5288 | if (card->base_addr) { | ||
5294 | /* clear interrupt */ | 5289 | /* clear interrupt */ |
5295 | cy_writeb(cy_card[i].base_addr + Cy_ClrIntr, 0); | 5290 | cy_writeb(card->base_addr + Cy_ClrIntr, 0); |
5296 | iounmap(cy_card[i].base_addr); | 5291 | iounmap(card->base_addr); |
5297 | if (cy_card[i].ctl_addr) | 5292 | if (card->ctl_addr) |
5298 | iounmap(cy_card[i].ctl_addr); | 5293 | iounmap(card->ctl_addr); |
5299 | if (cy_card[i].irq | 5294 | if (card->irq |
5300 | #ifndef CONFIG_CYZ_INTR | 5295 | #ifndef CONFIG_CYZ_INTR |
5301 | && !IS_CYC_Z(cy_card[i]) | 5296 | && !IS_CYC_Z(*card) |
5302 | #endif /* CONFIG_CYZ_INTR */ | 5297 | #endif /* CONFIG_CYZ_INTR */ |
5303 | ) | 5298 | ) |
5304 | free_irq(cy_card[i].irq, &cy_card[i]); | 5299 | free_irq(card->irq, card); |
5305 | for (e1 = cy_card[i].first_line; | 5300 | for (e1 = card->first_line; |
5306 | e1 < cy_card[i].first_line + | 5301 | e1 < card->first_line + |
5307 | cy_card[i].nports; e1++) | 5302 | card->nports; e1++) |
5308 | tty_unregister_device(cy_serial_driver, e1); | 5303 | tty_unregister_device(cy_serial_driver, e1); |
5304 | kfree(card->ports); | ||
5309 | } | 5305 | } |
5310 | } | 5306 | } |
5311 | 5307 | ||