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