patch-2.4.22 linux-2.4.22/drivers/acorn/char/serial-card.c

Next file: linux-2.4.22/drivers/acorn/char/serial-dualsp.c
Previous file: linux-2.4.22/drivers/acorn/char/serial-atomwide.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/drivers/acorn/char/serial-card.c linux-2.4.22/drivers/acorn/char/serial-card.c
@@ -27,106 +27,110 @@
  */
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
 #include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 
+#include <asm/io.h>
 #include <asm/ecard.h>
 #include <asm/string.h>
 
-#ifndef NUM_SERIALS
-#define NUM_SERIALS	MY_NUMPORTS * MAX_ECARDS
-#endif
-
-#ifdef MODULE
-static int __serial_ports[NUM_SERIALS];
-static int __serial_pcount;
-static int __serial_addr[NUM_SERIALS];
-static struct expansion_card *expcard[MAX_ECARDS];
-#define ADD_ECARD(ec,card) expcard[(card)] = (ec)
-#define ADD_PORT(port,addr)					\
-	do {							\
-		__serial_ports[__serial_pcount] = (port);	\
-		__serial_addr[__serial_pcount] = (addr);	\
-		__serial_pcount += 1;				\
-	} while (0)
-#else
-#define ADD_ECARD(ec,card)
-#define ADD_PORT(port,addr)
-#endif
+struct serial_card_info {
+	unsigned int	num_ports;
+	int		ports[MAX_PORTS];
+};
 
-static const card_ids serial_cids[] = { MY_CARD_LIST, { 0xffff, 0xffff } };
-
-static inline int serial_register_onedev (unsigned long port, int irq)
+static inline int
+serial_register_onedev(unsigned long baddr, void *vaddr, int irq, unsigned int baud_base)
 {
-    struct serial_struct req;
+	struct serial_struct req;
 
-    memset(&req, 0, sizeof(req));
-    req.baud_base = MY_BAUD_BASE;
-    req.irq = irq;
-    req.port = port;
-    req.flags = 0;
+	memset(&req, 0, sizeof(req));
+	req.irq 		= irq;
+	req.flags		= UPF_AUTOPROBE | UPF_RESOURCES |
+				  UPF_SHARE_IRQ;
+	req.baud_base		= baud_base;
+	req.io_type		= UPIO_MEM;
+	req.iomem_base		= vaddr;
+	req.iomem_reg_shift	= 2;
+	req.iomap_base		= baddr;
 
-    return register_serial(&req);
+	return register_serial(&req);
 }
 
-static int __init INIT (void)
+static int __devinit
+serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
-    int card = 0;
-
-    ecard_startfind ();
+	struct serial_card_info *info;
+	struct serial_card_type *type = id->data;
+	unsigned long bus_addr;
+	unsigned char *virt_addr;
+	unsigned int port;
+
+	info = kmalloc(sizeof(struct serial_card_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	memset(info, 0, sizeof(struct serial_card_info));
+	info->num_ports = type->num_ports;
+
+	ecard_set_drvdata(ec, info);
+
+	bus_addr = ec->resource[type->type].start;
+	virt_addr = ioremap(bus_addr, ec->resource[type->type].end - bus_addr + 1);
+	if (!virt_addr) {
+		kfree(info);
+		return -ENOMEM;
+	}
 
-    do {
-	struct expansion_card *ec;
-	unsigned long cardaddr;
-	int port;
+	for (port = 0; port < info->num_ports; port ++) {
+		unsigned long baddr = bus_addr + type->offset[port];
+		unsigned char *vaddr = virt_addr + type->offset[port];
 
-	ec = ecard_find (0, serial_cids);
-	if (!ec)
-	    break;
+		info->ports[port] = serial_register_onedev(baddr, vaddr,
+						ec->irq, type->baud_base);
+	}
 
-	cardaddr = MY_BASE_ADDRESS(ec);
+	return 0;
+}
 
-	for (port = 0; port < MY_NUMPORTS; port ++) {
-	    unsigned long address;
-	    int line;
+static void __devexit serial_card_remove(struct expansion_card *ec)
+{
+	struct serial_card_info *info = ecard_get_drvdata(ec);
+	int i;
 
-	    address = MY_PORT_ADDRESS(port, cardaddr);
+	ecard_set_drvdata(ec, NULL);
 
-	    line = serial_register_onedev (address, ec->irq);
-	    if (line < 0)
-		break;
-	    ADD_PORT(line, address);
-	}
+	for (i = 0; i < info->num_ports; i++)
+		if (info->ports[i] > 0)
+			unregister_serial(info->ports[i]);
 
-	if (port) {
-	    ecard_claim (ec);
-	    ADD_ECARD(ec, card);
-	} else
-	    break;
-    } while (++card < MAX_ECARDS);
-    return card ? 0 : -ENODEV;
+	kfree(info);
 }
 
-static void __exit EXIT (void)
+static struct ecard_driver serial_card_driver = {
+	.probe		= serial_card_probe,
+	.remove 	= __devexit_p(serial_card_remove),
+	.id_table	= serial_cids,
+};
+
+static int __init serial_card_init(void)
 {
-#ifdef MODULE
-    int i;
+	return ecard_register_driver(&serial_card_driver);
+}
 
-    for (i = 0; i < __serial_pcount; i++) {
-	unregister_serial(__serial_ports[i]);
-	release_region(__serial_addr[i], 8);
-    }
-
-    for (i = 0; i < MAX_ECARDS; i++)
-	if (expcard[i])
-	    ecard_release (expcard[i]);
-#endif
+static void __exit serial_card_exit(void)
+{
+	ecard_remove_driver(&serial_card_driver);
 }
 
 EXPORT_NO_SYMBOLS;
 
+MODULE_AUTHOR("Russell King");
 MODULE_LICENSE("GPL");
 
-module_init(INIT);
-module_exit(EXIT);
+module_init(serial_card_init);
+module_exit(serial_card_exit);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)