linux-old/arch/ia64/sn/io/io.c
<<
>>
Prefs
   1/* $Id: io.c,v 1.2 2001/06/26 14:02:43 pfg Exp $
   2 *
   3 * This file is subject to the terms and conditions of the GNU General Public
   4 * License.  See the file "COPYING" in the main directory of this archive
   5 * for more details.
   6 *
   7 * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
   8 */
   9
  10#include <linux/config.h>
  11#include <linux/types.h>
  12#include <linux/slab.h>
  13#include <asm/sn/types.h>
  14#include <asm/sn/sgi.h>
  15#include <asm/sn/driver.h>
  16#include <asm/sn/iograph.h>
  17#include <asm/param.h>
  18#include <asm/sn/pio.h>
  19#include <asm/sn/xtalk/xwidget.h>
  20#include <asm/sn/io.h>
  21#include <asm/sn/sn_private.h>
  22#include <asm/sn/addrs.h>
  23#include <asm/sn/invent.h>
  24#include <asm/sn/hcl.h>
  25#include <asm/sn/hcl_util.h>
  26#include <asm/sn/intr.h>
  27#include <asm/sn/xtalk/xtalkaddrs.h>
  28#include <asm/sn/klconfig.h>
  29#include <asm/sn/sn_cpuid.h>
  30
  31extern xtalk_provider_t hub_provider;
  32extern void hub_intr_init(vertex_hdl_t hubv);
  33
  34static int force_fire_and_forget = 1;
  35static int ignore_conveyor_override;
  36
  37
  38/* 
  39 * Implementation of hub iobus operations.
  40 *
  41 * Hub provides a crosstalk "iobus" on IP27 systems.  These routines
  42 * provide a platform-specific implementation of xtalk used by all xtalk 
  43 * cards on IP27 systems.
  44 *
  45 * Called from corresponding xtalk_* routines.
  46 */
  47
  48
  49/* PIO MANAGEMENT */
  50/* For mapping system virtual address space to xtalk space on a specified widget */
  51
  52/*
  53 * Setup pio structures needed for a particular hub.
  54 */
  55static void
  56hub_pio_init(vertex_hdl_t hubv)
  57{
  58        xwidgetnum_t widget;
  59        hubinfo_t hubinfo;
  60        nasid_t nasid;
  61        int bigwin;
  62        hub_piomap_t hub_piomap;
  63
  64        hubinfo_get(hubv, &hubinfo);
  65        nasid = hubinfo->h_nasid;
  66
  67        /* Initialize small window piomaps for this hub */
  68        for (widget=0; widget <= HUB_WIDGET_ID_MAX; widget++) {
  69                hub_piomap = hubinfo_swin_piomap_get(hubinfo, (int)widget);
  70                hub_piomap->hpio_xtalk_info.xp_target = widget;
  71                hub_piomap->hpio_xtalk_info.xp_xtalk_addr = 0;
  72                hub_piomap->hpio_xtalk_info.xp_mapsz = SWIN_SIZE;
  73                hub_piomap->hpio_xtalk_info.xp_kvaddr = (caddr_t)NODE_SWIN_BASE(nasid, widget);
  74                hub_piomap->hpio_hub = hubv;
  75                hub_piomap->hpio_flags = HUB_PIOMAP_IS_VALID;
  76        }
  77
  78        /* Initialize big window piomaps for this hub */
  79        for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) {
  80                hub_piomap = hubinfo_bwin_piomap_get(hubinfo, bigwin);
  81                hub_piomap->hpio_xtalk_info.xp_mapsz = BWIN_SIZE;
  82                hub_piomap->hpio_hub = hubv;
  83                hub_piomap->hpio_holdcnt = 0;
  84                hub_piomap->hpio_flags = HUB_PIOMAP_IS_BIGWINDOW;
  85                IIO_ITTE_DISABLE(nasid, bigwin);
  86        }
  87        hub_set_piomode(nasid, HUB_PIO_CONVEYOR);
  88
  89        spin_lock_init(&hubinfo->h_bwlock);
  90/*
  91 * If this lock can be acquired from interrupts or bh's, add SV_INTS or SV_BHS,
  92 * respectively, to the flags here.
  93 */
  94        sv_init(&hubinfo->h_bwwait, &hubinfo->h_bwlock, SV_ORDER_FIFO | SV_MON_SPIN); 
  95}
  96
  97/* 
  98 * Create a caddr_t-to-xtalk_addr mapping.
  99 *
 100 * Use a small window if possible (that's the usual case), but
 101 * manage big windows if needed.  Big window mappings can be
 102 * either FIXED or UNFIXED -- we keep at least 1 big window available
 103 * for UNFIXED mappings.
 104 *
 105 * Returns an opaque pointer-sized type which can be passed to
 106 * other hub_pio_* routines on success, or NULL if the request
 107 * cannot be satisfied.
 108 */
 109/* ARGSUSED */
 110hub_piomap_t
 111hub_piomap_alloc(vertex_hdl_t dev,      /* set up mapping for this device */
 112                device_desc_t dev_desc, /* device descriptor */
 113                iopaddr_t xtalk_addr,   /* map for this xtalk_addr range */
 114                size_t byte_count,
 115                size_t byte_count_max,  /* maximum size of a mapping */
 116                unsigned flags)         /* defined in sys/pio.h */
 117{
 118        xwidget_info_t widget_info = xwidget_info_get(dev);
 119        xwidgetnum_t widget = xwidget_info_id_get(widget_info);
 120        vertex_hdl_t hubv = xwidget_info_master_get(widget_info);
 121        hubinfo_t hubinfo;
 122        hub_piomap_t bw_piomap;
 123        int bigwin, free_bw_index;
 124        nasid_t nasid;
 125        volatile hubreg_t junk;
 126        caddr_t kvaddr;
 127#ifdef PIOMAP_UNC_ACC_SPACE
 128        uint64_t addr;
 129#endif
 130
 131        /* sanity check */
 132        if (byte_count_max > byte_count)
 133                return(NULL);
 134
 135        hubinfo_get(hubv, &hubinfo);
 136
 137        /* If xtalk_addr range is mapped by a small window, we don't have 
 138         * to do much 
 139         */
 140        if (xtalk_addr + byte_count <= SWIN_SIZE) {
 141                hub_piomap_t piomap;
 142
 143                piomap = hubinfo_swin_piomap_get(hubinfo, (int)widget);
 144#ifdef PIOMAP_UNC_ACC_SPACE
 145                if (flags & PIOMAP_UNC_ACC) {
 146                        addr = (uint64_t)piomap->hpio_xtalk_info.xp_kvaddr;
 147                        addr |= PIOMAP_UNC_ACC_SPACE;
 148                        piomap->hpio_xtalk_info.xp_kvaddr = (caddr_t)addr;
 149                }
 150#endif
 151                return piomap;
 152        }
 153
 154        /* We need to use a big window mapping.  */
 155
 156        /*
 157         * TBD: Allow requests that would consume multiple big windows --
 158         * split the request up and use multiple mapping entries.
 159         * For now, reject requests that span big windows.
 160         */
 161        if ((xtalk_addr % BWIN_SIZE) + byte_count > BWIN_SIZE)
 162                return(NULL);
 163
 164
 165        /* Round xtalk address down for big window alignement */
 166        xtalk_addr = xtalk_addr & ~(BWIN_SIZE-1);
 167
 168        /*
 169         * Check to see if an existing big window mapping will suffice.
 170         */
 171tryagain:
 172        free_bw_index = -1;
 173        spin_lock(&hubinfo->h_bwlock);
 174        for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) {
 175                bw_piomap = hubinfo_bwin_piomap_get(hubinfo, bigwin);
 176
 177                /* If mapping is not valid, skip it */
 178                if (!(bw_piomap->hpio_flags & HUB_PIOMAP_IS_VALID)) {
 179                        free_bw_index = bigwin;
 180                        continue;
 181                }
 182
 183                /* 
 184                 * If mapping is UNFIXED, skip it.  We don't allow sharing
 185                 * of UNFIXED mappings, because this would allow starvation.
 186                 */
 187                if (!(bw_piomap->hpio_flags & HUB_PIOMAP_IS_FIXED))
 188                        continue;
 189
 190                if ( xtalk_addr == bw_piomap->hpio_xtalk_info.xp_xtalk_addr &&
 191                     widget == bw_piomap->hpio_xtalk_info.xp_target) {
 192                        bw_piomap->hpio_holdcnt++;
 193                        spin_unlock(&hubinfo->h_bwlock);
 194                        return(bw_piomap);
 195                }
 196        }
 197
 198        /*
 199         * None of the existing big window mappings will work for us --
 200         * we need to establish a new mapping.
 201         */
 202
 203        /* Insure that we don't consume all big windows with FIXED mappings */
 204        if (flags & PIOMAP_FIXED) {
 205                if (hubinfo->h_num_big_window_fixed < HUB_NUM_BIG_WINDOW-1) {
 206                        ASSERT(free_bw_index >= 0);
 207                        hubinfo->h_num_big_window_fixed++;
 208                } else {
 209                        bw_piomap = NULL;
 210                        goto done;
 211                }
 212        } else /* PIOMAP_UNFIXED */ {
 213                if (free_bw_index < 0) {
 214                        if (flags & PIOMAP_NOSLEEP) {
 215                                bw_piomap = NULL;
 216                                goto done;
 217                        }
 218
 219                        sv_wait(&hubinfo->h_bwwait, 0, 0);
 220                        goto tryagain;
 221                }
 222        }
 223
 224
 225        /* OK!  Allocate big window free_bw_index for this mapping. */
 226        /* 
 227         * The code below does a PIO write to setup an ITTE entry.
 228         * We need to prevent other CPUs from seeing our updated memory 
 229         * shadow of the ITTE (in the piomap) until the ITTE entry is 
 230         * actually set up; otherwise, another CPU might attempt a PIO 
 231         * prematurely.  
 232         *
 233         * Also, the only way we can know that an entry has been received 
 234         * by the hub and can be used by future PIO reads/writes is by 
 235         * reading back the ITTE entry after writing it.
 236         *
 237         * For these two reasons, we PIO read back the ITTE entry after
 238         * we write it.
 239         */
 240
 241        nasid = hubinfo->h_nasid;
 242        IIO_ITTE_PUT(nasid, free_bw_index, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr);     
 243        junk = HUB_L(IIO_ITTE_GET(nasid, free_bw_index));
 244
 245        bw_piomap = hubinfo_bwin_piomap_get(hubinfo, free_bw_index);
 246        bw_piomap->hpio_xtalk_info.xp_dev = dev;
 247        bw_piomap->hpio_xtalk_info.xp_target = widget;
 248        bw_piomap->hpio_xtalk_info.xp_xtalk_addr = xtalk_addr;
 249        kvaddr = (caddr_t)NODE_BWIN_BASE(nasid, free_bw_index);
 250#ifdef PIOMAP_UNC_ACC_SPACE
 251        if (flags & PIOMAP_UNC_ACC) {
 252                addr = (uint64_t)kvaddr;
 253                addr |= PIOMAP_UNC_ACC_SPACE;
 254                kvaddr = (caddr_t)addr;
 255        }
 256#endif
 257        bw_piomap->hpio_xtalk_info.xp_kvaddr = kvaddr;
 258        bw_piomap->hpio_holdcnt++;
 259        bw_piomap->hpio_bigwin_num = free_bw_index;
 260
 261        if (flags & PIOMAP_FIXED)
 262                bw_piomap->hpio_flags |= HUB_PIOMAP_IS_VALID | HUB_PIOMAP_IS_FIXED;
 263        else
 264                bw_piomap->hpio_flags |= HUB_PIOMAP_IS_VALID;
 265
 266done:
 267        spin_unlock(&hubinfo->h_bwlock);
 268        return(bw_piomap);
 269}
 270
 271/*
 272 * hub_piomap_free destroys a caddr_t-to-xtalk pio mapping and frees
 273 * any associated mapping resources.  
 274 *
 275 * If this * piomap was handled with a small window, or if it was handled
 276 * in a big window that's still in use by someone else, then there's 
 277 * nothing to do.  On the other hand, if this mapping was handled 
 278 * with a big window, AND if we were the final user of that mapping, 
 279 * then destroy the mapping.
 280 */
 281void
 282hub_piomap_free(hub_piomap_t hub_piomap)
 283{
 284        vertex_hdl_t hubv;
 285        hubinfo_t hubinfo;
 286        nasid_t nasid;
 287
 288        /* 
 289         * Small windows are permanently mapped to corresponding widgets,
 290         * so there're no resources to free.
 291         */
 292        if (!(hub_piomap->hpio_flags & HUB_PIOMAP_IS_BIGWINDOW))
 293                return;
 294
 295        ASSERT(hub_piomap->hpio_flags & HUB_PIOMAP_IS_VALID);
 296        ASSERT(hub_piomap->hpio_holdcnt > 0);
 297
 298        hubv = hub_piomap->hpio_hub;
 299        hubinfo_get(hubv, &hubinfo);
 300        nasid = hubinfo->h_nasid;
 301
 302        spin_lock(&hubinfo->h_bwlock);
 303
 304        /*
 305         * If this is the last hold on this mapping, free it.
 306         */
 307        if (--hub_piomap->hpio_holdcnt == 0) {
 308                IIO_ITTE_DISABLE(nasid, hub_piomap->hpio_bigwin_num );
 309
 310                if (hub_piomap->hpio_flags & HUB_PIOMAP_IS_FIXED) {
 311                        hub_piomap->hpio_flags &= ~(HUB_PIOMAP_IS_VALID | HUB_PIOMAP_IS_FIXED);
 312                        hubinfo->h_num_big_window_fixed--;
 313                        ASSERT(hubinfo->h_num_big_window_fixed >= 0);
 314                } else
 315                        hub_piomap->hpio_flags &= ~HUB_PIOMAP_IS_VALID;
 316
 317                (void)sv_signal(&hubinfo->h_bwwait);
 318        }
 319
 320        spin_unlock(&hubinfo->h_bwlock);
 321}
 322
 323/*
 324 * Establish a mapping to a given xtalk address range using the resources
 325 * allocated earlier.
 326 */
 327caddr_t
 328hub_piomap_addr(hub_piomap_t hub_piomap,        /* mapping resources */
 329                iopaddr_t xtalk_addr,           /* map for this xtalk address */
 330                size_t byte_count)              /* map this many bytes */
 331{
 332        /* Verify that range can be mapped using the specified piomap */
 333        if (xtalk_addr < hub_piomap->hpio_xtalk_info.xp_xtalk_addr)
 334                return(0);
 335
 336        if (xtalk_addr + byte_count > 
 337                ( hub_piomap->hpio_xtalk_info.xp_xtalk_addr + 
 338                        hub_piomap->hpio_xtalk_info.xp_mapsz))
 339                return(0);
 340
 341        if (hub_piomap->hpio_flags & HUB_PIOMAP_IS_VALID)
 342                return(hub_piomap->hpio_xtalk_info.xp_kvaddr + 
 343                        (xtalk_addr % hub_piomap->hpio_xtalk_info.xp_mapsz));
 344        else
 345                return(0);
 346}
 347
 348
 349/*
 350 * Driver indicates that it's done with PIO's from an earlier piomap_addr.
 351 */
 352/* ARGSUSED */
 353void
 354hub_piomap_done(hub_piomap_t hub_piomap)        /* done with these mapping resources */
 355{
 356        /* Nothing to do */
 357}
 358
 359
 360/*
 361 * For translations that require no mapping resources, supply a kernel virtual
 362 * address that maps to the specified xtalk address range.
 363 */
 364/* ARGSUSED */
 365caddr_t
 366hub_piotrans_addr(      vertex_hdl_t dev,       /* translate to this device */
 367                        device_desc_t dev_desc, /* device descriptor */
 368                        iopaddr_t xtalk_addr,   /* Crosstalk address */
 369                        size_t byte_count,      /* map this many bytes */
 370                        unsigned flags)         /* (currently unused) */
 371{
 372        xwidget_info_t widget_info = xwidget_info_get(dev);
 373        xwidgetnum_t widget = xwidget_info_id_get(widget_info);
 374        vertex_hdl_t hubv = xwidget_info_master_get(widget_info);
 375        hub_piomap_t hub_piomap;
 376        hubinfo_t hubinfo;
 377        caddr_t addr;
 378
 379        hubinfo_get(hubv, &hubinfo);
 380
 381        if (xtalk_addr + byte_count <= SWIN_SIZE) {
 382                hub_piomap = hubinfo_swin_piomap_get(hubinfo, (int)widget);
 383                addr = hub_piomap_addr(hub_piomap, xtalk_addr, byte_count);
 384#ifdef PIOMAP_UNC_ACC_SPACE
 385                if (flags & PIOMAP_UNC_ACC) {
 386                        uint64_t iaddr;
 387                        iaddr = (uint64_t)addr;
 388                        iaddr |= PIOMAP_UNC_ACC_SPACE;
 389                        addr = (caddr_t)iaddr;
 390                }
 391#endif
 392                return(addr);
 393        } else
 394                return(0);
 395}
 396
 397
 398/* DMA MANAGEMENT */
 399/* Mapping from crosstalk space to system physical space */
 400
 401
 402/*
 403 * Allocate resources needed to set up DMA mappings up to a specified size
 404 * on a specified adapter.
 405 * 
 406 * We don't actually use the adapter ID for anything.  It's just the adapter
 407 * that the lower level driver plans to use for DMA.
 408 */
 409/* ARGSUSED */
 410hub_dmamap_t
 411hub_dmamap_alloc(       vertex_hdl_t dev,       /* set up mappings for this device */
 412                        device_desc_t dev_desc, /* device descriptor */
 413                        size_t byte_count_max,  /* max size of a mapping */
 414                        unsigned flags)         /* defined in dma.h */
 415{
 416        hub_dmamap_t dmamap;
 417        xwidget_info_t widget_info = xwidget_info_get(dev);
 418        xwidgetnum_t widget = xwidget_info_id_get(widget_info);
 419        vertex_hdl_t hubv = xwidget_info_master_get(widget_info);
 420
 421        dmamap = kmalloc(sizeof(struct hub_dmamap_s), GFP_ATOMIC);
 422        dmamap->hdma_xtalk_info.xd_dev = dev;
 423        dmamap->hdma_xtalk_info.xd_target = widget;
 424        dmamap->hdma_hub = hubv;
 425        dmamap->hdma_flags = HUB_DMAMAP_IS_VALID;
 426        if (flags & XTALK_FIXED)
 427                dmamap->hdma_flags |= HUB_DMAMAP_IS_FIXED;
 428
 429        return(dmamap);
 430}
 431
 432/*
 433 * Destroy a DMA mapping from crosstalk space to system address space.
 434 * There is no actual mapping hardware to destroy, but we at least mark
 435 * the dmamap INVALID and free the space that it took.
 436 */
 437void
 438hub_dmamap_free(hub_dmamap_t hub_dmamap)
 439{
 440        hub_dmamap->hdma_flags &= ~HUB_DMAMAP_IS_VALID;
 441        kfree(hub_dmamap);
 442}
 443
 444/*
 445 * Establish a DMA mapping using the resources allocated in a previous dmamap_alloc.
 446 * Return an appropriate crosstalk address range that maps to the specified physical 
 447 * address range.
 448 */
 449/* ARGSUSED */
 450extern iopaddr_t
 451hub_dmamap_addr(        hub_dmamap_t dmamap,    /* use these mapping resources */
 452                        paddr_t paddr,          /* map for this address */
 453                        size_t byte_count)      /* map this many bytes */
 454{
 455        vertex_hdl_t vhdl;
 456
 457        ASSERT(dmamap->hdma_flags & HUB_DMAMAP_IS_VALID);
 458
 459        if (dmamap->hdma_flags & HUB_DMAMAP_USED) {
 460            /* If the map is FIXED, re-use is OK. */
 461            if (!(dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
 462                char name[MAXDEVNAME];
 463                vhdl = dmamap->hdma_xtalk_info.xd_dev;
 464                printk(KERN_WARNING  "%s: hub_dmamap_addr re-uses dmamap.\n", vertex_to_name(vhdl, name, MAXDEVNAME));
 465            }
 466        } else {
 467                dmamap->hdma_flags |= HUB_DMAMAP_USED;
 468        }
 469
 470        /* There isn't actually any DMA mapping hardware on the hub. */
 471        return( (PHYS_TO_DMA(paddr)) );
 472}
 473
 474/*
 475 * Establish a DMA mapping using the resources allocated in a previous dmamap_alloc.
 476 * Return an appropriate crosstalk address list that maps to the specified physical 
 477 * address list.
 478 */
 479/* ARGSUSED */
 480alenlist_t
 481hub_dmamap_list(hub_dmamap_t hub_dmamap,        /* use these mapping resources */
 482                alenlist_t palenlist,           /* map this area of memory */
 483                unsigned flags)
 484{
 485        vertex_hdl_t vhdl;
 486
 487        ASSERT(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_VALID);
 488
 489        if (hub_dmamap->hdma_flags & HUB_DMAMAP_USED) {
 490            /* If the map is FIXED, re-use is OK. */
 491            if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
 492                char name[MAXDEVNAME];
 493                vhdl = hub_dmamap->hdma_xtalk_info.xd_dev;
 494                printk(KERN_WARNING  "%s: hub_dmamap_list re-uses dmamap\n", vertex_to_name(vhdl, name, MAXDEVNAME));
 495            }
 496        } else {
 497                hub_dmamap->hdma_flags |= HUB_DMAMAP_USED;
 498        }
 499
 500        /* There isn't actually any DMA mapping hardware on the hub.  */
 501        return(palenlist);
 502}
 503
 504/*
 505 * Driver indicates that it has completed whatever DMA it may have started
 506 * after an earlier dmamap_addr or dmamap_list call.
 507 */
 508void
 509hub_dmamap_done(hub_dmamap_t hub_dmamap)        /* done with these mapping resources */
 510{
 511        vertex_hdl_t vhdl;
 512
 513        if (hub_dmamap->hdma_flags & HUB_DMAMAP_USED) {
 514                hub_dmamap->hdma_flags &= ~HUB_DMAMAP_USED;
 515        } else {
 516            /* If the map is FIXED, re-done is OK. */
 517            if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
 518                char name[MAXDEVNAME];
 519                vhdl = hub_dmamap->hdma_xtalk_info.xd_dev;
 520                printk(KERN_WARNING  "%s: hub_dmamap_done already done with dmamap\n", vertex_to_name(vhdl, name, MAXDEVNAME));
 521            }
 522        }
 523}
 524
 525/*
 526 * Translate a single system physical address into a crosstalk address.
 527 */
 528/* ARGSUSED */
 529iopaddr_t
 530hub_dmatrans_addr(      vertex_hdl_t dev,       /* translate for this device */
 531                        device_desc_t dev_desc, /* device descriptor */
 532                        paddr_t paddr,          /* system physical address */
 533                        size_t byte_count,      /* length */
 534                        unsigned flags)         /* defined in dma.h */
 535{
 536        return( (PHYS_TO_DMA(paddr)) );
 537}
 538
 539/*
 540 * Translate a list of IP27 addresses and lengths into a list of crosstalk 
 541 * addresses and lengths.  No actual hardware mapping takes place; the hub 
 542 * has no DMA mapping registers -- crosstalk addresses map directly.
 543 */
 544/* ARGSUSED */
 545alenlist_t
 546hub_dmatrans_list(      vertex_hdl_t dev,       /* translate for this device */
 547                        device_desc_t dev_desc, /* device descriptor */
 548                        alenlist_t palenlist,   /* system address/length list */
 549                        unsigned flags)         /* defined in dma.h */
 550{
 551        BUG();
 552        /* no translation needed */
 553        return(palenlist);
 554}
 555
 556/*ARGSUSED*/
 557void
 558hub_dmamap_drain(       hub_dmamap_t map)
 559{
 560    /* XXX- flush caches, if cache coherency WAR is needed */
 561}
 562
 563/*ARGSUSED*/
 564void
 565hub_dmaaddr_drain(      vertex_hdl_t vhdl,
 566                        paddr_t addr,
 567                        size_t bytes)
 568{
 569    /* XXX- flush caches, if cache coherency WAR is needed */
 570}
 571
 572/*ARGSUSED*/
 573void
 574hub_dmalist_drain(      vertex_hdl_t vhdl,
 575                        alenlist_t list)
 576{
 577    /* XXX- flush caches, if cache coherency WAR is needed */
 578}
 579
 580
 581int
 582hub_dma_enabled(vertex_hdl_t xconn_vhdl)
 583{
 584        return(0);
 585}
 586
 587int
 588hub_error_devenable(vertex_hdl_t xconn_vhdl, int devnum, int error_code)
 589{
 590        return(0);
 591}
 592
 593
 594/* CONFIGURATION MANAGEMENT */
 595
 596/*
 597 * Perform initializations that allow this hub to start crosstalk support.
 598 */
 599void
 600hub_provider_startup(vertex_hdl_t hubv)
 601{
 602        hub_pio_init(hubv);
 603        hub_intr_init(hubv);
 604}
 605
 606/*
 607 * Shutdown crosstalk support from a hub.
 608 */
 609void
 610hub_provider_shutdown(vertex_hdl_t hub)
 611{
 612        /* TBD */
 613        xtalk_provider_unregister(hub);
 614}
 615
 616/*
 617 * Check that an address is in the real small window widget 0 space
 618 * or else in the big window we're using to emulate small window 0
 619 * in the kernel.
 620 */
 621int
 622hub_check_is_widget0(void *addr)
 623{
 624        nasid_t nasid = NASID_GET(addr);
 625
 626        if (((__psunsigned_t)addr >= RAW_NODE_SWIN_BASE(nasid, 0)) &&
 627            ((__psunsigned_t)addr < RAW_NODE_SWIN_BASE(nasid, 1)))
 628                return 1;
 629        return 0;
 630}
 631
 632
 633/*
 634 * Check that two addresses use the same widget
 635 */
 636int
 637hub_check_window_equiv(void *addra, void *addrb)
 638{
 639        if (hub_check_is_widget0(addra) && hub_check_is_widget0(addrb))
 640                return 1;
 641
 642        /* XXX - Assume this is really a small window address */
 643        if (WIDGETID_GET((__psunsigned_t)addra) ==
 644            WIDGETID_GET((__psunsigned_t)addrb))
 645                return 1;
 646
 647        return 0;
 648}
 649
 650
 651/*
 652 * hub_setup_prb(nasid, prbnum, credits, conveyor)
 653 *
 654 *      Put a PRB into fire-and-forget mode if conveyor isn't set.  Otherwise,
 655 *      put it into conveyor belt mode with the specified number of credits.
 656 */
 657void
 658hub_setup_prb(nasid_t nasid, int prbnum, int credits, int conveyor)
 659{
 660        iprb_t prb;
 661        int prb_offset;
 662
 663        if (force_fire_and_forget && !ignore_conveyor_override)
 664            if (conveyor == HUB_PIO_CONVEYOR)
 665                conveyor = HUB_PIO_FIRE_N_FORGET;
 666
 667        /*
 668         * Get the current register value.
 669         */
 670        prb_offset = IIO_IOPRB(prbnum);
 671        prb.iprb_regval = REMOTE_HUB_L(nasid, prb_offset);
 672
 673        /*
 674         * Clear out some fields.
 675         */
 676        prb.iprb_ovflow = 1;
 677        prb.iprb_bnakctr = 0;
 678        prb.iprb_anakctr = 0;
 679
 680        /*
 681         * Enable or disable fire-and-forget mode.
 682         */
 683        prb.iprb_ff = ((conveyor == HUB_PIO_CONVEYOR) ? 0 : 1);
 684
 685        /*
 686         * Set the appropriate number of PIO cresits for the widget.
 687         */
 688        prb.iprb_xtalkctr = credits;
 689
 690        /*
 691         * Store the new value to the register.
 692         */
 693        REMOTE_HUB_S(nasid, prb_offset, prb.iprb_regval);
 694}
 695
 696/*
 697 * hub_set_piomode()
 698 *
 699 *      Put the hub into either "PIO conveyor belt" mode or "fire-and-forget"
 700 *      mode.  To do this, we have to make absolutely sure that no PIOs
 701 *      are in progress so we turn off access to all widgets for the duration
 702 *      of the function.
 703 * 
 704 * XXX - This code should really check what kind of widget we're talking
 705 * to.  Bridges can only handle three requests, but XG will do more.
 706 * How many can crossbow handle to widget 0?  We're assuming 1.
 707 *
 708 * XXX - There is a bug in the crossbow that link reset PIOs do not
 709 * return write responses.  The easiest solution to this problem is to
 710 * leave widget 0 (xbow) in fire-and-forget mode at all times.  This
 711 * only affects pio's to xbow registers, which should be rare.
 712 */
 713void
 714hub_set_piomode(nasid_t nasid, int conveyor)
 715{
 716        hubreg_t ii_iowa;
 717        int direct_connect;
 718        hubii_wcr_t ii_wcr;
 719        int prbnum;
 720
 721        ASSERT(NASID_TO_COMPACT_NODEID(nasid) != INVALID_CNODEID);
 722
 723        ii_iowa = REMOTE_HUB_L(nasid, IIO_OUTWIDGET_ACCESS);
 724        REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, 0);
 725
 726        ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid, IIO_WCR);
 727        direct_connect = ii_wcr.iwcr_dir_con;
 728
 729        if (direct_connect) {
 730                /* 
 731                 * Assume a bridge here.
 732                 */
 733                hub_setup_prb(nasid, 0, 3, conveyor);
 734        } else {
 735                /* 
 736                 * Assume a crossbow here.
 737                 */
 738                hub_setup_prb(nasid, 0, 1, conveyor);
 739        }
 740
 741        for (prbnum = HUB_WIDGET_ID_MIN; prbnum <= HUB_WIDGET_ID_MAX; prbnum++) {
 742                /*
 743                 * XXX - Here's where we should take the widget type into
 744                 * when account assigning credits.
 745                 */
 746                /* Always set the PRBs in fire-and-forget mode */
 747                hub_setup_prb(nasid, prbnum, 3, conveyor);
 748        }
 749
 750        REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa);
 751}
 752/* Interface to allow special drivers to set hub specific
 753 * device flags.
 754 * Return 0 on failure , 1 on success
 755 */
 756int
 757hub_widget_flags_set(nasid_t            nasid,
 758                     xwidgetnum_t       widget_num,
 759                     hub_widget_flags_t flags)
 760{
 761
 762        ASSERT((flags & HUB_WIDGET_FLAGS) == flags);
 763
 764        if (flags & HUB_PIO_CONVEYOR) {
 765                hub_setup_prb(nasid,widget_num,
 766                              3,HUB_PIO_CONVEYOR); /* set the PRB in conveyor 
 767                                                    * belt mode with 3 credits
 768                                                    */
 769        } else if (flags & HUB_PIO_FIRE_N_FORGET) {
 770                hub_setup_prb(nasid,widget_num,
 771                              3,HUB_PIO_FIRE_N_FORGET); /* set the PRB in fire
 772                                                         *  and forget mode 
 773                                                         */
 774        }
 775
 776        return 1;
 777}
 778
 779/*
 780 * A pointer to this structure hangs off of every hub hwgraph vertex.
 781 * The generic xtalk layer may indirect through it to get to this specific
 782 * crosstalk bus provider.
 783 */
 784xtalk_provider_t hub_provider = {
 785        (xtalk_piomap_alloc_f *)        hub_piomap_alloc,
 786        (xtalk_piomap_free_f *)         hub_piomap_free,
 787        (xtalk_piomap_addr_f *)         hub_piomap_addr,
 788        (xtalk_piomap_done_f *)         hub_piomap_done,
 789        (xtalk_piotrans_addr_f *)       hub_piotrans_addr,
 790
 791        (xtalk_dmamap_alloc_f *)        hub_dmamap_alloc,
 792        (xtalk_dmamap_free_f *)         hub_dmamap_free,
 793        (xtalk_dmamap_addr_f *)         hub_dmamap_addr,
 794        (xtalk_dmamap_list_f *)         hub_dmamap_list,
 795        (xtalk_dmamap_done_f *)         hub_dmamap_done,
 796        (xtalk_dmatrans_addr_f *)       hub_dmatrans_addr,
 797        (xtalk_dmatrans_list_f *)       hub_dmatrans_list,
 798        (xtalk_dmamap_drain_f *)        hub_dmamap_drain,
 799        (xtalk_dmaaddr_drain_f *)       hub_dmaaddr_drain,
 800        (xtalk_dmalist_drain_f *)       hub_dmalist_drain,
 801
 802        (xtalk_intr_alloc_f *)          hub_intr_alloc,
 803        (xtalk_intr_alloc_f *)          hub_intr_alloc_nothd,
 804        (xtalk_intr_free_f *)           hub_intr_free,
 805        (xtalk_intr_connect_f *)        hub_intr_connect,
 806        (xtalk_intr_disconnect_f *)     hub_intr_disconnect,
 807        (xtalk_provider_startup_f *)    hub_provider_startup,
 808        (xtalk_provider_shutdown_f *)   hub_provider_shutdown,
 809};
 810
 811/*
 812 * per_ice_init
 813 *
 814 *      This code is executed once for each Ice chip.
 815 */
 816void
 817per_ice_init(cnodeid_t cnode)
 818{
 819
 820        /* Initialize error interrupts for this ice. */
 821        printk("per_ice_init: We need to init ice here ....!\n");
 822        /* ice_error_init(cnode); */
 823
 824}
 825/*
 826 * per_hub_init
 827 *
 828 *      This code is executed once for each Hub chip.
 829 */
 830void
 831per_hub_init(cnodeid_t cnode)
 832{
 833        nasid_t         nasid;
 834        nodepda_t       *npdap;
 835        ii_icmr_u_t     ii_icmr;
 836        ii_ibcr_u_t     ii_ibcr;
 837        ii_ilcsr_u_t    ii_ilcsr;
 838
 839        nasid = COMPACT_TO_NASID_NODEID(cnode);
 840
 841        ASSERT(nasid != INVALID_NASID);
 842        ASSERT(NASID_TO_COMPACT_NODEID(nasid) == cnode);
 843
 844        npdap = NODEPDA(cnode);
 845
 846        /* Disable the request and reply errors. */
 847        REMOTE_HUB_S(nasid, IIO_IWEIM, 0xC000);
 848
 849        /*
 850         * Set the total number of CRBs that can be used.
 851         */
 852        ii_icmr.ii_icmr_regval= 0x0;
 853        ii_icmr.ii_icmr_fld_s.i_c_cnt = 0xf;
 854        if (enable_shub_wars_1_1() ) {
 855                // Set bit one of ICMR to prevent II from sending interrupt for II bug.
 856                ii_icmr.ii_icmr_regval |= 0x1;
 857        }
 858        REMOTE_HUB_S(nasid, IIO_ICMR, ii_icmr.ii_icmr_regval);
 859
 860        /*
 861         * Set the number of CRBs that both of the BTEs combined
 862         * can use minus 1.
 863         */
 864        ii_ibcr.ii_ibcr_regval= 0x0;
 865        ii_ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
 866        if (ii_ilcsr.ii_ilcsr_fld_s.i_llp_stat & LNK_STAT_WORKING) {
 867            ii_ibcr.ii_ibcr_fld_s.i_count = 0x8;
 868        } else {
 869            /*
 870             * if the LLP is down, there is no attached I/O, so
 871            * give BTE all the CRBs.
 872            */
 873            ii_ibcr.ii_ibcr_fld_s.i_count = 0x14;
 874        }
 875        REMOTE_HUB_S(nasid, IIO_IBCR, ii_ibcr.ii_ibcr_regval);
 876
 877        /*
 878         * Set CRB timeout to be 10ms.
 879         */
 880        REMOTE_HUB_S(nasid, IIO_ICTP, 0xffffff );
 881        REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);
 882
 883        /* Initialize error interrupts for this hub. */
 884        hub_error_init(cnode);
 885}
 886
 887
 888
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.