linux/drivers/char/rio/riotable.c
<<
>>
Prefs
   1/*
   2** -----------------------------------------------------------------------------
   3**
   4**  Perle Specialix driver for Linux
   5**  Ported from existing RIO Driver for SCO sources.
   6 *
   7 *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
   8 *
   9 *      This program is free software; you can redistribute it and/or modify
  10 *      it under the terms of the GNU General Public License as published by
  11 *      the Free Software Foundation; either version 2 of the License, or
  12 *      (at your option) any later version.
  13 *
  14 *      This program is distributed in the hope that it will be useful,
  15 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 *      GNU General Public License for more details.
  18 *
  19 *      You should have received a copy of the GNU General Public License
  20 *      along with this program; if not, write to the Free Software
  21 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22**
  23**      Module          : riotable.c
  24**      SID             : 1.2
  25**      Last Modified   : 11/6/98 10:33:47
  26**      Retrieved       : 11/6/98 10:33:50
  27**
  28**  ident @(#)riotable.c        1.2
  29**
  30** -----------------------------------------------------------------------------
  31*/
  32
  33#include <linux/module.h>
  34#include <linux/slab.h>
  35#include <linux/errno.h>
  36#include <linux/interrupt.h>
  37#include <linux/string.h>
  38
  39#include <asm/io.h>
  40#include <asm/system.h>
  41#include <asm/string.h>
  42#include <asm/uaccess.h>
  43
  44#include <linux/termios.h>
  45#include <linux/serial.h>
  46
  47#include <linux/generic_serial.h>
  48
  49
  50#include "linux_compat.h"
  51#include "rio_linux.h"
  52#include "pkt.h"
  53#include "daemon.h"
  54#include "rio.h"
  55#include "riospace.h"
  56#include "cmdpkt.h"
  57#include "map.h"
  58#include "rup.h"
  59#include "port.h"
  60#include "riodrvr.h"
  61#include "rioinfo.h"
  62#include "func.h"
  63#include "errors.h"
  64#include "pci.h"
  65
  66#include "parmmap.h"
  67#include "unixrup.h"
  68#include "board.h"
  69#include "host.h"
  70#include "phb.h"
  71#include "link.h"
  72#include "cmdblk.h"
  73#include "route.h"
  74#include "cirrus.h"
  75#include "rioioctl.h"
  76#include "param.h"
  77#include "protsts.h"
  78
  79/*
  80** A configuration table has been loaded. It is now up to us
  81** to sort it out and use the information contained therein.
  82*/
  83int RIONewTable(struct rio_info *p)
  84{
  85        int Host, Host1, Host2, NameIsUnique, Entry, SubEnt;
  86        struct Map *MapP;
  87        struct Map *HostMapP;
  88        struct Host *HostP;
  89
  90        char *cptr;
  91
  92        /*
  93         ** We have been sent a new table to install. We need to break
  94         ** it down into little bits and spread it around a bit to see
  95         ** what we have got.
  96         */
  97        /*
  98         ** Things to check:
  99         ** (things marked 'xx' aren't checked any more!)
 100         ** (1) That there are no booted Hosts/RTAs out there.
 101         ** (2) That the names are properly formed
 102         ** (3) That blank entries really are.
 103         ** xx (4)      That hosts mentioned in the table actually exist. xx
 104         ** (5) That the IDs are unique (per host).
 105         ** (6) That host IDs are zero
 106         ** (7) That port numbers are valid
 107         ** (8) That port numbers aren't duplicated
 108         ** (9) That names aren't duplicated
 109         ** xx (10) That hosts that actually exist are mentioned in the table. xx
 110         */
 111        rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(1)\n");
 112        if (p->RIOSystemUp) {   /* (1) */
 113                p->RIOError.Error = HOST_HAS_ALREADY_BEEN_BOOTED;
 114                return -EBUSY;
 115        }
 116
 117        p->RIOError.Error = NOTHING_WRONG_AT_ALL;
 118        p->RIOError.Entry = -1;
 119        p->RIOError.Other = -1;
 120
 121        for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
 122                MapP = &p->RIOConnectTable[Entry];
 123                if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) {
 124                        rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(2)\n");
 125                        cptr = MapP->Name;      /* (2) */
 126                        cptr[MAX_NAME_LEN - 1] = '\0';
 127                        if (cptr[0] == '\0') {
 128                                memcpy(MapP->Name, MapP->RtaUniqueNum ? "RTA    NN" : "HOST NN", 8);
 129                                MapP->Name[5] = '0' + Entry / 10;
 130                                MapP->Name[6] = '0' + Entry % 10;
 131                        }
 132                        while (*cptr) {
 133                                if (*cptr < ' ' || *cptr > '~') {
 134                                        p->RIOError.Error = BAD_CHARACTER_IN_NAME;
 135                                        p->RIOError.Entry = Entry;
 136                                        return -ENXIO;
 137                                }
 138                                cptr++;
 139                        }
 140                }
 141
 142                /*
 143                 ** If the entry saved was a tentative entry then just forget
 144                 ** about it.
 145                 */
 146                if (MapP->Flags & SLOT_TENTATIVE) {
 147                        MapP->HostUniqueNum = 0;
 148                        MapP->RtaUniqueNum = 0;
 149                        continue;
 150                }
 151
 152                rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(3)\n");
 153                if (!MapP->RtaUniqueNum && !MapP->HostUniqueNum) {      /* (3) */
 154                        if (MapP->ID || MapP->SysPort || MapP->Flags) {
 155                                rio_dprintk(RIO_DEBUG_TABLE, "%s pretending to be empty but isn't\n", MapP->Name);
 156                                p->RIOError.Error = TABLE_ENTRY_ISNT_PROPERLY_NULL;
 157                                p->RIOError.Entry = Entry;
 158                                return -ENXIO;
 159                        }
 160                        rio_dprintk(RIO_DEBUG_TABLE, "!RIO: Daemon: test (3) passes\n");
 161                        continue;
 162                }
 163
 164                rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(4)\n");
 165                for (Host = 0; Host < p->RIONumHosts; Host++) { /* (4) */
 166                        if (p->RIOHosts[Host].UniqueNum == MapP->HostUniqueNum) {
 167                                HostP = &p->RIOHosts[Host];
 168                                /*
 169                                 ** having done the lookup, we don't really want to do
 170                                 ** it again, so hang the host number in a safe place
 171                                 */
 172                                MapP->Topology[0].Unit = Host;
 173                                break;
 174                        }
 175                }
 176
 177                if (Host >= p->RIONumHosts) {
 178                        rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has unknown host unique number 0x%x\n", MapP->Name, MapP->HostUniqueNum);
 179                        MapP->HostUniqueNum = 0;
 180                        /* MapP->RtaUniqueNum   = 0; */
 181                        /* MapP->ID                     = 0; */
 182                        /* MapP->Flags           = 0; */
 183                        /* MapP->SysPort                 = 0; */
 184                        /* MapP->Name[0]                 = 0; */
 185                        continue;
 186                }
 187
 188                rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(5)\n");
 189                if (MapP->RtaUniqueNum) {       /* (5) */
 190                        if (!MapP->ID) {
 191                                rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an ID of zero!\n", MapP->Name);
 192                                p->RIOError.Error = ZERO_RTA_ID;
 193                                p->RIOError.Entry = Entry;
 194                                return -ENXIO;
 195                        }
 196                        if (MapP->ID > MAX_RUP) {
 197                                rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an invalid ID %d\n", MapP->Name, MapP->ID);
 198                                p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
 199                                p->RIOError.Entry = Entry;
 200                                return -ENXIO;
 201                        }
 202                        for (SubEnt = 0; SubEnt < Entry; SubEnt++) {
 203                                if (MapP->HostUniqueNum == p->RIOConnectTable[SubEnt].HostUniqueNum && MapP->ID == p->RIOConnectTable[SubEnt].ID) {
 204                                        rio_dprintk(RIO_DEBUG_TABLE, "Dupl. ID number allocated to RTA %s and RTA %s\n", MapP->Name, p->RIOConnectTable[SubEnt].Name);
 205                                        p->RIOError.Error = DUPLICATED_RTA_ID;
 206                                        p->RIOError.Entry = Entry;
 207                                        p->RIOError.Other = SubEnt;
 208                                        return -ENXIO;
 209                                }
 210                                /*
 211                                 ** If the RtaUniqueNum is the same, it may be looking at both
 212                                 ** entries for a 16 port RTA, so check the ids
 213                                 */
 214                                if ((MapP->RtaUniqueNum == p->RIOConnectTable[SubEnt].RtaUniqueNum)
 215                                    && (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) {
 216                                        rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", MapP->Name);
 217                                        rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", p->RIOConnectTable[SubEnt].Name);
 218                                        p->RIOError.Error = DUPLICATE_UNIQUE_NUMBER;
 219                                        p->RIOError.Entry = Entry;
 220                                        p->RIOError.Other = SubEnt;
 221                                        return -ENXIO;
 222                                }
 223                        }
 224                        rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7a)\n");
 225                        /* (7a) */
 226                        if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) {
 227                                rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d-RTA %s is not a multiple of %d!\n", (int) MapP->SysPort, MapP->Name, PORTS_PER_RTA);
 228                                p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
 229                                p->RIOError.Entry = Entry;
 230                                return -ENXIO;
 231                        }
 232                        rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7b)\n");
 233                        /* (7b) */
 234                        if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) {
 235                                rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d for RTA %s is too big\n", (int) MapP->SysPort, MapP->Name);
 236                                p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
 237                                p->RIOError.Entry = Entry;
 238                                return -ENXIO;
 239                        }
 240                        for (SubEnt = 0; SubEnt < Entry; SubEnt++) {
 241                                if (p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT)
 242                                        continue;
 243                                if (p->RIOConnectTable[SubEnt].RtaUniqueNum) {
 244                                        rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(8)\n");
 245                                        /* (8) */
 246                                        if ((MapP->SysPort != NO_PORT) && (MapP->SysPort == p->RIOConnectTable[SubEnt].SysPort)) {
 247                                                rio_dprintk(RIO_DEBUG_TABLE, "RTA %s:same TTY port # as RTA %s (%d)\n", MapP->Name, p->RIOConnectTable[SubEnt].Name, (int) MapP->SysPort);
 248                                                p->RIOError.Error = TTY_NUMBER_IN_USE;
 249                                                p->RIOError.Entry = Entry;
 250                                                p->RIOError.Other = SubEnt;
 251                                                return -ENXIO;
 252                                        }
 253                                        rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(9)\n");
 254                                        if (strcmp(MapP->Name, p->RIOConnectTable[SubEnt].Name) == 0 && !(MapP->Flags & RTA16_SECOND_SLOT)) {   /* (9) */
 255                                                rio_dprintk(RIO_DEBUG_TABLE, "RTA name %s used twice\n", MapP->Name);
 256                                                p->RIOError.Error = NAME_USED_TWICE;
 257                                                p->RIOError.Entry = Entry;
 258                                                p->RIOError.Other = SubEnt;
 259                                                return -ENXIO;
 260                                        }
 261                                }
 262                        }
 263                } else {        /* (6) */
 264                        rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(6)\n");
 265                        if (MapP->ID) {
 266                                rio_dprintk(RIO_DEBUG_TABLE, "RIO:HOST %s has been allocated ID that isn't zero!\n", MapP->Name);
 267                                p->RIOError.Error = HOST_ID_NOT_ZERO;
 268                                p->RIOError.Entry = Entry;
 269                                return -ENXIO;
 270                        }
 271                        if (MapP->SysPort != NO_PORT) {
 272                                rio_dprintk(RIO_DEBUG_TABLE, "RIO: HOST %s has been allocated port numbers!\n", MapP->Name);
 273                                p->RIOError.Error = HOST_SYSPORT_BAD;
 274                                p->RIOError.Entry = Entry;
 275                                return -ENXIO;
 276                        }
 277                }
 278        }
 279
 280        /*
 281         ** wow! if we get here then it's a goody!
 282         */
 283
 284        /*
 285         ** Zero the (old) entries for each host...
 286         */
 287        for (Host = 0; Host < RIO_HOSTS; Host++) {
 288                for (Entry = 0; Entry < MAX_RUP; Entry++) {
 289                        memset(&p->RIOHosts[Host].Mapping[Entry], 0, sizeof(struct Map));
 290                }
 291                memset(&p->RIOHosts[Host].Name[0], 0, sizeof(p->RIOHosts[Host].Name));
 292        }
 293
 294        /*
 295         ** Copy in the new table entries
 296         */
 297        for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
 298                rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: Copy table for Host entry %d\n", Entry);
 299                MapP = &p->RIOConnectTable[Entry];
 300
 301                /*
 302                 ** Now, if it is an empty slot ignore it!
 303                 */
 304                if (MapP->HostUniqueNum == 0)
 305                        continue;
 306
 307                /*
 308                 ** we saved the host number earlier, so grab it back
 309                 */
 310                HostP = &p->RIOHosts[MapP->Topology[0].Unit];
 311
 312                /*
 313                 ** If it is a host, then we only need to fill in the name field.
 314                 */
 315                if (MapP->ID == 0) {
 316                        rio_dprintk(RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name);
 317                        memcpy(HostP->Name, MapP->Name, MAX_NAME_LEN);
 318                        continue;
 319                }
 320
 321                /*
 322                 ** Its an RTA entry, so fill in the host mapping entries for it
 323                 ** and the port mapping entries. Notice that entry zero is for
 324                 ** ID one.
 325                 */
 326                HostMapP = &HostP->Mapping[MapP->ID - 1];
 327
 328                if (MapP->Flags & SLOT_IN_USE) {
 329                        rio_dprintk(RIO_DEBUG_TABLE, "Rta entry found. Name %s\n", MapP->Name);
 330                        /*
 331                         ** structure assign, then sort out the bits we shouldn't have done
 332                         */
 333                        *HostMapP = *MapP;
 334
 335                        HostMapP->Flags = SLOT_IN_USE;
 336                        if (MapP->Flags & RTA16_SECOND_SLOT)
 337                                HostMapP->Flags |= RTA16_SECOND_SLOT;
 338
 339                        RIOReMapPorts(p, HostP, HostMapP);
 340                } else {
 341                        rio_dprintk(RIO_DEBUG_TABLE, "TENTATIVE Rta entry found. Name %s\n", MapP->Name);
 342                }
 343        }
 344
 345        for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
 346                p->RIOSavedTable[Entry] = p->RIOConnectTable[Entry];
 347        }
 348
 349        for (Host = 0; Host < p->RIONumHosts; Host++) {
 350                for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) {
 351                        p->RIOHosts[Host].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
 352                        p->RIOHosts[Host].Topology[SubEnt].Link = NO_LINK;
 353                }
 354                for (Entry = 0; Entry < MAX_RUP; Entry++) {
 355                        for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) {
 356                                p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
 357                                p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Link = NO_LINK;
 358                        }
 359                }
 360                if (!p->RIOHosts[Host].Name[0]) {
 361                        memcpy(p->RIOHosts[Host].Name, "HOST 1", 7);
 362                        p->RIOHosts[Host].Name[5] += Host;
 363                }
 364                /*
 365                 ** Check that default name assigned is unique.
 366                 */
 367                Host1 = Host;
 368                NameIsUnique = 0;
 369                while (!NameIsUnique) {
 370                        NameIsUnique = 1;
 371                        for (Host2 = 0; Host2 < p->RIONumHosts; Host2++) {
 372                                if (Host2 == Host)
 373                                        continue;
 374                                if (strcmp(p->RIOHosts[Host].Name, p->RIOHosts[Host2].Name)
 375                                    == 0) {
 376                                        NameIsUnique = 0;
 377                                        Host1++;
 378                                        if (Host1 >= p->RIONumHosts)
 379                                                Host1 = 0;
 380                                        p->RIOHosts[Host].Name[5] = '1' + Host1;
 381                                }
 382                        }
 383                }
 384                /*
 385                 ** Rename host if name already used.
 386                 */
 387                if (Host1 != Host) {
 388                        rio_dprintk(RIO_DEBUG_TABLE, "Default name %s already used\n", p->RIOHosts[Host].Name);
 389                        memcpy(p->RIOHosts[Host].Name, "HOST 1", 7);
 390                        p->RIOHosts[Host].Name[5] += Host1;
 391                }
 392                rio_dprintk(RIO_DEBUG_TABLE, "Assigning default name %s\n", p->RIOHosts[Host].Name);
 393        }
 394        return 0;
 395}
 396
 397/*
 398** User process needs the config table - build it from first
 399** principles.
 400**
 401*       FIXME: SMP locking
 402*/
 403int RIOApel(struct rio_info *p)
 404{
 405        int Host;
 406        int link;
 407        int Rup;
 408        int Next = 0;
 409        struct Map *MapP;
 410        struct Host *HostP;
 411        unsigned long flags;
 412
 413        rio_dprintk(RIO_DEBUG_TABLE, "Generating a table to return to config.rio\n");
 414
 415        memset(&p->RIOConnectTable[0], 0, sizeof(struct Map) * TOTAL_MAP_ENTRIES);
 416
 417        for (Host = 0; Host < RIO_HOSTS; Host++) {
 418                rio_dprintk(RIO_DEBUG_TABLE, "Processing host %d\n", Host);
 419                HostP = &p->RIOHosts[Host];
 420                rio_spin_lock_irqsave(&HostP->HostLock, flags);
 421
 422                MapP = &p->RIOConnectTable[Next++];
 423                MapP->HostUniqueNum = HostP->UniqueNum;
 424                if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
 425                        rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
 426                        continue;
 427                }
 428                MapP->RtaUniqueNum = 0;
 429                MapP->ID = 0;
 430                MapP->Flags = SLOT_IN_USE;
 431                MapP->SysPort = NO_PORT;
 432                for (link = 0; link < LINKS_PER_UNIT; link++)
 433                        MapP->Topology[link] = HostP->Topology[link];
 434                memcpy(MapP->Name, HostP->Name, MAX_NAME_LEN);
 435                for (Rup = 0; Rup < MAX_RUP; Rup++) {
 436                        if (HostP->Mapping[Rup].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) {
 437                                p->RIOConnectTable[Next] = HostP->Mapping[Rup];
 438                                if (HostP->Mapping[Rup].Flags & SLOT_IN_USE)
 439                                        p->RIOConnectTable[Next].Flags |= SLOT_IN_USE;
 440                                if (HostP->Mapping[Rup].Flags & SLOT_TENTATIVE)
 441                                        p->RIOConnectTable[Next].Flags |= SLOT_TENTATIVE;
 442                                if (HostP->Mapping[Rup].Flags & RTA16_SECOND_SLOT)
 443                                        p->RIOConnectTable[Next].Flags |= RTA16_SECOND_SLOT;
 444                                Next++;
 445                        }
 446                }
 447                rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
 448        }
 449        return 0;
 450}
 451
 452/*
 453** config.rio has taken a dislike to one of the gross maps entries.
 454** if the entry is suitably inactive, then we can gob on it and remove
 455** it from the table.
 456*/
 457int RIODeleteRta(struct rio_info *p, struct Map *MapP)
 458{
 459        int host, entry, port, link;
 460        int SysPort;
 461        struct Host *HostP;
 462        struct Map *HostMapP;
 463        struct Port *PortP;
 464        int work_done = 0;
 465        unsigned long lock_flags, sem_flags;
 466
 467        rio_dprintk(RIO_DEBUG_TABLE, "Delete entry on host %x, rta %x\n", MapP->HostUniqueNum, MapP->RtaUniqueNum);
 468
 469        for (host = 0; host < p->RIONumHosts; host++) {
 470                HostP = &p->RIOHosts[host];
 471
 472                rio_spin_lock_irqsave(&HostP->HostLock, lock_flags);
 473
 474                if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
 475                        rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
 476                        continue;
 477                }
 478
 479                for (entry = 0; entry < MAX_RUP; entry++) {
 480                        if (MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum) {
 481                                HostMapP = &HostP->Mapping[entry];
 482                                rio_dprintk(RIO_DEBUG_TABLE, "Found entry offset %d on host %s\n", entry, HostP->Name);
 483
 484                                /*
 485                                 ** Check all four links of the unit are disconnected
 486                                 */
 487                                for (link = 0; link < LINKS_PER_UNIT; link++) {
 488                                        if (HostMapP->Topology[link].Unit != ROUTE_DISCONNECT) {
 489                                                rio_dprintk(RIO_DEBUG_TABLE, "Entry is in use and cannot be deleted!\n");
 490                                                p->RIOError.Error = UNIT_IS_IN_USE;
 491                                                rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
 492                                                return -EBUSY;
 493                                        }
 494                                }
 495                                /*
 496                                 ** Slot has been allocated, BUT not booted/routed/
 497                                 ** connected/selected or anything else-ed
 498                                 */
 499                                SysPort = HostMapP->SysPort;
 500
 501                                if (SysPort != NO_PORT) {
 502                                        for (port = SysPort; port < SysPort + PORTS_PER_RTA; port++) {
 503                                                PortP = p->RIOPortp[port];
 504                                                rio_dprintk(RIO_DEBUG_TABLE, "Unmap port\n");
 505
 506                                                rio_spin_lock_irqsave(&PortP->portSem, sem_flags);
 507
 508                                                PortP->Mapped = 0;
 509
 510                                                if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
 511
 512                                                        rio_dprintk(RIO_DEBUG_TABLE, "Gob on port\n");
 513                                                        PortP->TxBufferIn = PortP->TxBufferOut = 0;
 514                                                        /* What should I do 
 515                                                           wakeup( &PortP->TxBufferIn );
 516                                                           wakeup( &PortP->TxBufferOut);
 517                                                         */
 518                                                        PortP->InUse = NOT_INUSE;
 519                                                        /* What should I do 
 520                                                           wakeup( &PortP->InUse );
 521                                                           signal(PortP->TtyP->t_pgrp,SIGKILL);
 522                                                           ttyflush(PortP->TtyP,(FREAD|FWRITE));
 523                                                         */
 524                                                        PortP->State |= RIO_CLOSING | RIO_DELETED;
 525                                                }
 526
 527                                                /*
 528                                                 ** For the second slot of a 16 port RTA, the
 529                                                 ** driver needs to reset the changes made to
 530                                                 ** the phb to port mappings in RIORouteRup.
 531                                                 */
 532                                                if (PortP->SecondBlock) {
 533                                                        u16 dest_unit = HostMapP->ID;
 534                                                        u16 dest_port = port - SysPort;
 535                                                        u16 __iomem *TxPktP;
 536                                                        struct PKT __iomem *Pkt;
 537
 538                                                        for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
 539                                                                /*
 540                                                                 ** *TxPktP is the pointer to the
 541                                                                 ** transmit packet on the host card.
 542                                                                 ** This needs to be translated into
 543                                                                 ** a 32 bit pointer so it can be
 544                                                                 ** accessed from the driver.
 545                                                                 */
 546                                                                Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&*TxPktP));
 547                                                                rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", readw(TxPktP), readb(&Pkt->dest_unit), readb(&Pkt->dest_port), dest_unit, dest_port);
 548                                                                writew(dest_unit, &Pkt->dest_unit);
 549                                                                writew(dest_port, &Pkt->dest_port);
 550                                                        }
 551                                                        rio_dprintk(RIO_DEBUG_TABLE, "Port %d phb destination: Old %x:%x New %x:%x\n", port, readb(&PortP->PhbP->destination) & 0xff, (readb(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port);
 552                                                        writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination);
 553                                                }
 554                                                rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags);
 555                                        }
 556                                }
 557                                rio_dprintk(RIO_DEBUG_TABLE, "Entry nulled.\n");
 558                                memset(HostMapP, 0, sizeof(struct Map));
 559                                work_done++;
 560                        }
 561                }
 562                rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
 563        }
 564
 565        /* XXXXX lock me up */
 566        for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
 567                if (p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {
 568                        memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map));
 569                        work_done++;
 570                }
 571                if (p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {
 572                        memset(&p->RIOConnectTable[entry], 0, sizeof(struct Map));
 573                        work_done++;
 574                }
 575        }
 576        if (work_done)
 577                return 0;
 578
 579        rio_dprintk(RIO_DEBUG_TABLE, "Couldn't find entry to be deleted\n");
 580        p->RIOError.Error = COULDNT_FIND_ENTRY;
 581        return -ENXIO;
 582}
 583
 584int RIOAssignRta(struct rio_info *p, struct Map *MapP)
 585{
 586        int host;
 587        struct Map *HostMapP;
 588        char *sptr;
 589        int link;
 590
 591
 592        rio_dprintk(RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);
 593
 594        if ((MapP->ID != (u16) - 1) && ((int) MapP->ID < (int) 1 || (int) MapP->ID > MAX_RUP)) {
 595                rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
 596                p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
 597                return -EINVAL;
 598        }
 599        if (MapP->RtaUniqueNum == 0) {
 600                rio_dprintk(RIO_DEBUG_TABLE, "Rta Unique number zero!\n");
 601                p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO;
 602                return -EINVAL;
 603        }
 604        if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) {
 605                rio_dprintk(RIO_DEBUG_TABLE, "Port %d not multiple of %d!\n", (int) MapP->SysPort, PORTS_PER_RTA);
 606                p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
 607                return -EINVAL;
 608        }
 609        if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) {
 610                rio_dprintk(RIO_DEBUG_TABLE, "Port %d not valid!\n", (int) MapP->SysPort);
 611                p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
 612                return -EINVAL;
 613        }
 614
 615        /*
 616         ** Copy the name across to the map entry.
 617         */
 618        MapP->Name[MAX_NAME_LEN - 1] = '\0';
 619        sptr = MapP->Name;
 620        while (*sptr) {
 621                if (*sptr < ' ' || *sptr > '~') {
 622                        rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
 623                        p->RIOError.Error = BAD_CHARACTER_IN_NAME;
 624                        return -EINVAL;
 625                }
 626                sptr++;
 627        }
 628
 629        for (host = 0; host < p->RIONumHosts; host++) {
 630                if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {
 631                        if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {
 632                                p->RIOError.Error = HOST_NOT_RUNNING;
 633                                return -ENXIO;
 634                        }
 635
 636                        /*
 637                         ** Now we have a host we need to allocate an ID
 638                         ** if the entry does not already have one.
 639                         */
 640                        if (MapP->ID == (u16) - 1) {
 641                                int nNewID;
 642
 643                                rio_dprintk(RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n", MapP->Name);
 644                                /*
 645                                 ** The idea here is to allow RTA's to be assigned
 646                                 ** before they actually appear on the network.
 647                                 ** This allows the addition of RTA's without having
 648                                 ** to plug them in.
 649                                 ** What we do is:
 650                                 **  - Find a free ID and allocate it to the RTA.
 651                                 **  - If this map entry is the second half of a
 652                                 **    16 port entry then find the other half and
 653                                 **    make sure the 2 cross reference each other.
 654                                 */
 655                                if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0) {
 656                                        p->RIOError.Error = COULDNT_FIND_ENTRY;
 657                                        return -EBUSY;
 658                                }
 659                                MapP->ID = (u16) nNewID + 1;
 660                                rio_dprintk(RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID);
 661                                HostMapP = &p->RIOHosts[host].Mapping[nNewID];
 662                                HostMapP->RtaUniqueNum = MapP->RtaUniqueNum;
 663                                HostMapP->HostUniqueNum = MapP->HostUniqueNum;
 664                                HostMapP->ID = MapP->ID;
 665                                for (link = 0; link < LINKS_PER_UNIT; link++) {
 666                                        HostMapP->Topology[link].Unit = ROUTE_DISCONNECT;
 667                                        HostMapP->Topology[link].Link = NO_LINK;
 668                                }
 669                                if (MapP->Flags & RTA16_SECOND_SLOT) {
 670                                        int unit;
 671
 672                                        for (unit = 0; unit < MAX_RUP; unit++)
 673                                                if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum == MapP->RtaUniqueNum)
 674                                                        break;
 675                                        if (unit == MAX_RUP) {
 676                                                p->RIOError.Error = COULDNT_FIND_ENTRY;
 677                                                return -EBUSY;
 678                                        }
 679                                        HostMapP->Flags |= RTA16_SECOND_SLOT;
 680                                        HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID;
 681                                        p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID;
 682                                        rio_dprintk(RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n", MapP->ID, p->RIOHosts[host].Mapping[unit].ID);
 683                                }
 684                        }
 685
 686                        HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];
 687
 688                        if (HostMapP->Flags & SLOT_IN_USE) {
 689                                rio_dprintk(RIO_DEBUG_TABLE, "Map table slot for ID %d is already in use.\n", MapP->ID);
 690                                p->RIOError.Error = ID_ALREADY_IN_USE;
 691                                return -EBUSY;
 692                        }
 693
 694                        /*
 695                         ** Assign the sys ports and the name, and mark the slot as
 696                         ** being in use.
 697                         */
 698                        HostMapP->SysPort = MapP->SysPort;
 699                        if ((MapP->Flags & RTA16_SECOND_SLOT) == 0)
 700                                memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN);
 701                        HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED;
 702#ifdef NEED_TO_FIX
 703                        RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID - 1]);
 704#endif
 705                        if (MapP->Flags & RTA16_SECOND_SLOT)
 706                                HostMapP->Flags |= RTA16_SECOND_SLOT;
 707
 708                        RIOReMapPorts(p, &p->RIOHosts[host], HostMapP);
 709                        /*
 710                         ** Adjust 2nd block of 8 phbs
 711                         */
 712                        if (MapP->Flags & RTA16_SECOND_SLOT)
 713                                RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1);
 714
 715                        if (HostMapP->SysPort != NO_PORT) {
 716                                if (HostMapP->SysPort < p->RIOFirstPortsBooted)
 717                                        p->RIOFirstPortsBooted = HostMapP->SysPort;
 718                                if (HostMapP->SysPort > p->RIOLastPortsBooted)
 719                                        p->RIOLastPortsBooted = HostMapP->SysPort;
 720                        }
 721                        if (MapP->Flags & RTA16_SECOND_SLOT)
 722                                rio_dprintk(RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n", p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name);
 723                        else
 724                                rio_dprintk(RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name);
 725                        return 0;
 726                }
 727        }
 728        p->RIOError.Error = UNKNOWN_HOST_NUMBER;
 729        rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
 730        return -ENXIO;
 731}
 732
 733
 734int RIOReMapPorts(struct rio_info *p, struct Host *HostP, struct Map *HostMapP)
 735{
 736        struct Port *PortP;
 737        unsigned int SubEnt;
 738        unsigned int HostPort;
 739        unsigned int SysPort;
 740        u16 RtaType;
 741        unsigned long flags;
 742
 743        rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int) HostMapP->SysPort, HostMapP->ID);
 744
 745        /*
 746         ** We need to tell the UnixRups which sysport the rup corresponds to
 747         */
 748        HostP->UnixRups[HostMapP->ID - 1].BaseSysPort = HostMapP->SysPort;
 749
 750        if (HostMapP->SysPort == NO_PORT)
 751                return (0);
 752
 753        RtaType = GetUnitType(HostMapP->RtaUniqueNum);
 754        rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d-%d\n", (int) HostMapP->SysPort, (int) HostMapP->SysPort + PORTS_PER_RTA - 1);
 755
 756        /*
 757         ** now map each of its eight ports
 758         */
 759        for (SubEnt = 0; SubEnt < PORTS_PER_RTA; SubEnt++) {
 760                rio_dprintk(RIO_DEBUG_TABLE, "subent = %d, HostMapP->SysPort = %d\n", SubEnt, (int) HostMapP->SysPort);
 761                SysPort = HostMapP->SysPort + SubEnt;   /* portnumber within system */
 762                /* portnumber on host */
 763
 764                HostPort = (HostMapP->ID - 1) * PORTS_PER_RTA + SubEnt;
 765
 766                rio_dprintk(RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp);
 767                PortP = p->RIOPortp[SysPort];
 768                rio_dprintk(RIO_DEBUG_TABLE, "Map port\n");
 769
 770                /*
 771                 ** Point at all the real neat data structures
 772                 */
 773                rio_spin_lock_irqsave(&PortP->portSem, flags);
 774                PortP->HostP = HostP;
 775                PortP->Caddr = HostP->Caddr;
 776
 777                /*
 778                 ** The PhbP cannot be filled in yet
 779                 ** unless the host has been booted
 780                 */
 781                if ((HostP->Flags & RUN_STATE) == RC_RUNNING) {
 782                        struct PHB __iomem *PhbP = PortP->PhbP = &HostP->PhbP[HostPort];
 783                        PortP->TxAdd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_add));
 784                        PortP->TxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_start));
 785                        PortP->TxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_end));
 786                        PortP->RxRemove = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_remove));
 787                        PortP->RxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_start));
 788                        PortP->RxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_end));
 789                } else
 790                        PortP->PhbP = NULL;
 791
 792                /*
 793                 ** port related flags
 794                 */
 795                PortP->HostPort = HostPort;
 796                /*
 797                 ** For each part of a 16 port RTA, RupNum is ID - 1.
 798                 */
 799                PortP->RupNum = HostMapP->ID - 1;
 800                if (HostMapP->Flags & RTA16_SECOND_SLOT) {
 801                        PortP->ID2 = HostMapP->ID2 - 1;
 802                        PortP->SecondBlock = 1;
 803                } else {
 804                        PortP->ID2 = 0;
 805                        PortP->SecondBlock = 0;
 806                }
 807                PortP->RtaUniqueNum = HostMapP->RtaUniqueNum;
 808
 809                /*
 810                 ** If the port was already mapped then thats all we need to do.
 811                 */
 812                if (PortP->Mapped) {
 813                        rio_spin_unlock_irqrestore(&PortP->portSem, flags);
 814                        continue;
 815                } else
 816                        HostMapP->Flags &= ~RTA_NEWBOOT;
 817
 818                PortP->State = 0;
 819                PortP->Config = 0;
 820                /*
 821                 ** Check out the module type - if it is special (read only etc.)
 822                 ** then we need to set flags in the PortP->Config.
 823                 ** Note: For 16 port RTA, all ports are of the same type.
 824                 */
 825                if (RtaType == TYPE_RTA16) {
 826                        PortP->Config |= p->RIOModuleTypes[HostP->UnixRups[HostMapP->ID - 1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE];
 827                } else {
 828                        if (SubEnt < PORTS_PER_MODULE)
 829                                PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
 830                        else
 831                                PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
 832                }
 833
 834                /*
 835                 ** more port related flags
 836                 */
 837                PortP->PortState = 0;
 838                PortP->ModemLines = 0;
 839                PortP->ModemState = 0;
 840                PortP->CookMode = COOK_WELL;
 841                PortP->ParamSem = 0;
 842                PortP->FlushCmdBodge = 0;
 843                PortP->WflushFlag = 0;
 844                PortP->MagicFlags = 0;
 845                PortP->Lock = 0;
 846                PortP->Store = 0;
 847                PortP->FirstOpen = 1;
 848
 849                /*
 850                 ** Buffers 'n things
 851                 */
 852                PortP->RxDataStart = 0;
 853                PortP->Cor2Copy = 0;
 854                PortP->Name = &HostMapP->Name[0];
 855                PortP->statsGather = 0;
 856                PortP->txchars = 0;
 857                PortP->rxchars = 0;
 858                PortP->opens = 0;
 859                PortP->closes = 0;
 860                PortP->ioctls = 0;
 861                if (PortP->TxRingBuffer)
 862                        memset(PortP->TxRingBuffer, 0, p->RIOBufferSize);
 863                else if (p->RIOBufferSize) {
 864                        PortP->TxRingBuffer = kzalloc(p->RIOBufferSize, GFP_KERNEL);
 865                }
 866                PortP->TxBufferOut = 0;
 867                PortP->TxBufferIn = 0;
 868                PortP->Debug = 0;
 869                /*
 870                 ** LastRxTgl stores the state of the rx toggle bit for this
 871                 ** port, to be compared with the state of the next pkt received.
 872                 ** If the same, we have received the same rx pkt from the RTA
 873                 ** twice. Initialise to a value not equal to PHB_RX_TGL or 0.
 874                 */
 875                PortP->LastRxTgl = ~(u8) PHB_RX_TGL;
 876
 877                /*
 878                 ** and mark the port as usable
 879                 */
 880                PortP->Mapped = 1;
 881                rio_spin_unlock_irqrestore(&PortP->portSem, flags);
 882        }
 883        if (HostMapP->SysPort < p->RIOFirstPortsMapped)
 884                p->RIOFirstPortsMapped = HostMapP->SysPort;
 885        if (HostMapP->SysPort > p->RIOLastPortsMapped)
 886                p->RIOLastPortsMapped = HostMapP->SysPort;
 887
 888        return 0;
 889}
 890
 891int RIOChangeName(struct rio_info *p, struct Map *MapP)
 892{
 893        int host;
 894        struct Map *HostMapP;
 895        char *sptr;
 896
 897        rio_dprintk(RIO_DEBUG_TABLE, "Change name entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);
 898
 899        if (MapP->ID > MAX_RUP) {
 900                rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
 901                p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
 902                return -EINVAL;
 903        }
 904
 905        MapP->Name[MAX_NAME_LEN - 1] = '\0';
 906        sptr = MapP->Name;
 907
 908        while (*sptr) {
 909                if (*sptr < ' ' || *sptr > '~') {
 910                        rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
 911                        p->RIOError.Error = BAD_CHARACTER_IN_NAME;
 912                        return -EINVAL;
 913                }
 914                sptr++;
 915        }
 916
 917        for (host = 0; host < p->RIONumHosts; host++) {
 918                if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {
 919                        if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {
 920                                p->RIOError.Error = HOST_NOT_RUNNING;
 921                                return -ENXIO;
 922                        }
 923                        if (MapP->ID == 0) {
 924                                memcpy(p->RIOHosts[host].Name, MapP->Name, MAX_NAME_LEN);
 925                                return 0;
 926                        }
 927
 928                        HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];
 929
 930                        if (HostMapP->RtaUniqueNum != MapP->RtaUniqueNum) {
 931                                p->RIOError.Error = RTA_NUMBER_WRONG;
 932                                return -ENXIO;
 933                        }
 934                        memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN);
 935                        return 0;
 936                }
 937        }
 938        p->RIOError.Error = UNKNOWN_HOST_NUMBER;
 939        rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
 940        return -ENXIO;
 941}
 942