Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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