1/************************************************************************
2 * Copyright 2003 Digi International (www.digi.com)
3 *
4 * Copyright (C) 2004 IBM Corporation. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
13 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE.  See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 * Temple Place - Suite 330, Boston,
19 * MA  02111-1307, USA.
20 *
21 * Contact Information:
22 * Scott H Kilau <Scott_Kilau@digi.com>
23 * Wendy Xiong   <wendyx@us.ibm.com>
24 *
25 *
26 ***********************************************************************/
27#include <linux/moduleparam.h>
28#include <linux/pci.h>
29
30#include "jsm.h"
31
32MODULE_AUTHOR("Digi International, http://www.digi.com");
33MODULE_DESCRIPTION("Driver for the Digi International "
34		   "Neo PCI based product line");
35MODULE_LICENSE("GPL");
36MODULE_SUPPORTED_DEVICE("jsm");
37
38#define JSM_DRIVER_NAME "jsm"
39#define NR_PORTS	32
40#define JSM_MINOR_START	0
41
42struct uart_driver jsm_uart_driver = {
43	.owner		= THIS_MODULE,
44	.driver_name	= JSM_DRIVER_NAME,
45	.dev_name	= "ttyn",
46	.major		= 0,
47	.minor		= JSM_MINOR_START,
48	.nr		= NR_PORTS,
49};
50
51int jsm_debug;
52module_param(jsm_debug, int, 0);
53MODULE_PARM_DESC(jsm_debug, "Driver debugging level");
54
55static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
56{
57	int rc = 0;
58	struct jsm_board *brd;
59	static int adapter_count = 0;
60	int retval;
61
62	rc = pci_enable_device(pdev);
63	if (rc) {
64		dev_err(&pdev->dev, "Device enable FAILED\n");
65		goto out;
66	}
67
68	rc = pci_request_regions(pdev, "jsm");
69	if (rc) {
70		dev_err(&pdev->dev, "pci_request_region FAILED\n");
71		goto out_disable_device;
72	}
73
74	brd = kzalloc(sizeof(struct jsm_board), GFP_KERNEL);
75	if (!brd) {
76		dev_err(&pdev->dev,
77			"memory allocation for board structure failed\n");
78		rc = -ENOMEM;
79		goto out_release_regions;
80	}
81
82	/* store the info for the board we've found */
83	brd->boardnum = adapter_count++;
84	brd->pci_dev = pdev;
85	brd->maxports = 2;
86
87	spin_lock_init(&brd->bd_lock);
88	spin_lock_init(&brd->bd_intr_lock);
89
90	/* store which revision we have */
91	pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
92
93	brd->irq = pdev->irq;
94
95	jsm_printk(INIT, INFO, &brd->pci_dev,
96		"jsm_found_board - NEO adapter\n");
97
98	/* get the PCI Base Address Registers */
99	brd->membase	= pci_resource_start(pdev, 0);
100	brd->membase_end = pci_resource_end(pdev, 0);
101
102	if (brd->membase & 1)
103		brd->membase &= ~3;
104	else
105		brd->membase &= ~15;
106
107	/* Assign the board_ops struct */
108	brd->bd_ops = &jsm_neo_ops;
109
110	brd->bd_uart_offset = 0x200;
111	brd->bd_dividend = 921600;
112
113	brd->re_map_membase = ioremap(brd->membase, 0x1000);
114	if (!brd->re_map_membase) {
115		dev_err(&pdev->dev,
116			"card has no PCI Memory resources, "
117			"failing board.\n");
118		rc = -ENOMEM;
119		goto out_kfree_brd;
120	}
121
122	rc = request_irq(brd->irq, brd->bd_ops->intr,
123			IRQF_DISABLED|IRQF_SHARED, "JSM", brd);
124	if (rc) {
125		printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq);
126		goto out_iounmap;
127	}
128
129	rc = jsm_tty_init(brd);
130	if (rc < 0) {
131		dev_err(&pdev->dev, "Can't init tty devices (%d)\n", rc);
132		retval = -ENXIO;
133		goto out_free_irq;
134	}
135
136	rc = jsm_uart_port_init(brd);
137	if (rc < 0) {
138		dev_err(&pdev->dev, "Can't init uart port (%d)\n", rc);
139		retval = -ENXIO;
140		goto out_free_irq;
141	}
142
143	/* Log the information about the board */
144	dev_info(&pdev->dev, "board %d: Digi Neo (rev %d), irq %d\n",
145			adapter_count, brd->rev, brd->irq);
146
147	/*
148	 * allocate flip buffer for board.
149	 *
150	 * Okay to malloc with GFP_KERNEL, we are not at interrupt
151	 * context, and there are no locks held.
152	 */
153	brd->flipbuf = kzalloc(MYFLIPLEN, GFP_KERNEL);
154	if (!brd->flipbuf) {
155		dev_err(&pdev->dev, "memory allocation for flipbuf failed\n");
156		retval = -ENOMEM;
157		goto out_free_irq;
158	}
159
160	pci_set_drvdata(pdev, brd);
161
162	return 0;
163 out_free_irq:
164	free_irq(brd->irq, brd);
165 out_iounmap:
166	iounmap(brd->re_map_membase);
167 out_kfree_brd:
168	kfree(brd);
169 out_release_regions:
170	pci_release_regions(pdev);
171 out_disable_device:
172	pci_disable_device(pdev);
173 out:
174	return rc;
175}
176
177static void jsm_remove_one(struct pci_dev *pdev)
178{
179	struct jsm_board *brd = pci_get_drvdata(pdev);
180	int i = 0;
181
182	jsm_remove_uart_port(brd);
183
184	free_irq(brd->irq, brd);
185	iounmap(brd->re_map_membase);
186
187	/* Free all allocated channels structs */
188	for (i = 0; i < brd->maxports; i++) {
189		if (brd->channels[i]) {
190			kfree(brd->channels[i]->ch_rqueue);
191			kfree(brd->channels[i]->ch_equeue);
192			kfree(brd->channels[i]->ch_wqueue);
193			kfree(brd->channels[i]);
194		}
195	}
196
197	pci_release_regions(pdev);
198	pci_disable_device(pdev);
199	kfree(brd->flipbuf);
200	kfree(brd);
201}
202
203static struct pci_device_id jsm_pci_tbl[] = {
204	{ PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2DB9), 0, 0, 0 },
205	{ PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2DB9PRI), 0, 0, 1 },
206	{ PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45), 0, 0, 2 },
207	{ PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45PRI), 0, 0, 3 },
208	{ 0, }
209};
210MODULE_DEVICE_TABLE(pci, jsm_pci_tbl);
211
212static struct pci_driver jsm_driver = {
213	.name		= "jsm",
214	.id_table	= jsm_pci_tbl,
215	.probe		= jsm_probe_one,
216	.remove		= __devexit_p(jsm_remove_one),
217};
218
219static int __init jsm_init_module(void)
220{
221	int rc;
222
223	rc = uart_register_driver(&jsm_uart_driver);
224	if (!rc) {
225		rc = pci_register_driver(&jsm_driver);
226		if (rc)
227			uart_unregister_driver(&jsm_uart_driver);
228	}
229	return rc;
230}
231
232static void __exit jsm_exit_module(void)
233{
234	pci_unregister_driver(&jsm_driver);
235	uart_unregister_driver(&jsm_uart_driver);
236}
237
238module_init(jsm_init_module);
239module_exit(jsm_exit_module);
240