linux/drivers/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                count = tty_buffer_request_room(tty, count);
 755                trace(icom_port, "RCV_COUNT", count);
 756
 757                trace(icom_port, "REAL_COUNT", count);
 758
 759                offset =
 760                        cpu_to_le32(icom_port->statStg->rcv[rcv_buff].leBuffer) -
 761                        icom_port->recv_buf_pci;
 762
 763                /* Block copy all but the last byte as this may have status */
 764                if (count > 0) {
 765                        first = icom_port->recv_buf[offset];
 766                        tty_insert_flip_string(tty, icom_port->recv_buf + offset, count - 1);
 767                }
 768
 769                icount = &icom_port->uart_port.icount;
 770                icount->rx += count;
 771
 772                /* Break detect logic */
 773                if ((status & SA_FLAGS_FRAME_ERROR)
 774                    && first == 0) {
 775                        status &= ~SA_FLAGS_FRAME_ERROR;
 776                        status |= SA_FLAGS_BREAK_DET;
 777                        trace(icom_port, "BREAK_DET", 0);
 778                }
 779
 780                flag = TTY_NORMAL;
 781
 782                if (status &
 783                    (SA_FLAGS_BREAK_DET | SA_FLAGS_PARITY_ERROR |
 784                     SA_FLAGS_FRAME_ERROR | SA_FLAGS_OVERRUN)) {
 785
 786                        if (status & SA_FLAGS_BREAK_DET)
 787                                icount->brk++;
 788                        if (status & SA_FLAGS_PARITY_ERROR)
 789                                icount->parity++;
 790                        if (status & SA_FLAGS_FRAME_ERROR)
 791                                icount->frame++;
 792                        if (status & SA_FLAGS_OVERRUN)
 793                                icount->overrun++;
 794
 795                        /*
 796                         * Now check to see if character should be
 797                         * ignored, and mask off conditions which
 798                         * should be ignored.
 799                         */
 800                        if (status & icom_port->ignore_status_mask) {
 801                                trace(icom_port, "IGNORE_CHAR", 0);
 802                                goto ignore_char;
 803                        }
 804
 805                        status &= icom_port->read_status_mask;
 806
 807                        if (status & SA_FLAGS_BREAK_DET) {
 808                                flag = TTY_BREAK;
 809                        } else if (status & SA_FLAGS_PARITY_ERROR) {
 810                                trace(icom_port, "PARITY_ERROR", 0);
 811                                flag = TTY_PARITY;
 812                        } else if (status & SA_FLAGS_FRAME_ERROR)
 813                                flag = TTY_FRAME;
 814
 815                }
 816
 817                tty_insert_flip_char(tty, *(icom_port->recv_buf + offset + count - 1), flag);
 818
 819                if (status & SA_FLAGS_OVERRUN)
 820                        /*
 821                         * Overrun is special, since it's
 822                         * reported immediately, and doesn't
 823                         * affect the current character
 824                         */
 825                        tty_insert_flip_char(tty, 0, TTY_OVERRUN);
 826ignore_char:
 827                icom_port->statStg->rcv[rcv_buff].flags = 0;
 828                icom_port->statStg->rcv[rcv_buff].leLength = 0;
 829                icom_port->statStg->rcv[rcv_buff].WorkingLength =
 830                        (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
 831
 832                rcv_buff++;
 833                if (rcv_buff == NUM_RBUFFS)
 834                        rcv_buff = 0;
 835
 836                status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
 837        }
 838        icom_port->next_rcv = rcv_buff;
 839        tty_flip_buffer_push(tty);
 840}
 841
 842static void process_interrupt(u16 port_int_reg,
 843                              struct icom_port *icom_port)
 844{
 845
 846        spin_lock(&icom_port->uart_port.lock);
 847        trace(icom_port, "INTERRUPT", port_int_reg);
 848
 849        if (port_int_reg & (INT_XMIT_COMPLETED | INT_XMIT_DISABLED))
 850                xmit_interrupt(port_int_reg, icom_port);
 851
 852        if (port_int_reg & INT_RCV_COMPLETED)
 853                recv_interrupt(port_int_reg, icom_port);
 854
 855        spin_unlock(&icom_port->uart_port.lock);
 856}
 857
 858static irqreturn_t icom_interrupt(int irq, void *dev_id)
 859{
 860        void __iomem * int_reg;
 861        u32 adapter_interrupts;
 862        u16 port_int_reg;
 863        struct icom_adapter *icom_adapter;
 864        struct icom_port *icom_port;
 865
 866        /* find icom_port for this interrupt */
 867        icom_adapter = (struct icom_adapter *) dev_id;
 868
 869        if (icom_adapter->version == ADAPTER_V2) {
 870                int_reg = icom_adapter->base_addr + 0x8024;
 871
 872                adapter_interrupts = readl(int_reg);
 873
 874                if (adapter_interrupts & 0x00003FFF) {
 875                        /* port 2 interrupt,  NOTE:  for all ADAPTER_V2, port 2 will be active */
 876                        icom_port = &icom_adapter->port_info[2];
 877                        port_int_reg = (u16) adapter_interrupts;
 878                        process_interrupt(port_int_reg, icom_port);
 879                        check_modem_status(icom_port);
 880                }
 881                if (adapter_interrupts & 0x3FFF0000) {
 882                        /* port 3 interrupt */
 883                        icom_port = &icom_adapter->port_info[3];
 884                        if (icom_port->status == ICOM_PORT_ACTIVE) {
 885                                port_int_reg =
 886                                    (u16) (adapter_interrupts >> 16);
 887                                process_interrupt(port_int_reg, icom_port);
 888                                check_modem_status(icom_port);
 889                        }
 890                }
 891
 892                /* Clear out any pending interrupts */
 893                writel(adapter_interrupts, int_reg);
 894
 895                int_reg = icom_adapter->base_addr + 0x8004;
 896        } else {
 897                int_reg = icom_adapter->base_addr + 0x4004;
 898        }
 899
 900        adapter_interrupts = readl(int_reg);
 901
 902        if (adapter_interrupts & 0x00003FFF) {
 903                /* port 0 interrupt, NOTE:  for all adapters, port 0 will be active */
 904                icom_port = &icom_adapter->port_info[0];
 905                port_int_reg = (u16) adapter_interrupts;
 906                process_interrupt(port_int_reg, icom_port);
 907                check_modem_status(icom_port);
 908        }
 909        if (adapter_interrupts & 0x3FFF0000) {
 910                /* port 1 interrupt */
 911                icom_port = &icom_adapter->port_info[1];
 912                if (icom_port->status == ICOM_PORT_ACTIVE) {
 913                        port_int_reg = (u16) (adapter_interrupts >> 16);
 914                        process_interrupt(port_int_reg, icom_port);
 915                        check_modem_status(icom_port);
 916                }
 917        }
 918
 919        /* Clear out any pending interrupts */
 920        writel(adapter_interrupts, int_reg);
 921
 922        /* flush the write */
 923        adapter_interrupts = readl(int_reg);
 924
 925        return IRQ_HANDLED;
 926}
 927
 928/*
 929 * ------------------------------------------------------------------
 930 * Begin serial-core API
 931 * ------------------------------------------------------------------
 932 */
 933static unsigned int icom_tx_empty(struct uart_port *port)
 934{
 935        int ret;
 936        unsigned long flags;
 937
 938        spin_lock_irqsave(&port->lock, flags);
 939        if (cpu_to_le16(ICOM_PORT->statStg->xmit[0].flags) &
 940            SA_FLAGS_READY_TO_XMIT)
 941                ret = TIOCSER_TEMT;
 942        else
 943                ret = 0;
 944
 945        spin_unlock_irqrestore(&port->lock, flags);
 946        return ret;
 947}
 948
 949static void icom_set_mctrl(struct uart_port *port, unsigned int mctrl)
 950{
 951        unsigned char local_osr;
 952
 953        trace(ICOM_PORT, "SET_MODEM", 0);
 954        local_osr = readb(&ICOM_PORT->dram->osr);
 955
 956        if (mctrl & TIOCM_RTS) {
 957                trace(ICOM_PORT, "RAISE_RTS", 0);
 958                local_osr |= ICOM_RTS;
 959        } else {
 960                trace(ICOM_PORT, "LOWER_RTS", 0);
 961                local_osr &= ~ICOM_RTS;
 962        }
 963
 964        if (mctrl & TIOCM_DTR) {
 965                trace(ICOM_PORT, "RAISE_DTR", 0);
 966                local_osr |= ICOM_DTR;
 967        } else {
 968                trace(ICOM_PORT, "LOWER_DTR", 0);
 969                local_osr &= ~ICOM_DTR;
 970        }
 971
 972        writeb(local_osr, &ICOM_PORT->dram->osr);
 973}
 974
 975static unsigned int icom_get_mctrl(struct uart_port *port)
 976{
 977        unsigned char status;
 978        unsigned int result;
 979
 980        trace(ICOM_PORT, "GET_MODEM", 0);
 981
 982        status = readb(&ICOM_PORT->dram->isr);
 983
 984        result = ((status & ICOM_DCD) ? TIOCM_CAR : 0)
 985            | ((status & ICOM_RI) ? TIOCM_RNG : 0)
 986            | ((status & ICOM_DSR) ? TIOCM_DSR : 0)
 987            | ((status & ICOM_CTS) ? TIOCM_CTS : 0);
 988        return result;
 989}
 990
 991static void icom_stop_tx(struct uart_port *port)
 992{
 993        unsigned char cmdReg;
 994
 995        trace(ICOM_PORT, "STOP", 0);
 996        cmdReg = readb(&ICOM_PORT->dram->CmdReg);
 997        writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg);
 998}
 999
