[PATCH] Char: mxser_new, compact structures, round2

Too many structures are in the driver for each type of card.  Make only one
for all cards and appropriate alter the code.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c
index e665dfc..82cb420 100644
--- a/drivers/char/mxser_new.c
+++ b/drivers/char/mxser_new.c
@@ -84,97 +84,11 @@
 #define CI134_ASIC_ID	3
 #define CI104J_ASIC_ID  5
 
-enum {
-	MXSER_BOARD_C168_ISA = 1,
-	MXSER_BOARD_C104_ISA,
-	MXSER_BOARD_CI104J,
-	MXSER_BOARD_C168_PCI,
-	MXSER_BOARD_C104_PCI,
-	MXSER_BOARD_C102_ISA,
-	MXSER_BOARD_CI132,
-	MXSER_BOARD_CI134,
-	MXSER_BOARD_CP132,
-	MXSER_BOARD_CP114,
-	MXSER_BOARD_CT114,
-	MXSER_BOARD_CP102,
-	MXSER_BOARD_CP104U,
-	MXSER_BOARD_CP168U,
-	MXSER_BOARD_CP132U,
-	MXSER_BOARD_CP134U,
-	MXSER_BOARD_CP104JU,
-	MXSER_BOARD_RC7000,
-	MXSER_BOARD_CP118U,
-	MXSER_BOARD_CP102UL,
-	MXSER_BOARD_CP102U,
-	MXSER_BOARD_CP118EL,
-	MXSER_BOARD_CP168EL,
-	MXSER_BOARD_CP104EL
-};
-
-static char *mxser_brdname[] = {
-	"C168 series",
-	"C104 series",
-	"CI-104J series",
-	"C168H/PCI series",
-	"C104H/PCI series",
-	"C102 series",
-	"CI-132 series",
-	"CI-134 series",
-	"CP-132 series",
-	"CP-114 series",
-	"CT-114 series",
-	"CP-102 series",
-	"CP-104U series",
-	"CP-168U series",
-	"CP-132U series",
-	"CP-134U series",
-	"CP-104JU series",
-	"Moxa UC7000 Serial",
-	"CP-118U series",
-	"CP-102UL series",
-	"CP-102U series",
-	"CP-118EL series",
-	"CP-168EL series",
-	"CP-104EL series"
-};
-
-static int mxser_numports[] = {
-	8,			/* C168-ISA */
-	4,			/* C104-ISA */
-	4,			/* CI104J */
-	8,			/* C168-PCI */
-	4,			/* C104-PCI */
-	2,			/* C102-ISA */
-	2,			/* CI132 */
-	4,			/* CI134 */
-	2,			/* CP132 */
-	4,			/* CP114 */
-	4,			/* CT114 */
-	2,			/* CP102 */
-	4,			/* CP104U */
-	8,			/* CP168U */
-	2,			/* CP132U */
-	4,			/* CP134U */
-	4,			/* CP104JU */
-	8,			/* RC7000 */
-	8,			/* CP118U */
-	2,			/* CP102UL */
-	2,			/* CP102U */
-	8,			/* CP118EL */
-	8,			/* CP168EL */
-	4			/* CP104EL */
-};
-
-#define UART_TYPE_NUM	2
-
-static const unsigned int Gmoxa_uart_id[UART_TYPE_NUM] = {
-	MOXA_MUST_MU150_HWID,
-	MOXA_MUST_MU860_HWID
-};
+#define MXSER_HIGHBAUD	1
+#define MXSER_HAS2	2
 
 /* This is only for PCI */
