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