1000static void icom_start_tx(struct uart_port *port)
1001{
1002        unsigned char cmdReg;
1003
1004        trace(ICOM_PORT, "START", 0);
1005        cmdReg = readb(&ICOM_PORT->dram->CmdReg);
1006        if ((cmdReg & CMD_HOLD_XMIT) == CMD_HOLD_XMIT)
1007                writeb(cmdReg & ~CMD_HOLD_XMIT,
1008                       &ICOM_PORT->dram->CmdReg);
1009
1010        icom_write(port);
1011}
1012
1013static void icom_send_xchar(struct uart_port *port, char ch)
1014{
1015        unsigned char xdata;
1016        int index;
1017        unsigned long flags;
1018
1019        trace(ICOM_PORT, "SEND_XCHAR", ch);
1020
1021        /* wait .1 sec to send char */
1022        for (index = 0; index < 10; index++) {
1023                spin_lock_irqsave(&port->lock, flags);
1024                xdata = readb(&ICOM_PORT->dram->xchar);
1025                if (xdata == 0x00) {
1026                        trace(ICOM_PORT, "QUICK_WRITE", 0);
1027                        writeb(ch, &ICOM_PORT->dram->xchar);
1028
1029                        /* flush write operation */
1030                        xdata = readb(&ICOM_PORT->dram->xchar);
1031                        spin_unlock_irqrestore(&port->lock, flags);
1032                        break;
1033                }
1034                spin_unlock_irqrestore(&port->lock, flags);
1035                msleep(10);
1036        }
1037}
1038
1039static void icom_stop_rx(struct uart_port *port)
1040{
1041        unsigned char cmdReg;
1042
1043        cmdReg = readb(&ICOM_PORT->dram->CmdReg);
1044        writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
1045}
1046
1047static void icom_enable_ms(struct uart_port *port)
1048{
1049        /* no-op */
1050}
1051
1052static void icom_break(struct uart_port *port, int break_state)
1053{
1054        unsigned char cmdReg;
1055        unsigned long flags;
1056
1057        spin_lock_irqsave(&port->lock, flags);
1058        trace(ICOM_PORT, "BREAK", 0);
1059        cmdReg = readb(&ICOM_PORT->dram->CmdReg);
1060        if (break_state == -1) {
1061                writeb(cmdReg | CMD_SND_BREAK, &ICOM_PORT->dram->CmdReg);
1062        } else {
1063                writeb(cmdReg & ~CMD_SND_BREAK, &ICOM_PORT->dram->CmdReg);
1064        }
1065        spin_unlock_irqrestore(&port->lock, flags);
1066}
1067
1068static int icom_open(struct uart_port *port)
1069{
1070        int retval;
1071
1072        kref_get(&ICOM_PORT->adapter->kref);
1073        retval = startup(ICOM_PORT);
1074
1075        if (retval) {
1076                kref_put(&ICOM_PORT->adapter->kref, icom_kref_release);
1077                trace(ICOM_PORT, "STARTUP_ERROR", 0);
1078                return retval;
1079        }
1080
1081        return 0;
1082}
1083
1084static void icom_close(struct uart_port *port)
1085{
1086        unsigned char cmdReg;
1087
1088        trace(ICOM_PORT, "CLOSE", 0);
1089
1090        /* stop receiver */
1091        cmdReg = readb(&ICOM_PORT->dram->CmdReg);
1092        writeb(cmdReg & (unsigned char) ~CMD_RCV_ENABLE,
1093               &ICOM_PORT->dram->CmdReg);
1094
1095        shutdown(ICOM_PORT);
1096
1097        kref_put(&ICOM_PORT->adapter->kref, icom_kref_release);
1098}
1099
1100static void icom_set_termios(struct uart_port *port,
1101                             struct ktermios *termios,
1102                             struct ktermios *old_termios)
1103{
1104        int baud;
1105        unsigned cflag, iflag;
1106        char new_config2;
1107        char new_config3 = 0;
1108        char tmp_byte;
1109        int index;
1110        int rcv_buff, xmit_buff;
1111        unsigned long offset;
1112        unsigned long flags;
1113
1114        spin_lock_irqsave(&port->lock, flags);
1115        trace(ICOM_PORT, "CHANGE_SPEED", 0);
1116
1117        cflag = termios->c_cflag;
1118        iflag = termios->c_iflag;
1119
1120        new_config2 = ICOM_ACFG_DRIVE1;
1121
1122        /* byte size and parity */
1123        switch (cflag & CSIZE) {
1124        case CS5:               /* 5 bits/char */
1125                new_config2 |= ICOM_ACFG_5BPC;
1126                break;
1127        case CS6:               /* 6 bits/char */
1128                new_config2 |= ICOM_ACFG_6BPC;
1129                break;
1130        case CS7:               /* 7 bits/char */
1131                new_config2 |= ICOM_ACFG_7BPC;
1132                break;
1133        case CS8:               /* 8 bits/char */
1134                new_config2 |= ICOM_ACFG_8BPC;
1135                break;
1136        default:
1137                break;
1138        }
1139        if (cflag & CSTOPB) {
1140                /* 2 stop bits */
1141                new_config2 |= ICOM_ACFG_2STOP_BIT;
1142        }
1143        if (cflag & PARENB) {
1144                /* parity bit enabled */
1145                new_config2 |= ICOM_ACFG_PARITY_ENAB;
1146                trace(ICOM_PORT, "PARENB", 0);
1147        }
1148        if (cflag & PARODD) {
1149                /* odd parity */
1150                new_config2 |= ICOM_ACFG_PARITY_ODD;
1151                trace(ICOM_PORT, "PARODD", 0);
1152        }
1153
1154        /* Determine divisor based on baud rate */
1155        baud = uart_get_baud_rate(port, termios, old_termios,
1156                                  icom_acfg_baud[0],
1157                                  icom_acfg_baud[BAUD_TABLE_LIMIT]);
1158        if (!baud)
1159                baud = 9600;    /* B0 transition handled in rs_set_termios */
1160
1161        for (index = 0; index < BAUD_TABLE_LIMIT; index++) {
1162                if (icom_acfg_baud[index] == baud) {
1163                        new_config3 = index;
1164                        break;
1165                }
1166        }
1167
1168        uart_update_timeout(port, cflag, baud);
1169
1170        /* CTS flow control flag and modem status interrupts */
1171        tmp_byte = readb(&(ICOM_PORT->dram->HDLCConfigReg));
1172        if (cflag & CRTSCTS)
1173                tmp_byte |= HDLC_HDW_FLOW;
1174        else
1175                tmp_byte &= ~HDLC_HDW_FLOW;
1176        writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
1177
1178        /*
1179         * Set up parity check flag
1180         */
1181        ICOM_PORT->read_status_mask = SA_FLAGS_OVERRUN | SA_FL_RCV_DONE;
1182        if (iflag & INPCK)
1183                ICOM_PORT->read_status_mask |=
1184                    SA_FLAGS_FRAME_ERROR | SA_FLAGS_PARITY_ERROR;
1185
1186        if ((iflag & BRKINT) || (iflag & PARMRK))
1187                ICOM_PORT->read_status_mask |= SA_FLAGS_BREAK_DET;
1188
1189        /*
1190         * Characters to ignore
1191         */
1192        ICOM_PORT->ignore_status_mask = 0;
1193        if (iflag & IGNPAR)
1194                ICOM_PORT->ignore_status_mask |=
1195                    SA_FLAGS_PARITY_ERROR | SA_FLAGS_FRAME_ERROR;
1196        if (iflag & IGNBRK) {
1197                ICOM_PORT->ignore_status_mask |= SA_FLAGS_BREAK_DET;
1198                /*
1199                 * If we're ignore parity and break indicators, ignore
1200                 * overruns too.  (For real raw support).
1201                 */
1202                if (iflag & IGNPAR)
1203                        ICOM_PORT->ignore_status_mask |= SA_FLAGS_OVERRUN;
1204        }
1205
1206        /*
1207         * !!! ignore all characters if CREAD is not set
1208         */
1209        if ((cflag & CREAD) == 0)
1210                ICOM_PORT->ignore_status_mask |= SA_FL_RCV_DONE;
1211
1212        /* Turn off Receiver to prepare for reset */
1213        writeb(CMD_RCV_DISABLE, &ICOM_PORT->dram->CmdReg);
1214
1215        for (index = 0; index < 10; index++) {
1216                if (readb(&ICOM_PORT->dram->PrevCmdReg) == 0x00) {
1217                        break;
1218                }
1219        }
1220
1221        /* clear all current buffers of data */
1222        for (rcv_buff = 0; rcv_buff < NUM_RBUFFS; rcv_buff++) {
1223                ICOM_PORT->statStg->rcv[rcv_buff].flags = 0;
1224                ICOM_PORT->statStg->rcv[rcv_buff].leLength = 0;
1225                ICOM_PORT->statStg->rcv[rcv_buff].WorkingLength =
1226                    (unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
1227        }
1228
1229        for (xmit_buff = 0; xmit_buff < NUM_XBUFFS; xmit_buff++) {
1230                ICOM_PORT->statStg->xmit[xmit_buff].flags = 0;
1231        }
1232
1233        /* activate changes and start xmit and receiver here */
1234        /* Enable the receiver */
1235        writeb(new_config3, &(ICOM_PORT->dram->async_config3));
1236        writeb(new_config2, &(ICOM_PORT->dram->async_config2));
1237        tmp_byte = readb(&(ICOM_PORT->dram->HDLCConfigReg));
1238        tmp_byte |= HDLC_PPP_PURE_ASYNC | HDLC_FF_FILL;
1239        writeb(tmp_byte, &(ICOM_PORT->dram->HDLCConfigReg));
1240        writeb(0x04, &(ICOM_PORT->dram->FlagFillIdleTimer));    /* 0.5 seconds */
1241        writeb(0xFF, &(ICOM_PORT->dram->ier));  /* enable modem signal interrupts */
1242
1243        /* reset processor */
1244        writeb(CMD_RESTART, &ICOM_PORT->dram->CmdReg);
1245
1246        for (index = 0; index < 10; index++) {
1247                if (readb(&ICOM_PORT->dram->CmdReg) == 0x00) {
1248                        break;
1249                }
1250        }
1251
1252        /* Enable Transmitter and Reciever */
1253        offset =
1254            (unsigned long) &ICOM_PORT->statStg->rcv[0] -
1255            (unsigned long) ICOM_PORT->statStg;
1256        writel(ICOM_PORT->statStg_pci + offset,
1257               &ICOM_PORT->dram->RcvStatusAddr);
1258        ICOM_PORT->next_rcv = 0;
1259        ICOM_PORT->put_length = 0;
1260        *ICOM_PORT->xmitRestart = 0;
1261        writel(ICOM_PORT->xmitRestart_pci,
1262               &ICOM_PORT->dram->XmitStatusAddr);
1263        trace(ICOM_PORT, "XR_ENAB", 0);
1264        writeb(CMD_XMIT_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
1265
1266        spin_unlock_irqrestore(&port->lock, flags);
1267}
1268
1269static const char *icom_type(struct uart_port *port)
1270{
1271        return "icom";
1272}
1273
1274static void icom_release_port(struct uart_port *port)
1275{
1276}
1277
1278static int icom_request_port(struct uart_port *port)
1279{
1280        return 0;
1281}
1282
1283static void icom_config_port(struct uart_port *port, int flags)
1284{
1285        port->type = PORT_ICOM;
1286}
1287
1288static struct uart_ops icom_ops = {
1289        .tx_empty = icom_tx_empty,
1290        .set_mctrl = icom_set_mctrl,
1291        .get_mctrl = icom_get_mctrl,
1292        .stop_tx = icom_stop_tx,
1293        .start_tx = icom_start_tx,
1294        .send_xchar = icom_send_xchar,
1295        .stop_rx = icom_stop_rx,
1296        .enable_ms = icom_enable_ms,
1297        .break_ctl = icom_break,
1298        .startup = icom_open,
1299        .shutdown = icom_close,
1300        .set_termios = icom_set_termios,
1301        .type = icom_type,
1302        .release_port = icom_release_port,
1303        .request_port = icom_request_port,
1304        .config_port = icom_config_port,
1305};
1306
1307#define ICOM_CONSOLE NULL
1308
1309static struct uart_driver icom_uart_driver = {
1310        .owner = THIS_MODULE,
1311        .driver_name = ICOM_DRIVER_NAME,
1312        .dev_name = "ttyA",
1313        .major = ICOM_MAJOR,
1314        .minor = ICOM_MINOR_START,
1315        .nr = NR_PORTS,
1316        .cons = ICOM_CONSOLE,
1317};
1318
1319static int __devinit icom_init_ports(struct icom_adapter *icom_adapter)
1320{
1321        u32 subsystem_id = icom_adapter->subsystem_id;
1322        int i;
1323        struct icom_port *icom_port;
1324
1325        if (icom_adapter->version == ADAPTER_V1) {
1326                icom_adapter->numb_ports = 2;
1327
1328                for (i = 0; i < 2; i++) {
1329                        icom_port = &icom_adapter->port_info[i];
1330                        icom_port->port = i;
1331                        icom_port->status = ICOM_PORT_ACTIVE;
1332                        icom_port->imbed_modem = ICOM_UNKNOWN;
1333                }
1334        } else {
1335                if (subsystem_id == PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL) {
1336                        icom_adapter->numb_ports = 4;
1337
1338                        for (i = 0; i < 4; i++) {
1339                                icom_port = &icom_adapter->port_info[i];
1340
1341                                icom_port->port = i;
1342                                icom_port->status = ICOM_PORT_ACTIVE;
1343                                icom_port->imbed_modem = ICOM_IMBED_MODEM;
1344                        }
1345                } else {
1346                        icom_adapter->numb_ports = 4;
1347
1348                        icom_adapter->port_info[0].port = 0;
1349                        icom_adapter->port_info[0].status = ICOM_PORT_ACTIVE;
1350
1351                        if (subsystem_id ==
1352                            PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM) {
1353                                icom_adapter->port_info[0].imbed_modem = ICOM_IMBED_MODEM;
1354                        } else {
1355                                icom_adapter->port_info[0].imbed_modem = ICOM_RVX;
1356                        }
1357
1358                        icom_adapter->port_info[1].status = ICOM_PORT_OFF;
1359
1360                        icom_adapter->port_info[2].port = 2;
1361                        icom_adapter->port_info[2].status = ICOM_PORT_ACTIVE;
1362                        icom_adapter->port_info[2].imbed_modem = ICOM_RVX;
1363                        icom_adapter->port_info[3].status = ICOM_PORT_OFF;
1364                }
1365        }
1366
1367        return 0;
1368}
1369
1370static void icom_port_active(struct icom_port *icom_port, struct icom_adapter *icom_adapter, int port_num)
1371{
1372        if (icom_adapter->version == ADAPTER_V1) {
1373                icom_port->global_reg = icom_adapter->base_addr + 0x4000;
1374                icom_port->int_reg = icom_adapter->base_addr +
1375                    0x4004 + 2 - 2 * port_num;
1376        } else {
1377                icom_port->global_reg = icom_adapter->base_addr + 0x8000;
1378                if (icom_port->port < 2)
1379                        icom_port->int_reg = icom_adapter->base_addr +
1380                            0x8004 + 2 - 2 * icom_port->port;
1381                else
1382                        icom_port->int_reg = icom_adapter->base_addr +
1383                            0x8024 + 2 - 2 * (icom_port->port - 2);
1384        }
1385}
1386static int __devinit icom_load_ports(struct icom_adapter *icom_adapter)
1387{
1388        struct icom_port *icom_port;
1389        int port_num;
1390
1391        for (port_num = 0; port_num < icom_adapter->numb_ports; port_num++) {
1392
1393                icom_port = &icom_adapter->port_info[port_num];
1394
1395                if (icom_port->status == ICOM_PORT_ACTIVE) {
1396                        icom_port_active(icom_port, icom_adapter, port_num);
1397                        icom_port->dram = icom_adapter->base_addr +
1398                                        0x2000 * icom_port->port;
1399
1400                        icom_port->adapter = icom_adapter;
1401
1402                        /* get port memory */
1403                        if (get_port_memory(icom_port) != 0) {
1404                                dev_err(&icom_port->adapter->pci_dev->dev,
1405                                        "Memory allocation for port FAILED\n");
1406                        }
1407                }
1408        }
1409        return 0;
1410}
1411
1412static int __devinit icom_alloc_adapter(struct icom_adapter
1413                                        **icom_adapter_ref)
1414{
1415        int adapter_count = 0;
1416        struct icom_adapter *icom_adapter;
1417        struct icom_adapter *cur_adapter_entry;
1418        struct list_head *tmp;
1419
1420        icom_adapter = (struct icom_adapter *)
1421            kzalloc(sizeof(struct icom_adapter), GFP_KERNEL);
1422
1423        if (!icom_adapter) {
1424                return -ENOMEM;
1425        }
1426
1427        list_for_each(tmp, &icom_adapter_head) {
1428                cur_adapter_entry =
1429                    list_entry(tmp, struct icom_adapter,
1430                               icom_adapter_entry);
1431                if (cur_adapter_entry->index != adapter_count) {
1432                        break;
1433                }
1434                adapter_count++;
1435        }
1436
1437        icom_adapter->index = adapter_count;
1438        list_add_tail(&icom_adapter->icom_adapter_entry, tmp);
1439
1440        *icom_adapter_ref = icom_adapter;
1441        return 0;
1442}
1443
1444static void icom_free_adapter(struct icom_adapter *icom_adapter)
1445{
1446        list_del(&icom_adapter->icom_adapter_entry);
1447        kfree(icom_adapter);
1448}
1449
1450static void icom_remove_adapter(struct icom_adapter *icom_adapter)
1451{
1452        struct icom_port *icom_port;
1453        int index;
1454
1455        for (index = 0; index < icom_adapter->numb_ports; index++) {
1456                icom_port = &icom_adapter->port_info[index];
1457
1458                if (icom_port->status == ICOM_PORT_ACTIVE) {
1459                        dev_info(&icom_adapter->pci_dev->dev,
1460                                 "Device removed\n");
1461
1462                        uart_remove_one_port(&icom_uart_driver,
1463                                             &icom_port->uart_port);
1464
1465                        /* be sure that DTR and RTS are dropped */
1466                        writeb(0x00, &icom_port->dram->osr);
1467
1468                        /* Wait 0.1 Sec for simple Init to complete */
1469                        msleep(100);
1470
1471                        /* Stop proccessor */
1472                        stop_processor(icom_port);
1473
1474                        free_port_memory(icom_port);
1475                }
1476        }
1477
1478        free_irq(icom_adapter->pci_dev->irq, (void *) icom_adapter);
1479        iounmap(icom_adapter->base_addr);
1480        pci_release_regions(icom_adapter->pci_dev);
1481        icom_free_adapter(icom_adapter);
1482}
1483
1484static void icom_kref_release(struct kref *kref)
1485{
1486        struct icom_adapter *icom_adapter;
1487
1488        icom_adapter = to_icom_adapter(kref);
1489        icom_remove_adapter(icom_adapter);
1490}
1491
1492static int __devinit icom_probe(struct pci_dev *dev,
1493                                const struct pci_device_id *ent)
1494{
1495        int index;
1496        unsigned int command_reg;
1497        int retval;
1498        struct icom_adapter *icom_adapter;
1499        struct icom_port *icom_port;
1500
1501        retval = pci_enable_device(dev);
1502        if (retval) {
1503                dev_err(&dev->dev, "Device enable FAILED\n");
1504                return retval;
1505        }
1506
1507        if ( (retval = pci_request_regions(dev, "icom"))) {
1508                 dev_err(&dev->dev, "pci_request_regions FAILED\n");
1509                 pci_disable_device(dev);
1510                 return retval;
1511         }
1512
1513        pci_set_master(dev);
1514
1515        if ( (retval = pci_read_config_dword(dev, PCI_COMMAND, &command_reg))) {
1516                dev_err(&dev->dev, "PCI Config read FAILED\n");
1517                return retval;
1518        }
1519
1520        pci_write_config_dword(dev, PCI_COMMAND,
1521                command_reg | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
1522                | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
1523
1524        if (ent->driver_data == ADAPTER_V1) {
1525                pci_write_config_dword(dev, 0x44, 0x8300830A);
1526        } else {
1527                pci_write_config_dword(dev, 0x44, 0x42004200);
1528                pci_write_config_dword(dev, 0x48, 0x42004200);
1529        }
1530
1531
1532        retval = icom_alloc_adapter(&icom_adapter);
1533        if (retval) {
1534                 dev_err(&dev->dev, "icom_alloc_adapter FAILED\n");
1535                 retval = -EIO;
1536                 goto probe_exit0;
1537        }
1538
1539        icom_adapter->base_addr_pci = pci_resource_start(dev, 0);
1540        icom_adapter->pci_dev = dev;
1541        icom_adapter->version = ent->driver_data;
1542        icom_adapter->subsystem_id = ent->subdevice;
1543
1544
1545        retval = icom_init_ports(icom_adapter);
1546        if (retval) {
1547                dev_err(&dev->dev, "Port configuration failed\n");
1548                goto probe_exit1;
1549        }
1550
1551        icom_adapter->base_addr = pci_ioremap_bar(dev, 0);
1552
1553        if (!icom_adapter->base_addr)
1554                goto probe_exit1;
1555
1556         /* save off irq and request irq line */
1557         if ( (retval = request_irq(dev->irq, icom_interrupt,
1558                                   IRQF_DISABLED | IRQF_SHARED, ICOM_DRIVER_NAME,
1559                                   (void *) icom_adapter))) {
1560                  goto probe_exit2;
1561         }
1562
1563        retval = icom_load_ports(icom_adapter);
1564
1565        for (index = 0; index < icom_adapter->numb_ports; index++) {
1566                icom_port = &icom_adapter->port_info[index];
1567
1568                if (icom_port->status == ICOM_PORT_ACTIVE) {
1569                        icom_port->uart_port.irq = icom_port->adapter->pci_dev->irq;
1570                        icom_port->uart_port.type = PORT_ICOM;
1571                        icom_port->uart_port.iotype = UPIO_MEM;
1572                        icom_port->uart_port.membase =
1573                                               (char *) icom_adapter->base_addr_pci;
1574                        icom_port->uart_port.fifosize = 16;
1575                        icom_port->uart_port.ops = &icom_ops;
1576                        icom_port->uart_port.line =
1577                        icom_port->port + icom_adapter->index * 4;
1578                        if (uart_add_one_port (&icom_uart_driver, &icom_port->uart_port)) {
1579                                icom_port->status = ICOM_PORT_OFF;
1580                                dev_err(&dev->dev, "Device add failed\n");
1581                         } else
1582                                dev_info(&dev->dev, "Device added\n");
1583                }
1584        }
1585
1586        kref_init(&icom_adapter->kref);
1587        return 0;
1588
1589probe_exit2:
1590        iounmap(icom_adapter->base_addr);
1591probe_exit1:
1592        icom_free_adapter(icom_adapter);
1593
1594probe_exit0:
1595        pci_release_regions(dev);
1596        pci_disable_device(dev);
1597
1598        return retval;
1599}
1600
1601static void __devexit icom_remove(struct pci_dev *dev)
1602{
1603        struct icom_adapter *icom_adapter;
1604        struct list_head *tmp;
1605
1606        list_for_each(tmp, &icom_adapter_head) {
1607                icom_adapter = list_entry(tmp, struct icom_adapter,
1608                                          icom_adapter_entry);
1609                if (icom_adapter->pci_dev == dev) {
1610                        kref_put(&icom_adapter->kref, icom_kref_release);
1611                        return;
1612                }
1613        }
1614
1615        dev_err(&dev->dev, "Unable to find device to remove\n");
1616}
1617
1618static struct pci_driver icom_pci_driver = {
1619        .name = ICOM_DRIVER_NAME,
1620        .id_table = icom_pci_table,
1621        .probe = icom_probe,
1622        .remove = __devexit_p(icom_remove),
1623};
1624
1625static int __init icom_init(void)
1626{
1627        int ret;
1628
1629        spin_lock_init(&icom_lock);
1630
1631        ret = uart_register_driver(&icom_uart_driver);
1632        if (ret)
1633                return ret;
1634
1635        ret = pci_register_driver(&icom_pci_driver);
1636
1637        if (ret < 0)
1638                uart_unregister_driver(&icom_uart_driver);
1639
1640        return ret;
1641}
1642
1643static void __exit icom_exit(void)
1644{
1645        pci_unregister_driver(&icom_pci_driver);
1646        uart_unregister_driver(&icom_uart_driver);
1647}
1648
1649module_init(icom_init);
1650module_exit(icom_exit);
1651
1652MODULE_AUTHOR("Michael Anderson <mjanders@us.ibm.com>");
1653MODULE_DESCRIPTION("IBM iSeries Serial IOA driver");
1654MODULE_SUPPORTED_DEVICE
1655    ("IBM iSeries 2745, 2771, 2772, 2742, 2793 and 2805 Communications adapters");
1656MODULE_LICENSE("GPL");
1657
1658