-#define UART_INFO_NUM	3
-struct mxpciuart_info {
+static const struct {
 	int type;
 	int tx_fifo;
 	int rx_fifo;
@@ -183,51 +97,85 @@
 	int rx_trigger;
 	int rx_low_water;
 	long max_baud;
-};
-
-static const struct mxpciuart_info Gpci_uart_info[UART_INFO_NUM] = {
+} Gpci_uart_info[] = {
 	{MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L},
 	{MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L},
 	{MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L}
 };
+#define UART_INFO_NUM	ARRAY_SIZE(Gpci_uart_info)
 
+struct mxser_cardinfo {
+	unsigned int nports;
+	char *name;
+	unsigned int flags;
+};
+
+static const struct mxser_cardinfo mxser_cards[] = {
+	{ 8, "C168 series", },			/* C168-ISA */
+	{ 4, "C104 series", },			/* C104-ISA */
+	{ 4, "CI-104J series", },		/* CI104J */
+	{ 8, "C168H/PCI series", },		/* C168-PCI */
+	{ 4, "C104H/PCI series", },		/* C104-PCI */
+	{ 4, "C102 series", MXSER_HAS2 },	/* C102-ISA */
+	{ 4, "CI-132 series", MXSER_HAS2 },	/* CI132 */
+	{ 4, "CI-134 series", },		/* CI134 */
+	{ 2, "CP-132 series", },		/* CP132 */
+	{ 4, "CP-114 series", },		/* CP114 */
+	{ 4, "CT-114 series", },		/* CT114 */
+	{ 2, "CP-102 series", MXSER_HIGHBAUD },	/* CP102 */
+	{ 4, "CP-104U series", },		/* CP104U */
+	{ 8, "CP-168U series", },		/* CP168U */
+	{ 2, "CP-132U series", },		/* CP132U */
+	{ 4, "CP-134U series", },		/* CP134U */
+	{ 4, "CP-104JU series", },		/* CP104JU */
+	{ 8, "Moxa UC7000 Serial", },		/* RC7000 */
+	{ 8, "CP-118U series", },		/* CP118U */
+	{ 2, "CP-102UL series", },		/* CP102UL */
+	{ 2, "CP-102U series", },		/* CP102U */
+	{ 8, "CP-118EL series", },		/* CP118EL */
+	{ 8, "CP-168EL series", },		/* CP168EL */
+	{ 4, "CP-104EL series", }		/* CP104EL */
+};
+
+/* driver_data correspond to the lines in the structure above
+   see also ISA probe function before you change something */
 static struct pci_device_id mxser_pcibrds[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C168),
-		.driver_data = MXSER_BOARD_C168_PCI },
+		.driver_data = 3 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C104),
-		.driver_data = MXSER_BOARD_C104_PCI },
+		.driver_data = 4 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132),
-		.driver_data = MXSER_BOARD_CP132 },
+		.driver_data = 8 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP114),
-		.driver_data = MXSER_BOARD_CP114 },
+		.driver_data = 9 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CT114),
-		.driver_data = MXSER_BOARD_CT114 },
+		.driver_data = 10 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102),
-		.driver_data = MXSER_BOARD_CP102 },
+		.driver_data = 11 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104U),
-		.driver_data = MXSER_BOARD_CP104U },
+		.driver_data = 12 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168U),
-		.driver_data = MXSER_BOARD_CP168U },
+		.driver_data = 13 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132U),
-		.driver_data = MXSER_BOARD_CP132U },
+		.driver_data = 14 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP134U),
-		.driver_data = MXSER_BOARD_CP134U },
+		.driver_data = 15 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104JU),
-		.driver_data = MXSER_BOARD_CP104JU },
+		.driver_data = 16 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_RC7000),
-		.driver_data = MXSER_BOARD_RC7000 },
+		.driver_data = 17 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118U),
-		.driver_data = MXSER_BOARD_CP118U },
+		.driver_data = 18 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102UL),
-		.driver_data = MXSER_BOARD_CP102UL },
+		.driver_data = 19 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102U),
-		.driver_data = MXSER_BOARD_CP102U },
+		.driver_data = 20 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118EL),
-		.driver_data = MXSER_BOARD_CP118EL },
+		.driver_data = 21 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168EL),
-		.driver_data = MXSER_BOARD_CP168EL },
+		.driver_data = 22 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104EL),
-		.driver_data = MXSER_BOARD_CP104EL },
+		.driver_data = 23 },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
@@ -338,8 +286,7 @@
 	struct pci_dev *pdev; /* temporary (until pci probing) */
 
 	int irq;
-	int board_type;
-	unsigned int nports;
+	const struct mxser_cardinfo *info;
 	unsigned long vector;
 	unsigned long vector_mask;
 
@@ -392,8 +339,8 @@
 	}
 
 	GET_MOXA_MUST_HARDWARE_ID(io, &hwid);
-	for (i = 0; i < UART_TYPE_NUM; i++) {
-		if (hwid == Gmoxa_uart_id[i])
+	for (i = 1; i < UART_INFO_NUM; i++) { /* 0 = OTHER_UART */
+		if (hwid == Gpci_uart_info[i].type)
 			return (int)hwid;
 	}
 	return MOXA_OTHER_UART;
@@ -2447,7 +2394,7 @@
 		goto irq_stop;
 	if (brd == NULL)
 		goto irq_stop;
-	max = mxser_numports[brd->board_type - 1];
+	max = brd->info->nports;
 	while (1) {
 		irqbits = inb(brd->vector) & brd->vector_mask;
 		if (irqbits == brd->vector_mask)
@@ -2574,7 +2521,7 @@
 		pci_release_region(pdev, 3);
 		pci_dev_put(pdev);
 	} else {
-		release_region(brd->ports[0].ioaddr, 8 * brd->nports);
+		release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
 		release_region(brd->vector, 1);
 	}
 }
