blob: 9d3105b64a7a597ba3f634ad4b270dd72d7e4ff9 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * icom.c
3 *
4 * Copyright (C) 2001 IBM Corporation. All rights reserved.
5 *
6 * Serial device driver.
7 *
8 * Based on code from serial.c
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25#define SERIAL_DO_RESTART
26#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/kernel.h>
28#include <linux/errno.h>
29#include <linux/signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <linux/timer.h>
31#include <linux/interrupt.h>
32#include <linux/tty.h>
33#include <linux/termios.h>
34#include <linux/fs.h>
35#include <linux/tty_flip.h>
36#include <linux/serial.h>
37#include <linux/serial_reg.h>
38#include <linux/major.h>
39#include <linux/string.h>
40#include <linux/fcntl.h>
41#include <linux/ptrace.h>
42#include <linux/ioport.h>
43#include <linux/mm.h>
44#include <linux/slab.h>
45#include <linux/init.h>
46#include <linux/delay.h>
47#include <linux/pci.h>
48#include <linux/vmalloc.h>
49#include <linux/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#include <linux/spinlock.h>
51#include <linux/kobject.h>
52#include <linux/firmware.h>
53#include <linux/bitops.h>
54
55#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070056#include <asm/io.h>
57#include <asm/irq.h>
58#include <asm/uaccess.h>
59
60#include "icom.h"
61
62/*#define ICOM_TRACE enable port trace capabilities */
63
64#define ICOM_DRIVER_NAME "icom"
65#define ICOM_VERSION_STR "1.3.1"
66#define NR_PORTS 128
67#define ICOM_PORT ((struct icom_port *)port)
68#define to_icom_adapter(d) container_of(d, struct icom_adapter, kobj)
69
70static const struct pci_device_id icom_pci_table[] = {
71 {
wendy xiongbc88d5d2007-05-16 22:11:16 -070072 .vendor = PCI_VENDOR_ID_IBM,
73 .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1,
74 .subvendor = PCI_ANY_ID,
75 .subdevice = PCI_ANY_ID,
76 .driver_data = ADAPTER_V1,
77 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 {
wendy xiongbc88d5d2007-05-16 22:11:16 -070079 .vendor = PCI_VENDOR_ID_IBM,
80 .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
81 .subvendor = PCI_VENDOR_ID_IBM,
82 .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX,
83 .driver_data = ADAPTER_V2,
84 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 {
wendy xiongbc88d5d2007-05-16 22:11:16 -070086 .vendor = PCI_VENDOR_ID_IBM,
87 .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
88 .subvendor = PCI_VENDOR_ID_IBM,
89 .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM,
90 .driver_data = ADAPTER_V2,
91 },
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 {
wendy xiongbc88d5d2007-05-16 22:11:16 -070093 .vendor = PCI_VENDOR_ID_IBM,
94 .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
95 .subvendor = PCI_VENDOR_ID_IBM,
96 .subdevice = PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL,
97 .driver_data = ADAPTER_V2,
98 },
99 {
100 .vendor = PCI_VENDOR_ID_IBM,
101 .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2,
102 .subvendor = PCI_VENDOR_ID_IBM,
103 .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE,
104 .driver_data = ADAPTER_V2,
105 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 {}
107};
108
109struct lookup_proc_table start_proc[4] = {
110 {NULL, ICOM_CONTROL_START_A},
111 {NULL, ICOM_CONTROL_START_B},
112 {NULL, ICOM_CONTROL_START_C},
113 {NULL, ICOM_CONTROL_START_D}
114};
115
116
117struct lookup_proc_table stop_proc[4] = {
118 {NULL, ICOM_CONTROL_STOP_A},
119 {NULL, ICOM_CONTROL_STOP_B},
120 {NULL, ICOM_CONTROL_STOP_C},
121 {NULL, ICOM_CONTROL_STOP_D}
122};
123
124struct lookup_int_table int_mask_tbl[4] = {
125 {NULL, ICOM_INT_MASK_PRC_A},
126 {NULL, ICOM_INT_MASK_PRC_B},
127 {NULL, ICOM_INT_MASK_PRC_C},
128 {NULL, ICOM_INT_MASK_PRC_D},
129};
130
131
132MODULE_DEVICE_TABLE(pci, icom_pci_table);
133
134static LIST_HEAD(icom_adapter_head);
135
136/* spinlock for adapter initialization and changing adapter operations */
137static spinlock_t icom_lock;
138
139#ifdef ICOM_TRACE
140static inline void trace(struct icom_port *, char *, unsigned long) {};
141#else
142static inline void trace(struct icom_port *icom_port, char *trace_pt, unsigned long trace_data) {};
143#endif
144
145static void free_port_memory(struct icom_port *icom_port)
146{
147 struct pci_dev *dev = icom_port->adapter->pci_dev;
148
149 trace(icom_port, "RET_PORT_MEM", 0);
150 if (icom_port->recv_buf) {
151 pci_free_consistent(dev, 4096, icom_port->recv_buf,
152 icom_port->recv_buf_pci);
153 icom_port->recv_buf = NULL;
154 }
155 if (icom_port->xmit_buf) {
156 pci_free_consistent(dev, 4096, icom_port->xmit_buf,
157 icom_port->xmit_buf_pci);
158 icom_port->xmit_buf = NULL;
159 }
160 if (icom_port->statStg) {
161 pci_free_consistent(dev, 4096, icom_port->statStg,
162 icom_port->statStg_pci);
163 icom_port->statStg = NULL;
164 }
165
166 if (icom_port->xmitRestart) {
167 pci_free_consistent(dev, 4096, icom_port->xmitRestart,
168 icom_port->xmitRestart_pci);
169 icom_port->xmitRestart = NULL;
170 }
171}
172
Jiri Slaby98f85d32007-04-23 14:41:20 -0700173static int __devinit get_port_memory(struct icom_port *icom_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174{
175 int index;
176 unsigned long stgAddr;
177 unsigned long startStgAddr;
178 unsigned long offset;
179 struct pci_dev *dev = icom_port->adapter->pci_dev;
180
181 icom_port->xmit_buf =
182 pci_alloc_consistent(dev, 4096, &icom_port->xmit_buf_pci);
183 if (!icom_port->xmit_buf) {
184 dev_err(&dev->dev, "Can not allocate Transmit buffer\n");
185 return -ENOMEM;
186 }
187
188 trace(icom_port, "GET_PORT_MEM",
189 (unsigned long) icom_port->xmit_buf);
190
191 icom_port->recv_buf =
192 pci_alloc_consistent(dev, 4096, &icom_port->recv_buf_pci);
193 if (!icom_port->recv_buf) {
194 dev_err(&dev->dev, "Can not allocate Receive buffer\n");
195 free_port_memory(icom_port);
196 return -ENOMEM;
197 }
198 trace(icom_port, "GET_PORT_MEM",
199 (unsigned long) icom_port->recv_buf);
200
201 icom_port->statStg =
202 pci_alloc_consistent(dev, 4096, &icom_port->statStg_pci);
203 if (!icom_port->statStg) {
204 dev_err(&dev->dev, "Can not allocate Status buffer\n");
205 free_port_memory(icom_port);
206 return -ENOMEM;
207 }
208 trace(icom_port, "GET_PORT_MEM",
209 (unsigned long) icom_port->statStg);
210
211 icom_port->xmitRestart =
212 pci_alloc_consistent(dev, 4096, &icom_port->xmitRestart_pci);
213 if (!icom_port->xmitRestart) {
214 dev_err(&dev->dev,
215 "Can not allocate xmit Restart buffer\n");
216 free_port_memory(icom_port);
217 return -ENOMEM;
218 }
219
220 memset(icom_port->statStg, 0, 4096);
221
222 /* FODs: Frame Out Descriptor Queue, this is a FIFO queue that
223 indicates that frames are to be transmitted
224 */
225
226 stgAddr = (unsigned long) icom_port->statStg;
227 for (index = 0; index < NUM_XBUFFS; index++) {
228 trace(icom_port, "FOD_ADDR", stgAddr);
229 stgAddr = stgAddr + sizeof(icom_port->statStg->xmit[0]);
230 if (index < (NUM_XBUFFS - 1)) {
231 memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
232 icom_port->statStg->xmit[index].leLengthASD =
233 (unsigned short int) cpu_to_le16(XMIT_BUFF_SZ);
234 trace(icom_port, "FOD_ADDR", stgAddr);
235 trace(icom_port, "FOD_XBUFF",
236 (unsigned long) icom_port->xmit_buf);
237 icom_port->statStg->xmit[index].leBuffer =
238 cpu_to_le32(icom_port->xmit_buf_pci);
239 } else if (index == (NUM_XBUFFS - 1)) {
240 memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
241 icom_port->statStg->xmit[index].leLengthASD =
242 (unsigned short int) cpu_to_le16(XMIT_BUFF_SZ);
243 trace(icom_port, "FOD_XBUFF",
244 (unsigned long) icom_port->xmit_buf);
245 icom_port->statStg->xmit[index].leBuffer =
246 cpu_to_le32(icom_port->xmit_buf_pci);
247 } else {
248 memset(&icom_port->statStg->xmit[index], 0, sizeof(struct xmit_status_area));
249 }
250 }
251 /* FIDs */
252 startStgAddr = stgAddr;
253
254 /* fill in every entry, even if no buffer */
255 for (index = 0; index < NUM_RBUFFS; index++) {
256 trace(icom_port, "FID_ADDR", stgAddr);
257 stgAddr = stgAddr + sizeof(icom_port->statStg->rcv[0]);
258 icom_port->statStg->rcv[index].leLength = 0;
259 icom_port->statStg->rcv[index].WorkingLength =
260 (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
261 if (index < (NUM_RBUFFS - 1) ) {
262 offset = stgAddr - (unsigned long) icom_port->statStg;
263 icom_port->statStg->rcv[index].leNext =
264 cpu_to_le32(icom_port-> statStg_pci + offset);
265 trace(icom_port, "FID_RBUFF",
266 (unsigned long) icom_port->recv_buf);
267 icom_port->statStg->rcv[index].leBuffer =
268 cpu_to_le32(icom_port->recv_buf_pci);
269 } else if (index == (NUM_RBUFFS -1) ) {
270 offset = startStgAddr - (unsigned long) icom_port->statStg;
271 icom_port->statStg->rcv[index].leNext =
272 cpu_to_le32(icom_port-> statStg_pci + offset);
273 trace(icom_port, "FID_RBUFF",
274 (unsigned long) icom_port->recv_buf + 2048);
275 icom_port->statStg->rcv[index].leBuffer =
276 cpu_to_le32(icom_port->recv_buf_pci + 2048);
277 } else {
278 icom_port->statStg->rcv[index].leNext = 0;
279 icom_port->statStg->rcv[index].leBuffer = 0;
280 }
281 }
282
283 return 0;
284}
285
286static void stop_processor(struct icom_port *icom_port)
287{
288 unsigned long temp;
289 unsigned long flags;
290 int port;
291
292 spin_lock_irqsave(&icom_lock, flags);
293
294 port = icom_port->port;
295 if (port == 0 || port == 1)
296 stop_proc[port].global_control_reg = &icom_port->global_reg->control;
297 else
298 stop_proc[port].global_control_reg = &icom_port->global_reg->control_2;
299
300
301 if (port < 4) {
302 temp = readl(stop_proc[port].global_control_reg);
303 temp =
304 (temp & ~start_proc[port].processor_id) | stop_proc[port].processor_id;
305 writel(temp, stop_proc[port].global_control_reg);
306
307 /* write flush */
308 readl(stop_proc[port].global_control_reg);
309 } else {
310 dev_err(&icom_port->adapter->pci_dev->dev,
311 "Invalid port assignment\n");
312 }
313
314 spin_unlock_irqrestore(&icom_lock, flags);
315}
316
317static void start_processor(struct icom_port *icom_port)
318{
319 unsigned long temp;
320 unsigned long flags;
321 int port;
322
323 spin_lock_irqsave(&icom_lock, flags);
324
325 port = icom_port->port;
326 if (port == 0 || port == 1)
327 start_proc[port].global_control_reg = &icom_port->global_reg->control;
328 else
329 start_proc[port].global_control_reg = &icom_port->global_reg->control_2;
330 if (port < 4) {
331 temp = readl(start_proc[port].global_control_reg);
332 temp =
333 (temp & ~stop_proc[port].processor_id) | start_proc[port].processor_id;
334 writel(temp, start_proc[port].global_control_reg);
335
336 /* write flush */
337 readl(start_proc[port].global_control_reg);
338 } else {
339 dev_err(&icom_port->adapter->pci_dev->dev,
340 "Invalid port assignment\n");
341 }
342
343 spin_unlock_irqrestore(&icom_lock, flags);
344}
345
346static void load_code(struct icom_port *icom_port)
347{
348 const struct firmware *fw;
349 char __iomem *iram_ptr;
350 int index;
351 int status = 0;
352 void __iomem *dram_ptr = icom_port->dram;
353 dma_addr_t temp_pci;
354 unsigned char *new_page = NULL;
355 unsigned char cable_id = NO_CABLE;
356 struct pci_dev *dev = icom_port->adapter->pci_dev;
357
358 /* Clear out any pending interrupts */
359 writew(0x3FFF, icom_port->int_reg);
360
361 trace(icom_port, "CLEAR_INTERRUPTS", 0);
362
363 /* Stop processor */
364 stop_processor(icom_port);
365
366 /* Zero out DRAM */
367 memset_io(dram_ptr, 0, 512);
368
369 /* Load Call Setup into Adapter */
370 if (request_firmware(&fw, "icom_call_setup.bin", &dev->dev) < 0) {
371 dev_err(&dev->dev,"Unable to load icom_call_setup.bin firmware image\n");
372 status = -1;
373 goto load_code_exit;
374 }
375
376 if (fw->size > ICOM_DCE_IRAM_OFFSET) {
377 dev_err(&dev->dev, "Invalid firmware image for icom_call_setup.bin found.\n");
378 release_firmware(fw);
379 status = -1;
380 goto load_code_exit;
381 }
382
383 iram_ptr = (char __iomem *)icom_port->dram + ICOM_IRAM_OFFSET;
384 for (index = 0; index < fw->size; index++)
385 writeb(fw->data[index], &iram_ptr[index]);
386
387 release_firmware(fw);
388
389 /* Load Resident DCE portion of Adapter */
390 if (request_firmware(&fw, "icom_res_dce.bin", &dev->dev) < 0) {
391 dev_err(&dev->dev,"Unable to load icom_res_dce.bin firmware image\n");
392 status = -1;
393 goto load_code_exit;
394 }
395
396 if (fw->size > ICOM_IRAM_SIZE) {
397 dev_err(&dev->dev, "Invalid firmware image for icom_res_dce.bin found.\n");
398 release_firmware(fw);
399 status = -1;
400 goto load_code_exit;
401 }
402
403 iram_ptr = (char __iomem *) icom_port->dram + ICOM_IRAM_OFFSET;
404 for (index = ICOM_DCE_IRAM_OFFSET; index < fw->size; index++)
405 writeb(fw->data[index], &iram_ptr[index]);
406
407 release_firmware(fw);
408
409 /* Set Hardware level */
410 if ((icom_port->adapter->version | ADAPTER_V2) == ADAPTER_V2)
411 writeb(V2_HARDWARE, &(icom_port->dram->misc_flags));
412
413 /* Start the processor in Adapter */
414 start_processor(icom_port);
415
416 writeb((HDLC_PPP_PURE_ASYNC | HDLC_FF_FILL),
417 &(icom_port->dram->HDLCConfigReg));
418 writeb(0x04, &(icom_port->dram->FlagFillIdleTimer)); /* 0.5 seconds */
419 writeb(0x00, &(icom_port->dram->CmdReg));
420 writeb(0x10, &(icom_port->dram->async_config3));
421 writeb((ICOM_ACFG_DRIVE1 | ICOM_ACFG_NO_PARITY | ICOM_ACFG_8BPC |
422 ICOM_ACFG_1STOP_BIT), &(icom_port->dram->async_config2));
423
424 /*Set up data in icom DRAM to indicate where personality
425 *code is located and its length.
426 */
427 new_page = pci_alloc_consistent(dev, 4096, &temp_pci);
428
429 if (!new_page) {
430 dev_err(&dev->dev, "Can not allocate DMA buffer\n");
431 status = -1;
432 goto load_code_exit;
433 }
434
435 if (request_firmware(&fw, "icom_asc.bin", &dev->dev) < 0) {
436 dev_err(&dev->dev,"Unable to load icom_asc.bin firmware image\n");
437 status = -1;
438 goto load_code_exit;
439 }
440
441 if (fw->size > ICOM_DCE_IRAM_OFFSET) {
442 dev_err(&dev->dev, "Invalid firmware image for icom_asc.bin found.\n");
443 release_firmware(fw);
444 status = -1;
445 goto load_code_exit;
446 }
447
448 for (index = 0; index < fw->size; index++)
449 new_page[index] = fw->data[index];
450
451 release_firmware(fw);
452
453 writeb((char) ((fw->size + 16)/16), &icom_port->dram->mac_length);
454 writel(temp_pci, &icom_port->dram->mac_load_addr);
455
456 /*Setting the syncReg to 0x80 causes adapter to start downloading
457 the personality code into adapter instruction RAM.
458 Once code is loaded, it will begin executing and, based on
459 information provided above, will start DMAing data from
460 shared memory to adapter DRAM.
461 */
462 /* the wait loop below verifies this write operation has been done
463 and processed
464 */
465 writeb(START_DOWNLOAD, &icom_port->dram->sync);
466
467 /* Wait max 1 Sec for data download and processor to start */
468 for (index = 0; index < 10; index++) {
469 msleep(100);
470 if (readb(&icom_port->dram->misc_flags) & ICOM_HDW_ACTIVE)
471 break;
472 }
473
474 if (index == 10)
475 status = -1;
476
477 /*
478 * check Cable ID
479 */
480 cable_id = readb(&icom_port->dram->cable_id);
481
482 if (cable_id & ICOM_CABLE_ID_VALID) {
483 /* Get cable ID into the lower 4 bits (standard form) */
484 cable_id = (cable_id & ICOM_CABLE_ID_MASK) >> 4;
485 icom_port->cable_id = cable_id;
486 } else {
487 dev_err(&dev->dev,"Invalid or no cable attached\n");
488 icom_port->cable_id = NO_CABLE;
489 }
490
491 load_code_exit:
492
493 if (status != 0) {
494 /* Clear out any pending interrupts */
495 writew(0x3FFF, icom_port->int_reg);
496
497 /* Turn off port */
498 writeb(ICOM_DISABLE, &(icom_port->dram->disable));
499
500 /* Stop processor */
501 stop_processor(icom_port);
502
503 dev_err(&icom_port->adapter->pci_dev->dev,"Port not opertional\n");
504 }
505
506 if (new_page != NULL)
507 pci_free_consistent(dev, 4096, new_page, temp_pci);
508}
509
510static int startup(struct icom_port *icom_port)
511{
512 unsigned long temp;
513 unsigned char cable_id, raw_cable_id;
514 unsigned long flags;
515 int port;
516
517 trace(icom_port, "STARTUP", 0);
518
519 if (!icom_port->dram) {
520 /* should NEVER be NULL */
521 dev_err(&icom_port->adapter->pci_dev->dev,
522 "Unusable Port, port configuration missing\n");
523 return -ENODEV;
524 }
525
526 /*
527 * check Cable ID
528 */
529 raw_cable_id = readb(&icom_port->dram->cable_id);
530 trace(icom_port, "CABLE_ID", raw_cable_id);
531
532 /* Get cable ID into the lower 4 bits (standard form) */
533 cable_id = (raw_cable_id & ICOM_CABLE_ID_MASK) >> 4;
534
535 /* Check for valid Cable ID */
536 if (!(raw_cable_id & ICOM_CABLE_ID_VALID) ||
537 (cable_id != icom_port->cable_id)) {
538
539 /* reload adapter code, pick up any potential changes in cable id */
540 load_code(icom_port);
541
542 /* still no sign of cable, error out */
543 raw_cable_id = readb(&icom_port->dram->cable_id);
544 cable_id = (raw_cable_id & ICOM_CABLE_ID_MASK) >> 4;
545 if (!(raw_cable_id & ICOM_CABLE_ID_VALID) ||
546 (icom_port->cable_id == NO_CABLE))
547 return -EIO;
548 }
549
550 /*
551 * Finally, clear and enable interrupts
552 */
553 spin_lock_irqsave(&icom_lock, flags);
554 port = icom_port->port;
555 if (port == 0 || port == 1)
556 int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask;
557 else
558 int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask_2;
559
560 if (port == 0 || port == 2)
561 writew(0x00FF, icom_port->int_reg);
562 else
563 writew(0x3F00, icom_port->int_reg);
564 if (port < 4) {
565 temp = readl(int_mask_tbl[port].global_int_mask);
566 writel(temp & ~int_mask_tbl[port].processor_id, int_mask_tbl[port].global_int_mask);
567
568 /* write flush */
569 readl(int_mask_tbl[port].global_int_mask);
570 } else {
571 dev_err(&icom_port->adapter->pci_dev->dev,
572 "Invalid port assignment\n");
573 }
574
575 spin_unlock_irqrestore(&icom_lock, flags);
576 return 0;
577}
578
579static void shutdown(struct icom_port *icom_port)
580{
581 unsigned long temp;
582 unsigned char cmdReg;
583 unsigned long flags;
584 int port;
585
586 spin_lock_irqsave(&icom_lock, flags);
587 trace(icom_port, "SHUTDOWN", 0);
588
589 /*
590 * disable all interrupts
591 */
592 port = icom_port->port;
593 if (port == 0 || port == 1)
594 int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask;
595 else
596 int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask_2;
597
598 if (port < 4) {
599 temp = readl(int_mask_tbl[port].global_int_mask);
600 writel(temp | int_mask_tbl[port].processor_id, int_mask_tbl[port].global_int_mask);
601
602 /* write flush */
603 readl(int_mask_tbl[port].global_int_mask);
604 } else {
605 dev_err(&icom_port->adapter->pci_dev->dev,
606 "Invalid port assignment\n");
607 }
608 spin_unlock_irqrestore(&icom_lock, flags);
609
610 /*
611 * disable break condition
612 */
613 cmdReg = readb(&icom_port->dram->CmdReg);
614 if ((cmdReg | CMD_SND_BREAK) == CMD_SND_BREAK) {
615 writeb(cmdReg & ~CMD_SND_BREAK, &icom_port->dram->CmdReg);
616 }
617}
618
619static int icom_write(struct uart_port *port)
620{
621 unsigned long data_count;
622 unsigned char cmdReg;
623 unsigned long offset;
624 int temp_tail = port->info->xmit.tail;
625
626 trace(ICOM_PORT, "WRITE", 0);
627
628 if (cpu_to_le16(ICOM_PORT->statStg->xmit[0].flags) &
629 SA_FLAGS_READY_TO_XMIT) {
630 trace(ICOM_PORT, "WRITE_FULL", 0);
631 return 0;
632 }
633
634 data_count = 0;
635 while ((port->info->xmit.head != temp_tail) &&
636 (data_count <= XMIT_BUFF_SZ)) {
637
638 ICOM_PORT->xmit_buf[data_count++] =
639 port->info->xmit.buf[temp_tail];
640
641 temp_tail++;
642 temp_tail &= (UART_XMIT_SIZE - 1);
643 }
644
645 if (data_count) {
646 ICOM_PORT->statStg->xmit[0].flags =
647 cpu_to_le16(SA_FLAGS_READY_TO_XMIT);
648 ICOM_PORT->statStg->xmit[0].leLength =
649 cpu_to_le16(data_count);
650 offset =
651 (unsigned long) &ICOM_PORT->statStg->xmit[0] -
652 (unsigned long) ICOM_PORT->statStg;
653 *ICOM_PORT->xmitRestart =
654 cpu_to_le32(ICOM_PORT->statStg_pci + offset);
655 cmdReg = readb(&ICOM_PORT->dram->CmdReg);
656 writeb(cmdReg | CMD_XMIT_RCV_ENABLE,
657 &ICOM_PORT->dram->CmdReg);
658 writeb(START_XMIT, &ICOM_PORT->dram->StartXmitCmd);
659 trace(ICOM_PORT, "WRITE_START", data_count);
660 /* write flush */
661 readb(&ICOM_PORT->dram->StartXmitCmd);
662 }
663
664 return data_count;
665}
666
667static inline void check_modem_status(struct icom_port *icom_port)
668{
669 static char old_status = 0;
670 char delta_status;
671 unsigned char status;
672
673 spin_lock(&icom_port->uart_port.lock);
674
675 /*modem input register */
676 status = readb(&icom_port->dram->isr);
677 trace(icom_port, "CHECK_MODEM", status);
678 delta_status = status ^ old_status;
679 if (delta_status) {
680 if (delta_status & ICOM_RI)
681 icom_port->uart_port.icount.rng++;
682 if (delta_status & ICOM_DSR)
683 icom_port->uart_port.icount.dsr++;
684 if (delta_status & ICOM_DCD)
685 uart_handle_dcd_change(&icom_port->uart_port,
686 delta_status & ICOM_DCD);
687 if (delta_status & ICOM_CTS)
688 uart_handle_cts_change(&icom_port->uart_port,
689 delta_status & ICOM_CTS);
690
691 wake_up_interruptible(&icom_port->uart_port.info->
692 delta_msr_wait);
693 old_status = status;
694 }
695 spin_unlock(&icom_port->uart_port.lock);
696}
697
698static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port)
699{
700 unsigned short int count;
701 int i;
702
703 if (port_int_reg & (INT_XMIT_COMPLETED)) {
704 trace(icom_port, "XMIT_COMPLETE", 0);
705
706 /* clear buffer in use bit */
707 icom_port->statStg->xmit[0].flags &=
708 cpu_to_le16(~SA_FLAGS_READY_TO_XMIT);
709
710 count = (unsigned short int)
711 cpu_to_le16(icom_port->statStg->xmit[0].leLength);
712 icom_port->uart_port.icount.tx += count;
713
714 for (i=0; i<count &&
715 !uart_circ_empty(&icom_port->uart_port.info->xmit); i++) {
716
717 icom_port->uart_port.info->xmit.tail++;
718 icom_port->uart_port.info->xmit.tail &=
719 (UART_XMIT_SIZE - 1);
720 }
721
722 if (!icom_write(&icom_port->uart_port))
723 /* activate write queue */
724 uart_write_wakeup(&icom_port->uart_port);
725 } else
726 trace(icom_port, "XMIT_DISABLED", 0);
727}
728
729static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
730{
731 short int count, rcv_buff;
732 struct tty_struct *tty = icom_port->uart_port.info->tty;
733 unsigned short int status;
734 struct uart_icount *icount;
735 unsigned long offset;
Alan Cox33f0f882006-01-09 20:54:13 -0800736 unsigned char flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
738 trace(icom_port, "RCV_COMPLETE", 0);
739 rcv_buff = icom_port->next_rcv;
740
741 status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
742 while (status & SA_FL_RCV_DONE) {
Alan Cox33f0f882006-01-09 20:54:13 -0800743 int first = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744
745 trace(icom_port, "FID_STATUS", status);
746 count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength);
747
Alan Cox33f0f882006-01-09 20:54:13 -0800748 count = tty_buffer_request_room(tty, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 trace(icom_port, "RCV_COUNT", count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750
751 trace(icom_port, "REAL_COUNT", count);
752
753 offset =
754 cpu_to_le32(icom_port->statStg->rcv[rcv_buff].leBuffer) -
755 icom_port->recv_buf_pci;
756
Alan Cox33f0f882006-01-09 20:54:13 -0800757 /* Block copy all but the last byte as this may have status */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 if (count > 0) {
Alan Cox33f0f882006-01-09 20:54:13 -0800759 first = icom_port->recv_buf[offset];
760 tty_insert_flip_string(tty, icom_port->recv_buf + offset, count - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 }
762
763 icount = &icom_port->uart_port.icount;
764 icount->rx += count;
765
766 /* Break detect logic */
767 if ((status & SA_FLAGS_FRAME_ERROR)
Alan Cox33f0f882006-01-09 20:54:13 -0800768 && first == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 status &= ~SA_FLAGS_FRAME_ERROR;
770 status |= SA_FLAGS_BREAK_DET;
771 trace(icom_port, "BREAK_DET", 0);
772 }
773
Alan Cox33f0f882006-01-09 20:54:13 -0800774 flag = TTY_NORMAL;
775
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 if (status &
777 (SA_FLAGS_BREAK_DET | SA_FLAGS_PARITY_ERROR |
778 SA_FLAGS_FRAME_ERROR | SA_FLAGS_OVERRUN)) {
779
780 if (status & SA_FLAGS_BREAK_DET)
781 icount->brk++;
782 if (status & SA_FLAGS_PARITY_ERROR)
783 icount->parity++;
784 if (status & SA_FLAGS_FRAME_ERROR)
785 icount->frame++;
786 if (status & SA_FLAGS_OVERRUN)
787 icount->overrun++;
788
789 /*
790 * Now check to see if character should be
791 * ignored, and mask off conditions which
792 * should be ignored.
793 */
794 if (status & icom_port->ignore_status_mask) {
795 trace(icom_port, "IGNORE_CHAR", 0);
796 goto ignore_char;
797 }
798
799 status &= icom_port->read_status_mask;
800
801 if (status & SA_FLAGS_BREAK_DET) {
Alan Cox33f0f882006-01-09 20:54:13 -0800802 flag = TTY_BREAK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 } else if (status & SA_FLAGS_PARITY_ERROR) {
804 trace(icom_port, "PARITY_ERROR", 0);
Alan Cox33f0f882006-01-09 20:54:13 -0800805 flag = TTY_PARITY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 } else if (status & SA_FLAGS_FRAME_ERROR)
Alan Cox33f0f882006-01-09 20:54:13 -0800807 flag = TTY_FRAME;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 }
810
Alan Cox33f0f882006-01-09 20:54:13 -0800811 tty_insert_flip_char(tty, *(icom_port->recv_buf + offset + count - 1), flag);
812
813 if (status & SA_FLAGS_OVERRUN)
814 /*
815 * Overrun is special, since it's
816 * reported immediately, and doesn't
817 * affect the current character
818 */
819 tty_insert_flip_char(tty, 0, TTY_OVERRUN);
820ignore_char:
821 icom_port->statStg->rcv[rcv_buff].flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 icom_port->statStg->rcv[rcv_buff].leLength = 0;
823 icom_port->statStg->rcv[rcv_buff].WorkingLength =
824 (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
825
826 rcv_buff++;
827 if (rcv_buff == NUM_RBUFFS)
828 rcv_buff = 0;
829
830 status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
831 }
832 icom_port->next_rcv = rcv_buff;
833 tty_flip_buffer_push(tty);
834}
835
836static void process_interrupt(u16 port_int_reg,
837 struct icom_port *icom_port)
838{
839
840 spin_lock(&icom_port->uart_port.lock);
841 trace(icom_port, "INTERRUPT", port_int_reg);
842
843 if (port_int_reg & (INT_XMIT_COMPLETED | INT_XMIT_DISABLED))
844 xmit_interrupt(port_int_reg, icom_port);
845
846 if (port_int_reg & INT_RCV_COMPLETED)
847 recv_interrupt(port_int_reg, icom_port);
848
849 spin_unlock(&icom_port->uart_port.lock);
850}
851
David Howells7d12e782006-10-05 14:55:46 +0100852static irqreturn_t icom_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853{
854 void __iomem * int_reg;
855 u32 adapter_interrupts;
856 u16 port_int_reg;
857 struct icom_adapter *icom_adapter;
858 struct icom_port *icom_port;
859
860 /* find icom_port for this interrupt */
861 icom_adapter = (struct icom_adapter *) dev_id;
862
863 if ((icom_adapter->version | ADAPTER_V2) == ADAPTER_V2) {
864 int_reg = icom_adapter->base_addr + 0x8024;
865
866 adapter_interrupts = readl(int_reg);
867
868 if (adapter_interrupts & 0x00003FFF) {
869 /* port 2 interrupt, NOTE: for all ADAPTER_V2, port 2 will be active */
870 icom_port = &icom_adapter->port_info[2];
871 port_int_reg = (u16) adapter_interrupts;
872 process_interrupt(port_int_reg, icom_port);
873 check_modem_status(icom_port);
874 }
875 if (adapter_interrupts & 0x3FFF0000) {
876 /* port 3 interrupt */
877 icom_port = &icom_adapter->port_info[3];
878 if (icom_port->status == ICOM_PORT_ACTIVE) {
879 port_int_reg =
880 (u16) (adapter_interrupts >> 16);
881 process_interrupt(port_int_reg, icom_port);
882 check_modem_status(icom_port);
883 }
884 }
885
886 /* Clear out any pending interrupts */
887 writel(adapter_interrupts, int_reg);
888
889 int_reg = icom_adapter->base_addr + 0x8004;
890 } else {
891 int_reg = icom_adapter->base_addr + 0x4004;
892 }
893
894 adapter_interrupts = readl(int_reg);
895
896 if (adapter_interrupts & 0x00003FFF) {
897 /* port 0 interrupt, NOTE: for all adapters, port 0 will be active */
898 icom_port = &icom_adapter->port_info[0];
899 port_int_reg = (u16) adapter_interrupts;
900 process_interrupt(port_int_reg, icom_port);
901 check_modem_status(icom_port);
902 }
903 if (adapter_interrupts & 0x3FFF0000) {
904 /* port 1 interrupt */
905 icom_port = &icom_adapter->port_info[1];
906 if (icom_port->status == ICOM_PORT_ACTIVE) {
907 port_int_reg = (u16) (adapter_interrupts >> 16);
908 process_interrupt(port_int_reg, icom_port);
909 check_modem_status(icom_port);
910 }
911 }
912
913 /* Clear out any pending interrupts */
914 writel(adapter_interrupts, int_reg);
915
916 /* flush the write */
917 adapter_interrupts = readl(int_reg);
918
919 return IRQ_HANDLED;
920}
921
922/*
923 * ------------------------------------------------------------------
924 * Begin serial-core API
925 * ------------------------------------------------------------------
926 */
927static unsigned int icom_tx_empty(struct uart_port *port)
928{
929 int ret;
930 unsigned long flags;
931
932 spin_lock_irqsave(&port->lock, flags);
933 if (cpu_to_le16(ICOM_PORT->statStg->xmit[0].flags) &
934 SA_FLAGS_READY_TO_XMIT)
935 ret = TIOCSER_TEMT;
936 else
937 ret = 0;
938
939 spin_unlock_irqrestore(&port->lock, flags);
940 return ret;
941}
942
943static void icom_set_mctrl(struct uart_port *port, unsigned int mctrl)
944{
945 unsigned char local_osr;
946
947 trace(ICOM_PORT, "SET_MODEM", 0);
948 local_osr = readb(&ICOM_PORT->dram->osr);
949
950 if (mctrl & TIOCM_RTS) {
951 trace(ICOM_PORT, "RAISE_RTS", 0);
952 local_osr |= ICOM_RTS;
953 } else {
954 trace(ICOM_PORT, "LOWER_RTS", 0);
955 local_osr &= ~ICOM_RTS;
956 }
957
958 if (mctrl & TIOCM_DTR) {
959 trace(ICOM_PORT, "RAISE_DTR", 0);
960 local_osr |= ICOM_DTR;
961 } else {
962 trace(ICOM_PORT, "LOWER_DTR", 0);
963 local_osr &= ~ICOM_DTR;
964 }
965
966 writeb(local_osr, &ICOM_PORT->dram->osr);
967}
968
969static unsigned int icom_get_mctrl(struct uart_port *port)
970{
971 unsigned char status;
972 unsigned int result;
973
974 trace(ICOM_PORT, "GET_MODEM", 0);
975
976 status = readb(&ICOM_PORT->dram->isr);
977
978 result = ((status & ICOM_DCD) ? TIOCM_CAR : 0)
979 | ((status & ICOM_RI) ? TIOCM_RNG : 0)
980 | ((status & ICOM_DSR) ? TIOCM_DSR : 0)
981 | ((status & ICOM_CTS) ? TIOCM_CTS : 0);
982 return result;
983}
984
Russell Kingb129a8c2005-08-31 10:12:14 +0100985static void icom_stop_tx(struct uart_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986{
987 unsigned char cmdReg;
988
Russell Kingb129a8c2005-08-31 10:12:14 +0100989 trace(ICOM_PORT, "STOP", 0);
990 cmdReg = readb(&ICOM_PORT->dram->CmdReg);
991 writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992}
993
Russell Kingb129a8c2005-08-31 10:12:14 +0100994static void icom_start_tx(struct uart_port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995{
996 unsigned char cmdReg;
997
998 trace(ICOM_PORT, "START", 0);
999 cmdReg = readb(&ICOM_PORT->dram->CmdReg);
1000 if ((cmdReg & CMD_HOLD_XMIT) == CMD_HOLD_XMIT)
1001 writeb(cmdReg & ~CMD_HOLD_XMIT,
1002 &ICOM_PORT->dram->CmdReg);
1003
1004 icom_write(port);
1005}
1006
1007static void icom_send_xchar(struct uart_port *port, char ch)
1008{
1009 unsigned char xdata;
1010 int index;
1011 unsigned long flags;
1012
1013 trace(ICOM_PORT, "SEND_XCHAR", ch);
1014
1015 /* wait .1 sec to send char */
1016 for (index = 0; index < 10; index++) {
1017 spin_lock_irqsave(&port->lock, flags);
1018 xdata = readb(&ICOM_PORT->dram->xchar);
1019 if (xdata == 0x00) {
1020 trace(ICOM_PORT, "QUICK_WRITE", 0);
1021 writeb(ch, &ICOM_PORT->dram->xchar);
1022
1023 /* flush write operation */
1024 xdata = readb(&ICOM_PORT->dram->xchar);
1025 spin_unlock_irqrestore(&port->lock, flags);
1026 break;
1027 }
1028 spin_unlock_irqrestore(&port->lock, flags);
1029 msleep(10);
1030 }
1031}
1032
1033static void icom_stop_rx(struct uart_port *port)
1034{
1035 unsigned char cmdReg;
1036
1037 cmdReg = readb(&ICOM_PORT->dram->CmdReg);
1038 writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
1039}
1040
1041static void icom_enable_ms(struct uart_port *port)
1042{
1043 /* no-op */
1044}
1045
1046static void icom_break(struct uart_port *port, int break_state)
1047{
1048 unsigned char cmdReg;
1049 unsigned long flags;
1050
1051 spin_lock_irqsave(&port->lock, flags);
1052 trace(ICOM_PORT, "BREAK", 0);
1053 cmdReg = readb(&ICOM_PORT->dram->CmdReg);
1054 if (break_state == -1) {
1055 writeb(cmdReg | CMD_SND_BREAK, &ICOM_PORT->dram->CmdReg);
1056 } else {
1057 writeb(cmdReg & ~CMD_SND_BREAK, &ICOM_PORT->dram->CmdReg);
1058 }
1059 spin_unlock_irqrestore(&port->lock, flags);
1060}
1061
1062static int icom_open(struct uart_port *port)
1063{
1064 int retval;
1065
1066 kobject_get(&ICOM_PORT->adapter->kobj);
1067 retval = startup(ICOM_PORT);
1068
1069 if (retval) {
1070 kobject_put(&ICOM_PORT->adapter->kobj);
1071 trace(ICOM_PORT, "STARTUP_ERROR", 0);
1072 return retval;
1073 }
1074
1075 return 0;
1076}
1077
1078static void icom_close(struct uart_port *port)
1079{
1080 unsigned char cmdReg;
1081
1082 trace(ICOM_PORT, "CLOSE", 0);
1083
1084 /* stop receiver */
1085 cmdReg = readb(&ICOM_PORT->dram->CmdReg);
1086 writeb(cmdReg & (unsigned char) ~CMD_RCV_ENABLE,
1087 &ICOM_PORT->dram->CmdReg);
1088
1089 shutdown(ICOM_PORT);
1090
1091 kobject_put(&ICOM_PORT->adapter->kobj);
1092}
1093
1094static void icom_set_termios(struct uart_port *port,
Alan Cox606d0992006-12-08 02:38:45 -08001095 struct ktermios *termios,
1096 struct ktermios *old_termios)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097{
1098 int baud;
1099 unsigned cflag, iflag;
1100 int bits;
1101 char new_config2;
1102 char new_config3 = 0;
1103 char tmp_byte;
1104 int index;
1105 int rcv_buff, xmit_buff;
1106 unsigned long offset;
1107 unsigned long flags;
1108
1109 spin_lock_irqsave(&port->lock, flags);
1110 trace(ICOM_PORT, "CHANGE_SPEED", 0);
1111
1112 cflag = termios->c_cflag;
1113 iflag = termios->c_iflag;
1114
1115 new_config2 = ICOM_ACFG_DRIVE1;
1116
1117 /* byte size and parity */
1118 switch (cflag & CSIZE) {
1119 case CS5: /* 5 bits/char */
1120 new_config2 |= ICOM_ACFG_5BPC;
1121 bits = 7;
1122 break;
1123 case CS6: /* 6 bits/char */
1124 new_config2 |= ICOM_ACFG_6BPC;
1125 bits = 8;
1126 break;
1127 case CS7: /* 7 bits/char */
1128 new_config2 |= ICOM_ACFG_7BPC;
1129 bits = 9;
1130 break;
1131 case CS8: /* 8 bits/char */
1132 new_config2 |= ICOM_ACFG_8BPC;
1133 bits = 10;
1134 break;
1135 default:
1136 bits = 10;
1137 break;
1138 }
1139 if (cflag & CSTOPB) {
1140 /* 2 stop bits */
1141 new_config2 |= ICOM_ACFG_2STOP_BIT;
1142 bits++;
1143 }
1144 if (cflag & PARENB) {
1145 /* parity bit enabled */
1146 new_config2 |= ICOM_ACFG_PARITY_ENAB;
1147 trace(ICOM_PORT, "PARENB", 0);
1148 bits++;
1149 }
1150 if (cflag & PARODD) {
1151 /* odd parity */
1152 new_config2 |= ICOM_ACFG_PARITY_ODD;
1153 trace(ICOM_PORT, "PARODD", 0);
1154 }
1155
1156 /* Determine divisor based on baud rate */
1157 baud = uart_get_baud_rate(port, termios, old_termios,
1158 icom_acfg_baud[0],
1159 icom_acfg_baud[BAUD_TABLE_LIMIT]);
1160 if (!baud)
1161 baud = 9600; /* B0 transition handled in rs_set_termios */
1162
1163 for (index = 0; index < BAUD_TABLE_LIMIT; index++) {
1164 if (icom_acfg_baud[index] == baud) {
1165 new_config3 = index;
1166 break;
1167 }
1168 }
1169
1170 uart_update_timeout(port, cflag, baud);
1171
1172 /* CTS flow control flag and modem status interrupts */
1173 tmp_byte = readb(&(ICOM_PORT->dram->HDLCConfigReg));
1174 if (cflag & CRTSCTS)
1175 tmp_byte |= HDLC_HDW_FLOW;
1176 else
1177 tmp_byte &= ~HDLC_HDW_FLOW;
1178 writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
1179
1180 /*
1181 * Set up parity check flag
1182 */
1183 ICOM_PORT->read_status_mask = SA_FLAGS_OVERRUN | SA_FL_RCV_DONE;
1184 if (iflag & INPCK)
1185 ICOM_PORT->read_status_mask |=
1186 SA_FLAGS_FRAME_ERROR | SA_FLAGS_PARITY_ERROR;
1187
1188 if ((iflag & BRKINT) || (iflag & PARMRK))
1189 ICOM_PORT->read_status_mask |= SA_FLAGS_BREAK_DET;
1190
1191 /*
1192 * Characters to ignore
1193 */
1194 ICOM_PORT->ignore_status_mask = 0;
1195 if (iflag & IGNPAR)
1196 ICOM_PORT->ignore_status_mask |=
1197 SA_FLAGS_PARITY_ERROR | SA_FLAGS_FRAME_ERROR;
1198 if (iflag & IGNBRK) {
1199 ICOM_PORT->ignore_status_mask |= SA_FLAGS_BREAK_DET;
1200 /*
1201 * If we're ignore parity and break indicators, ignore
1202 * overruns too. (For real raw support).
1203 */
1204 if (iflag & IGNPAR)
1205 ICOM_PORT->ignore_status_mask |= SA_FLAGS_OVERRUN;
1206 }
1207
1208 /*
1209 * !!! ignore all characters if CREAD is not set
1210 */
1211 if ((cflag & CREAD) == 0)
1212 ICOM_PORT->ignore_status_mask |= SA_FL_RCV_DONE;
1213
1214 /* Turn off Receiver to prepare for reset */
1215 writeb(CMD_RCV_DISABLE, &ICOM_PORT->dram->CmdReg);
1216
1217 for (index = 0; index < 10; index++) {
1218 if (readb(&ICOM_PORT->dram->PrevCmdReg) == 0x00) {
1219 break;
1220 }
1221 }
1222
1223 /* clear all current buffers of data */
1224 for (rcv_buff = 0; rcv_buff < NUM_RBUFFS; rcv_buff++) {
1225 ICOM_PORT->statStg->rcv[rcv_buff].flags = 0;
1226 ICOM_PORT->statStg->rcv[rcv_buff].leLength = 0;
1227 ICOM_PORT->statStg->rcv[rcv_buff].WorkingLength =
1228 (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
1229 }
1230
1231 for (xmit_buff = 0; xmit_buff < NUM_XBUFFS; xmit_buff++) {
1232 ICOM_PORT->statStg->xmit[xmit_buff].flags = 0;
1233 }
1234
1235 /* activate changes and start xmit and receiver here */
1236 /* Enable the receiver */
1237 writeb(new_config3, &(ICOM_PORT->dram->async_config3));
1238 writeb(new_config2, &(ICOM_PORT->dram->async_config2));
1239 tmp_byte = readb(&(ICOM_PORT->dram->HDLCConfigReg));
1240 tmp_byte |= HDLC_PPP_PURE_ASYNC | HDLC_FF_FILL;
1241 writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
1242 writeb(0x04, &(ICOM_PORT->dram->FlagFillIdleTimer)); /* 0.5 seconds */
1243 writeb(0xFF, &(ICOM_PORT->dram->ier)); /* enable modem signal interrupts */
1244
1245 /* reset processor */
1246 writeb(CMD_RESTART, &ICOM_PORT->dram->CmdReg);
1247
1248 for (index = 0; index < 10; index++) {
1249 if (readb(&ICOM_PORT->dram->CmdReg) == 0x00) {
1250 break;
1251 }
1252 }
1253
1254 /* Enable Transmitter and Reciever */
1255 offset =
1256 (unsigned long) &ICOM_PORT->statStg->rcv[0] -
1257 (unsigned long) ICOM_PORT->statStg;
1258 writel(ICOM_PORT->statStg_pci + offset,
1259 &ICOM_PORT->dram->RcvStatusAddr);
1260 ICOM_PORT->next_rcv = 0;
1261 ICOM_PORT->put_length = 0;
1262 *ICOM_PORT->xmitRestart = 0;
1263 writel(ICOM_PORT->xmitRestart_pci,
1264 &ICOM_PORT->dram->XmitStatusAddr);
1265 trace(ICOM_PORT, "XR_ENAB", 0);
1266 writeb(CMD_XMIT_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
1267
1268 spin_unlock_irqrestore(&port->lock, flags);
1269}
1270
1271static const char *icom_type(struct uart_port *port)
1272{
1273 return "icom";
1274}
1275
1276static void icom_release_port(struct uart_port *port)
1277{
1278}
1279
1280static int icom_request_port(struct uart_port *port)
1281{
1282 return 0;
1283}
1284
1285static void icom_config_port(struct uart_port *port, int flags)
1286{
1287 port->type = PORT_ICOM;
1288}
1289
1290static struct uart_ops icom_ops = {
1291 .tx_empty = icom_tx_empty,
1292 .set_mctrl = icom_set_mctrl,
1293 .get_mctrl = icom_get_mctrl,
1294 .stop_tx = icom_stop_tx,
1295 .start_tx = icom_start_tx,
1296 .send_xchar = icom_send_xchar,
1297 .stop_rx = icom_stop_rx,
1298 .enable_ms = icom_enable_ms,
1299 .break_ctl = icom_break,
1300 .startup = icom_open,
1301 .shutdown = icom_close,
1302 .set_termios = icom_set_termios,
1303 .type = icom_type,
1304 .release_port = icom_release_port,
1305 .request_port = icom_request_port,
1306 .config_port = icom_config_port,
1307};
1308
1309#define ICOM_CONSOLE NULL
1310
1311static struct uart_driver icom_uart_driver = {
1312 .owner = THIS_MODULE,
1313 .driver_name = ICOM_DRIVER_NAME,
1314 .dev_name = "ttyA",
1315 .major = ICOM_MAJOR,
1316 .minor = ICOM_MINOR_START,
1317 .nr = NR_PORTS,
1318 .cons = ICOM_CONSOLE,
1319};
1320
1321static int __devinit icom_init_ports(struct icom_adapter *icom_adapter)
1322{
1323 u32 subsystem_id = icom_adapter->subsystem_id;
1324 int retval = 0;
1325 int i;
1326 struct icom_port *icom_port;
1327
1328 if (icom_adapter->version == ADAPTER_V1) {
1329 icom_adapter->numb_ports = 2;
1330
1331 for (i = 0; i < 2; i++) {
1332 icom_port = &icom_adapter->port_info[i];
1333 icom_port->port = i;
1334 icom_port->status = ICOM_PORT_ACTIVE;
1335 icom_port->imbed_modem = ICOM_UNKNOWN;
1336 }
1337 } else {
1338 if (subsystem_id == PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL) {
1339 icom_adapter->numb_ports = 4;
1340
1341 for (i = 0; i < 4; i++) {
1342 icom_port = &icom_adapter->port_info[i];
1343
1344 icom_port->port = i;
1345 icom_port->status = ICOM_PORT_ACTIVE;
1346 icom_port->imbed_modem = ICOM_IMBED_MODEM;
1347 }
1348 } else {
1349 icom_adapter->numb_ports = 4;
1350
1351 icom_adapter->port_info[0].port = 0;
1352 icom_adapter->port_info[0].status = ICOM_PORT_ACTIVE;
1353
1354 if (subsystem_id ==
1355 PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM) {
1356 icom_adapter->port_info[0].imbed_modem = ICOM_IMBED_MODEM;
1357 } else {
1358 icom_adapter->port_info[0].imbed_modem = ICOM_RVX;
1359 }
1360
1361 icom_adapter->port_info[1].status = ICOM_PORT_OFF;
1362
1363 icom_adapter->port_info[2].port = 2;
1364 icom_adapter->port_info[2].status = ICOM_PORT_ACTIVE;
1365 icom_adapter->port_info[2].imbed_modem = ICOM_RVX;
1366 icom_adapter->port_info[3].status = ICOM_PORT_OFF;
1367 }
1368 }
1369
1370 return retval;
1371}
1372
1373static void icom_port_active(struct icom_port *icom_port, struct icom_adapter *icom_adapter, int port_num)
1374{
1375 if (icom_adapter->version == ADAPTER_V1) {
1376 icom_port->global_reg = icom_adapter->base_addr + 0x4000;
1377 icom_port->int_reg = icom_adapter->base_addr +
1378 0x4004 + 2 - 2 * port_num;
1379 } else {
1380 icom_port->global_reg = icom_adapter->base_addr + 0x8000;
1381 if (icom_port->port < 2)
1382 icom_port->int_reg = icom_adapter->base_addr +
1383 0x8004 + 2 - 2 * icom_port->port;
1384 else
1385 icom_port->int_reg = icom_adapter->base_addr +
1386 0x8024 + 2 - 2 * (icom_port->port - 2);
1387 }
1388}
Jiri Slaby98f85d32007-04-23 14:41:20 -07001389static int __devinit icom_load_ports(struct icom_adapter *icom_adapter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390{
1391 struct icom_port *icom_port;
1392 int port_num;
1393 int retval;
1394
1395 for (port_num = 0; port_num < icom_adapter->numb_ports; port_num++) {
1396
1397 icom_port = &icom_adapter->port_info[port_num];
1398
1399 if (icom_port->status == ICOM_PORT_ACTIVE) {
1400 icom_port_active(icom_port, icom_adapter, port_num);
1401 icom_port->dram = icom_adapter->base_addr +
1402 0x2000 * icom_port->port;
1403
1404 icom_port->adapter = icom_adapter;
1405
1406 /* get port memory */
1407 if ((retval = get_port_memory(icom_port)) != 0) {
1408 dev_err(&icom_port->adapter->pci_dev->dev,
1409 "Memory allocation for port FAILED\n");
1410 }
1411 }
1412 }
1413 return 0;
1414}
1415
1416static int __devinit icom_alloc_adapter(struct icom_adapter
1417 **icom_adapter_ref)
1418{
1419 int adapter_count = 0;
1420 struct icom_adapter *icom_adapter;
1421 struct icom_adapter *cur_adapter_entry;
1422 struct list_head *tmp;
1423
1424 icom_adapter = (struct icom_adapter *)
Burman Yan8f31bb32007-02-14 00:33:07 -08001425 kzalloc(sizeof(struct icom_adapter), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426
1427 if (!icom_adapter) {
1428 return -ENOMEM;
1429 }
1430
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 list_for_each(tmp, &icom_adapter_head) {
1432 cur_adapter_entry =
1433 list_entry(tmp, struct icom_adapter,
1434 icom_adapter_entry);
1435 if (cur_adapter_entry->index != adapter_count) {
1436 break;
1437 }
1438 adapter_count++;
1439 }
1440
1441 icom_adapter->index = adapter_count;
1442 list_add_tail(&icom_adapter->icom_adapter_entry, tmp);
1443
1444 *icom_adapter_ref = icom_adapter;
1445 return 0;
1446}
1447
1448static void icom_free_adapter(struct icom_adapter *icom_adapter)
1449{
1450 list_del(&icom_adapter->icom_adapter_entry);
1451 kfree(icom_adapter);
1452}
1453
1454static void icom_remove_adapter(struct icom_adapter *icom_adapter)
1455{
1456 struct icom_port *icom_port;
1457 int index;
1458
1459 for (index = 0; index < icom_adapter->numb_ports; index++) {
1460 icom_port = &icom_adapter->port_info[index];
1461
1462 if (icom_port->status == ICOM_PORT_ACTIVE) {
1463 dev_info(&icom_adapter->pci_dev->dev,
1464 "Device removed\n");
1465
1466 uart_remove_one_port(&icom_uart_driver,
1467 &icom_port->uart_port);
1468
1469 /* be sure that DTR and RTS are dropped */
1470 writeb(0x00, &icom_port->dram->osr);
1471
1472 /* Wait 0.1 Sec for simple Init to complete */
1473 msleep(100);
1474
1475 /* Stop proccessor */
1476 stop_processor(icom_port);
1477
1478 free_port_memory(icom_port);
1479 }
1480 }
1481
Olaf Hering179fb0c2007-04-23 14:41:15 -07001482 free_irq(icom_adapter->pci_dev->irq, (void *) icom_adapter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 iounmap(icom_adapter->base_addr);
1484 icom_free_adapter(icom_adapter);
1485 pci_release_regions(icom_adapter->pci_dev);
1486}
1487
1488static void icom_kobj_release(struct kobject *kobj)
1489{
1490 struct icom_adapter *icom_adapter;
1491
1492 icom_adapter = to_icom_adapter(kobj);
1493 icom_remove_adapter(icom_adapter);
1494}
1495
1496static struct kobj_type icom_kobj_type = {
1497 .release = icom_kobj_release,
1498};
1499
1500static int __devinit icom_probe(struct pci_dev *dev,
1501 const struct pci_device_id *ent)
1502{
1503 int index;
1504 unsigned int command_reg;
1505 int retval;
1506 struct icom_adapter *icom_adapter;
1507 struct icom_port *icom_port;
1508
1509 retval = pci_enable_device(dev);
1510 if (retval) {
1511 dev_err(&dev->dev, "Device enable FAILED\n");
1512 return retval;
1513 }
1514
1515 if ( (retval = pci_request_regions(dev, "icom"))) {
Thomas Hisch87c18aa2006-12-12 19:20:35 +01001516 dev_err(&dev->dev, "pci_request_regions FAILED\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 pci_disable_device(dev);
1518 return retval;
1519 }
1520
1521 pci_set_master(dev);
1522
1523 if ( (retval = pci_read_config_dword(dev, PCI_COMMAND, &command_reg))) {
1524 dev_err(&dev->dev, "PCI Config read FAILED\n");
1525 return retval;
1526 }
1527
1528 pci_write_config_dword(dev, PCI_COMMAND,
1529 command_reg | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
1530 | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
1531
1532 if (ent->driver_data == ADAPTER_V1) {
1533 pci_write_config_dword(dev, 0x44, 0x8300830A);
1534 } else {
1535 pci_write_config_dword(dev, 0x44, 0x42004200);
1536 pci_write_config_dword(dev, 0x48, 0x42004200);
1537 }
1538
1539
1540 retval = icom_alloc_adapter(&icom_adapter);
1541 if (retval) {
1542 dev_err(&dev->dev, "icom_alloc_adapter FAILED\n");
1543 retval = -EIO;
1544 goto probe_exit0;
1545 }
1546
1547 icom_adapter->base_addr_pci = pci_resource_start(dev, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 icom_adapter->pci_dev = dev;
1549 icom_adapter->version = ent->driver_data;
1550 icom_adapter->subsystem_id = ent->subdevice;
1551
1552
1553 retval = icom_init_ports(icom_adapter);
1554 if (retval) {
1555 dev_err(&dev->dev, "Port configuration failed\n");
1556 goto probe_exit1;
1557 }
1558
1559 icom_adapter->base_addr = ioremap(icom_adapter->base_addr_pci,
1560 pci_resource_len(dev, 0));
1561
1562 if (!icom_adapter->base_addr)
1563 goto probe_exit1;
1564
1565 /* save off irq and request irq line */
1566 if ( (retval = request_irq(dev->irq, icom_interrupt,
Thomas Gleixner40663cc2006-07-01 19:29:43 -07001567 IRQF_DISABLED | IRQF_SHARED, ICOM_DRIVER_NAME,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 (void *) icom_adapter))) {
1569 goto probe_exit2;
1570 }
1571
1572 retval = icom_load_ports(icom_adapter);
1573
1574 for (index = 0; index < icom_adapter->numb_ports; index++) {
1575 icom_port = &icom_adapter->port_info[index];
1576
1577 if (icom_port->status == ICOM_PORT_ACTIVE) {
Olaf Hering179fb0c2007-04-23 14:41:15 -07001578 icom_port->uart_port.irq = icom_port->adapter->pci_dev->irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579 icom_port->uart_port.type = PORT_ICOM;
1580 icom_port->uart_port.iotype = UPIO_MEM;
1581 icom_port->uart_port.membase =
1582 (char *) icom_adapter->base_addr_pci;
1583 icom_port->uart_port.fifosize = 16;
1584 icom_port->uart_port.ops = &icom_ops;
1585 icom_port->uart_port.line =
1586 icom_port->port + icom_adapter->index * 4;
1587 if (uart_add_one_port (&icom_uart_driver, &icom_port->uart_port)) {
1588 icom_port->status = ICOM_PORT_OFF;
1589 dev_err(&dev->dev, "Device add failed\n");
1590 } else
1591 dev_info(&dev->dev, "Device added\n");
1592 }
1593 }
1594
1595 kobject_init(&icom_adapter->kobj);
1596 icom_adapter->kobj.ktype = &icom_kobj_type;
1597 return 0;
1598
1599probe_exit2:
1600 iounmap(icom_adapter->base_addr);
1601probe_exit1:
1602 icom_free_adapter(icom_adapter);
1603
1604probe_exit0:
1605 pci_release_regions(dev);
1606 pci_disable_device(dev);
1607
1608 return retval;
1609
1610
1611}
1612
1613static void __devexit icom_remove(struct pci_dev *dev)
1614{
1615 struct icom_adapter *icom_adapter;
1616 struct list_head *tmp;
1617
1618 list_for_each(tmp, &icom_adapter_head) {
1619 icom_adapter = list_entry(tmp, struct icom_adapter,
1620 icom_adapter_entry);
1621 if (icom_adapter->pci_dev == dev) {
1622 kobject_put(&icom_adapter->kobj);
1623 return;
1624 }
1625 }
1626
1627 dev_err(&dev->dev, "Unable to find device to remove\n");
1628}
1629
1630static struct pci_driver icom_pci_driver = {
1631 .name = ICOM_DRIVER_NAME,
1632 .id_table = icom_pci_table,
1633 .probe = icom_probe,
1634 .remove = __devexit_p(icom_remove),
1635};
1636
1637static int __init icom_init(void)
1638{
1639 int ret;
1640
1641 spin_lock_init(&icom_lock);
1642
1643 ret = uart_register_driver(&icom_uart_driver);
1644 if (ret)
1645 return ret;
1646
1647 ret = pci_register_driver(&icom_pci_driver);
1648
1649 if (ret < 0)
1650 uart_unregister_driver(&icom_uart_driver);
1651
1652 return ret;
1653}
1654
1655static void __exit icom_exit(void)
1656{
1657 pci_unregister_driver(&icom_pci_driver);
1658 uart_unregister_driver(&icom_uart_driver);
1659}
1660
1661module_init(icom_init);
1662module_exit(icom_exit);
1663
1664#ifdef ICOM_TRACE
1665static inline void trace(struct icom_port *icom_port, char *trace_pt,
1666 unsigned long trace_data)
1667{
1668 dev_info(&icom_port->adapter->pci_dev->dev, ":%d:%s - %lx\n",
1669 icom_port->port, trace_pt, trace_data);
1670}
1671#endif
1672
1673MODULE_AUTHOR("Michael Anderson <mjanders@us.ibm.com>");
1674MODULE_DESCRIPTION("IBM iSeries Serial IOA driver");
1675MODULE_SUPPORTED_DEVICE
1676 ("IBM iSeries 2745, 2771, 2772, 2742, 2793 and 2805 Communications adapters");
1677MODULE_LICENSE("GPL");
1678