2 * linux/drivers/acorn/char/serial-card.c
4 * Copyright (C) 1996-1999 Russell King.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * A generic handler of serial expansion cards that use 16550s or
14 * MY_PRODS Product numbers to identify this card by
15 * MY_MANUS Manufacturer numbers to identify this card by
16 * MY_NUMPORTS Number of ports per card
17 * MY_BAUD_BASE Baud base for the card
18 * MY_INIT Initialisation routine name
19 * MY_BASE_ADDRESS(ec) Return base address for ports
21 * (port,cardaddr) Return address for port using base address
25 * 30-07-1996 RMK Created
26 * 22-04-1998 RMK Removed old register_pre_init_serial
28 #include <linux/module.h>
29 #include <linux/types.h>
30 #include <linux/tty.h>
31 #include <linux/serial_core.h>
32 #include <linux/errno.h>
33 #include <linux/ioport.h>
34 #include <linux/slab.h>
35 #include <linux/init.h>
38 #include <asm/ecard.h>
39 #include <asm/string.h>
41 struct serial_card_info {
42 unsigned int num_ports;
47 serial_register_onedev(unsigned long baddr, void *vaddr, int irq, unsigned int baud_base)
49 struct serial_struct req;
51 memset(&req, 0, sizeof(req));
53 req.flags = UPF_AUTOPROBE | UPF_RESOURCES |
55 req.baud_base = baud_base;
56 req.io_type = UPIO_MEM;
57 req.iomem_base = vaddr;
58 req.iomem_reg_shift = 2;
59 req.iomap_base = baddr;
61 return register_serial(&req);
65 serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
67 struct serial_card_info *info;
68 struct serial_card_type *type = id->data;
69 unsigned long bus_addr;
70 unsigned char *virt_addr;
73 info = kmalloc(sizeof(struct serial_card_info), GFP_KERNEL);
77 memset(info, 0, sizeof(struct serial_card_info));
78 info->num_ports = type->num_ports;
80 ecard_set_drvdata(ec, info);
82 bus_addr = ec->resource[type->type].start;
83 virt_addr = ioremap(bus_addr, ec->resource[type->type].end - bus_addr + 1);
89 for (port = 0; port < info->num_ports; port ++) {
90 unsigned long baddr = bus_addr + type->offset[port];
91 unsigned char *vaddr = virt_addr + type->offset[port];
93 info->ports[port] = serial_register_onedev(baddr, vaddr,
94 ec->irq, type->baud_base);
100 static void __devexit serial_card_remove(struct expansion_card *ec)
102 struct serial_card_info *info = ecard_get_drvdata(ec);
105 ecard_set_drvdata(ec, NULL);
107 for (i = 0; i < info->num_ports; i++)
108 if (info->ports[i] > 0)
109 unregister_serial(info->ports[i]);
114 static struct ecard_driver serial_card_driver = {
115 .probe = serial_card_probe,
116 .remove = __devexit_p(serial_card_remove),
117 .id_table = serial_cids,
120 static int __init serial_card_init(void)
122 return ecard_register_driver(&serial_card_driver);
125 static void __exit serial_card_exit(void)
127 ecard_remove_driver(&serial_card_driver);
132 MODULE_AUTHOR("Russell King");
133 MODULE_LICENSE("GPL");
135 module_init(serial_card_init);
136 module_exit(serial_card_exit);