aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/cyclades.c
diff options
context:
space:
mode:
authorJiri Slaby <jirislaby@gmail.com>2007-05-08 03:37:02 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:15:25 -0400
commitdd025c0c7a047b1be7dfaa4061368b4783d89ebb (patch)
tree7041390fe906a8a2e0e95463ce2212bca2df9e45 /drivers/char/cyclades.c
parentf2462bfe558559c9fbc4ef60812d5df30ccb01f6 (diff)
Char: cyclades, dynamic ports
and save thus approx. 160k of .bss Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/cyclades.c')
-rw-r--r--drivers/char/cyclades.c142
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*/
723static struct cyclades_card cy_card[NR_CARDS]; 723static 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*/
728static struct cyclades_port cy_port[NR_PORTS];
729
730static int cy_next_channel; /* next minor available */ 725static 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, &param) == 1) { 1712 while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 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,
2468static int cy_open(struct tty_struct *tty, struct file *filp) 2454static 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
4440static void __devinit cy_init_card(struct cyclades_card *cinfo) 4433static 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
5106static struct pci_driver cy_pci_driver = { 5103static 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;
5161done: 5159done:
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
5212static int __init cy_init(void) 5210static 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
5276static void __exit cy_cleanup_module(void) 5269static 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