@@ -2587,7 +2534,7 @@
 
 	printk(KERN_INFO "max. baud rate = %d bps.\n", brd->ports[0].max_baud);
 
-	for (i = 0; i < brd->nports; i++) {
+	for (i = 0; i < brd->info->nports; i++) {
 		info = &brd->ports[i];
 		info->board = brd;
 		info->stop_rx = 0;
@@ -2628,7 +2575,7 @@
 	if (retval) {
 		printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
 			"conflict with another device.\n",
-			mxser_brdname[brd->board_type - 1], brd->irq);
+			brd->info->name, brd->irq);
 		/* We hold resources, we need to release them. */
 		mxser_release_res(brd, 0);
 		return retval;
@@ -2645,40 +2592,44 @@
 	brd->chip_flag = MOXA_OTHER_UART;
 
 	id = mxser_read_register(cap, regs);
-	if (id == C168_ASIC_ID) {
-		brd->board_type = MXSER_BOARD_C168_ISA;
-		brd->nports = 8;
-	} else if (id == C104_ASIC_ID) {
-		brd->board_type = MXSER_BOARD_C104_ISA;
-		brd->nports = 4;
-	} else if (id == C102_ASIC_ID) {
-		brd->board_type = MXSER_BOARD_C102_ISA;
-		brd->nports = 2;
-	} else if (id == CI132_ASIC_ID) {
-		brd->board_type = MXSER_BOARD_CI132;
-		brd->nports = 2;
-	} else if (id == CI134_ASIC_ID) {
-		brd->board_type = MXSER_BOARD_CI134;
-		brd->nports = 4;
-	} else if (id == CI104J_ASIC_ID) {
-		brd->board_type = MXSER_BOARD_CI104J;
-		brd->nports = 4;
-	} else
+	switch (id) {
+	case C168_ASIC_ID:
+		brd->info = &mxser_cards[0];
+		break;
+	case C104_ASIC_ID:
+		brd->info = &mxser_cards[1];
+		break;
+	case CI104J_ASIC_ID:
+		brd->info = &mxser_cards[2];
+		break;
+	case C102_ASIC_ID:
+		brd->info = &mxser_cards[5];
+		break;
+	case CI132_ASIC_ID:
+		brd->info = &mxser_cards[6];
+		break;
+	case CI134_ASIC_ID:
+		brd->info = &mxser_cards[7];
+		break;
+	default:
 		return 0;
+	}
 
 	irq = 0;
-	if (brd->nports == 2) {
+	/* some ISA cards have 2 ports, but we want to see them as 4-port (why?)
+	   Flag-hack checks if configuration should be read as 2-port here. */
+	if (brd->info->nports == 2 || (brd->info->flags & MXSER_HAS2)) {
 		irq = regs[9] & 0xF000;
 		irq = irq | (irq >> 4);
 		if (irq != (regs[9] & 0xFF00))
 			return MXSER_ERR_IRQ_CONFLIT;
-	} else if (brd->nports == 4) {
+	} else if (brd->info->nports == 4) {
 		irq = regs[9] & 0xF000;
 		irq = irq | (irq >> 4);
 		irq = irq | (irq >> 8);
 		if (irq != regs[9])
 			return MXSER_ERR_IRQ_CONFLIT;
-	} else if (brd->nports == 8) {
+	} else if (brd->info->nports == 8) {
 		irq = regs[9] & 0xF000;
 		irq = irq | (irq >> 4);
 		irq = irq | (irq >> 8);
@@ -2718,35 +2669,31 @@
 		brd->uart_type = PORT_16550A;
 	else
 		brd->uart_type = PORT_16450;
-	if (id == 1)
-		brd->nports = 8;
-	else
-		brd->nports = 4;
-	if (!request_region(brd->ports[0].ioaddr, 8 * brd->nports, "mxser(IO)"))
+	if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports,
+			"mxser(IO)"))
 		return MXSER_ERR_IOADDR;
 	if (!request_region(brd->vector, 1, "mxser(vector)")) {
-		release_region(brd->ports[0].ioaddr, 8 * brd->nports);
+		release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
 		return MXSER_ERR_VECTOR;
 	}
-	return brd->nports;
+	return brd->info->nports;
 }
 
