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