-static int __init mxser_get_PCI_conf(int board_type, struct mxser_board *brd,
-		struct pci_dev *pdev)
+static int __init mxser_get_PCI_conf(const struct pci_device_id *ent,
+		struct mxser_board *brd, struct pci_dev *pdev)
 {
 	unsigned int i, j;
 	unsigned long ioaddress;
 	int retval;
 
 	/* io address */
-	brd->board_type = board_type;
-	brd->nports = mxser_numports[board_type - 1];
+	brd->info = &mxser_cards[ent->driver_data];
 	ioaddress = pci_resource_start(pdev, 2);
 	retval = pci_request_region(pdev, 2, "mxser(IO)");
 	if (retval)
 		goto err;
 
-	for (i = 0; i < brd->nports; i++)
+	for (i = 0; i < brd->info->nports; i++)
 		brd->ports[i].ioaddr = ioaddress + 8 * i;
 
 	/* vector */
@@ -2763,14 +2710,14 @@
 	brd->uart_type = PORT_16550A;
 	brd->vector_mask = 0;
 
-	for (i = 0; i < brd->nports; i++) {
+	for (i = 0; i < brd->info->nports; i++) {
 		for (j = 0; j < UART_INFO_NUM; j++) {
 			if (Gpci_uart_info[j].type == brd->chip_flag) {
 				brd->ports[i].max_baud =
 					Gpci_uart_info[j].max_baud;
 
 				/* exception....CP-102 */
-				if (board_type == MXSER_BOARD_CP102)
+				if (brd->info->flags & MXSER_HIGHBAUD)
 					brd->ports[i].max_baud = 921600;
 				break;
 			}
@@ -2778,7 +2725,7 @@
 	}
 
 	if (brd->chip_flag == MOXA_MUST_MU860_HWID) {
-		for (i = 0; i < brd->nports; i++) {
+		for (i = 0; i < brd->info->nports; i++) {
 			if (i < 4)
 				brd->ports[i].opmode_ioaddr = ioaddress + 4;
 			else
@@ -2788,7 +2735,7 @@
 		outb(0, ioaddress + 0x0c);	/* default set to RS232 mode */
 	}
 
-	for (i = 0; i < brd->nports; i++) {
+	for (i = 0; i < brd->info->nports; i++) {
 		brd->vector_mask |= (1 << i);
 		brd->ports[i].baud_base = 921600;
 	}
@@ -2814,9 +2761,6 @@
 		return -ENOMEM;
 	spin_lock_init(&gm_lock);
 
-	for (i = 0; i < MXSER_BOARDS; i++)
-		mxser_boards[i].board_type = -1;
-
 	printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n",
 		MXSER_VERSION);
 
@@ -2863,8 +2807,7 @@
 			if (retval != 0)
 				printk(KERN_INFO "Found MOXA %s board "
 					"(CAP=0x%x)\n",
-					mxser_brdname[brd->board_type - 1],
-					ioaddr[b]);
+					brd->info->name, ioaddr[b]);
 
 			if (retval <= 0) {
 				if (retval == MXSER_ERR_IRQ)
@@ -2892,7 +2835,7 @@
 			if (mxser_initbrd(brd) < 0)
 				continue;
 
-			for (i = 0; i < brd->nports; i++)
+			for (i = 0; i < brd->info->nports; i++)
 				tty_register_device(mxvar_sdriver,
 					m * MXSER_PORTS_PER_BOARD + i, NULL);
 
@@ -2910,7 +2853,7 @@
 			continue;
 		}
 		printk(KERN_INFO "Found MOXA %s board(BusNo=%d,DevNo=%d)\n",
-			mxser_brdname[(int) (mxser_pcibrds[b].driver_data) - 1],
+			mxser_cards[mxser_pcibrds[b].driver_data].name,
 			pdev->bus->number, PCI_SLOT(pdev->devfn));
 		if (m >= MXSER_BOARDS)
 			printk(KERN_ERR
@@ -2925,8 +2868,7 @@
 			}
 			brd = &mxser_boards[m];
 			brd->pdev = pdev;
-			retval = mxser_get_PCI_conf(
-					(int)mxser_pcibrds[b].driver_data,
+			retval = mxser_get_PCI_conf(&mxser_pcibrds[b],
 					brd, pdev);
 			if (retval < 0) {
 				if (retval == MXSER_ERR_IRQ)
@@ -2950,7 +2892,7 @@
 			/* mxser_initbrd will hook ISR. */
 			if (mxser_initbrd(brd) < 0)
 				continue;
-			for (i = 0; i < brd->nports; i++)
+			for (i = 0; i < brd->info->nports; i++)
 				tty_register_device(mxvar_sdriver,
 					m * MXSER_PORTS_PER_BOARD + i,
 					&pdev->dev);
@@ -2989,7 +2931,7 @@
 	put_tty_driver(mxvar_sdriver);
 
 	for (i = 0; i < MXSER_BOARDS; i++)
-		if (mxser_boards[i].board_type != -1)
+		if (mxser_boards[i].info != NULL)
 			mxser_release_res(&mxser_boards[i], 1);
 
 	pr_debug("Done.\n");