Ignore:
Timestamp:
06/13/03 17:40:41 (20 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Children:
641fb28
Parents:
7a848b40
Message:

2003-06-13 Greg Menke <gregory.menke@…>

PR 405/bsps

  • bootloader/pci.c: Added support for configuring devices for pci busses > 0
  • pci/pci.c, pci/pci.h: Added FixupPCI() to store vectors in the INTERRUPT_LINE register of pci devices any # of hops away from the host processor.
  • motorola/motorola.c, motorola/motorola.h: Added interrupt routing tables in support of FixupPCI. This is board-specific, each board will have to supply information for FixupPCI() to do anything for it.
  • startup/bspstart.c: Extended bat2 to cover entire PCI address space.
  • irq/irq.c, irq/irq.h: Added support for shared interrupts. Existing single hander vectors are undisturbed, a new function added to allow adding/removing handlers from a vector.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/powerpc/shared/pci/pci.c

    r7a848b40 r12838559  
    217217
    218218
     219
     220
     221
     222
     223
     224
     225
     226
     227
     228
     229
     230#define PRINT_MSG() \
     231             printk("pci : Device %d:%02x routed to interrupt_line %d\n", pbus, pslot, int_name )
     232
     233
     234/*
     235** Validate a test interrupt name and print a warning if its not one of
     236** the names defined in the routing record.
     237*/
     238static int test_intname( struct _int_map *row, int pbus, int pslot, int int_pin, int int_name )
     239{
     240   int j,k;
     241   int _nopin= -1, _noname= -1;
     242
     243   for(j=0; row->pin_route[j].pin > -1; j++)
     244   {
     245      if( row->pin_route[j].pin == int_pin )
     246      {
     247         _nopin = 0;
     248         
     249         for(k=0; k<4 && row->pin_route[j].int_name[k] > -1; k++ )
     250         {
     251            if( row->pin_route[j].int_name[k] == int_name ){ _noname=0; break; }
     252         }
     253         break;
     254      }
     255   }
     256
     257   if( _nopin  )
     258   {
     259      printk("pci : Device %d:%02x supplied a bogus interrupt_pin %d\n", pbus, pslot, int_pin );
     260      return -1;
     261   }
     262   else
     263   {
     264      if( _noname )
     265         printk("pci : Device %d:%02x supplied a suspicious interrupt_line %d, using it anyway\n", pbus, pslot, int_name );
     266   }
     267   return 0;
     268}
     269
     270
     271
     272
     273
     274struct pcibridge
     275{
     276      int bus,slot;
     277};
     278
     279
     280static int FindPCIbridge( int mybus, struct pcibridge *pb )
     281{
     282   int          pbus, pslot;
     283   unsigned8    bussec, buspri;
     284   unsigned16   devid, vendorid, dclass;
     285
     286   for(pbus=0; pbus< BusCountPCI(); pbus++)
     287   {
     288      for(pslot=0; pslot< PCI_MAX_DEVICES; pslot++)
     289      {
     290         pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &devid);
     291         if( devid == 0xffff ) continue;
     292
     293         pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &vendorid);
     294         if( vendorid == 0xffff ) continue;
     295
     296         pci_read_config_word(pbus, pslot, 0, PCI_CLASS_DEVICE, &dclass);
     297
     298         if( dclass == PCI_CLASS_BRIDGE_PCI )
     299         {
     300            pci_read_config_byte(pbus, pslot, 0, PCI_PRIMARY_BUS,    &buspri);
     301            pci_read_config_byte(pbus, pslot, 0, PCI_SECONDARY_BUS,  &bussec);
     302
     303#if 0
     304            printk("pci : Found bridge at %d:%d, mybus %d, pribus %d, secbus %d  ", pbus, pslot, mybus, buspri, bussec );
     305#endif
     306            if( bussec == mybus )
     307            {
     308#if 0
     309               printk("match\n");
     310#endif
     311               /* found our nearest bridge going towards the root */
     312               pb->bus = pbus;
     313               pb->slot = pslot;
     314
     315               return 0;
     316            }
     317#if 0
     318            printk("no match\n");
     319#endif
     320         }
     321
     322
     323      }
     324   }
     325   return -1;
     326}
     327
     328
     329
     330
     331
     332
     333
     334
     335void FixupPCI( struct _int_map *bspmap, int (*swizzler)(int,int) )
     336{
     337   unsigned char        cvalue;
     338   unsigned16           devid;
     339   int                  ismatch, i, j, pbus, pslot, int_pin, int_name;
     340
     341   /*
     342   ** If the device has a non-zero INTERRUPT_PIN, assign a bsp-specific
     343   ** INTERRUPT_NAME if one isn't already in place.  Then, drivers can
     344   ** trivially use INTERRUPT_NAME to hook up with devices.
     345   */
     346
     347   for(pbus=0; pbus< BusCountPCI(); pbus++)
     348   {
     349      for(pslot=0; pslot< PCI_MAX_DEVICES; pslot++)
     350      {
     351         pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &devid);
     352         if( devid == 0xffff ) continue;
     353
     354         /* got a device */
     355
     356         pci_read_config_byte( pbus, pslot, 0, PCI_INTERRUPT_PIN, &cvalue);
     357         int_pin = cvalue;
     358
     359         pci_read_config_byte( pbus, pslot, 0, PCI_INTERRUPT_LINE, &cvalue);
     360         int_name = cvalue;
     361
     362/* printk("pci : device %d:%02x devid %04x, intpin %d, intline  %d\n", pbus, pslot, devid, int_pin, int_name ); */
     363
     364         if( int_pin > 0 )
     365         {
     366            ismatch = 0;
     367
     368            /*
     369            ** first run thru the bspmap table and see if we have an explicit configuration
     370            */
     371            for(i=0; bspmap[i].bus > -1; i++)
     372            {
     373               if( bspmap[i].bus == pbus && bspmap[i].slot == pslot )
     374               {
     375                  ismatch = -1;
     376                  /* we have a record in the table that gives specific
     377                   * pins and interrupts for devices in this slot */
     378                  if( int_name == 255 )
     379                  {
     380                     /* find the vector associated with whatever pin the device gives us */
     381                     for( int_name=-1, j=0; bspmap[i].pin_route[j].pin > -1; j++ )
     382                     {
     383                        if( bspmap[i].pin_route[j].pin == int_pin )
     384                        {
     385                           int_name = bspmap[i].pin_route[j].int_name[0];
     386                           break;
     387                        }
     388                     }
     389                     if( int_name == -1 )
     390                     {
     391                        printk("pci : Unable to resolve device %d:%d w/ swizzled int pin %i to an interrupt_line.\n", pbus, pslot, int_pin );
     392                     }
     393                     else
     394                     {
     395                        PRINT_MSG();
     396                        pci_write_config_byte(pbus,pslot,0,PCI_INTERRUPT_LINE,(cvalue= int_name, cvalue));
     397                     }
     398                  }
     399                  else
     400                  {
     401                     test_intname( &bspmap[i],pbus,pslot,int_pin,int_name);
     402                  }
     403                  break;
     404               }
     405            }
     406
     407           
     408            if( !ismatch )
     409            {
     410               /*
     411               ** no match, which means we're on a bus someplace.  Work
     412               ** backwards from it to one of our defined busses,
     413               ** swizzling thru each bridge on the way.
     414               */
     415
     416               /* keep pbus, pslot pointed to the device being
     417               configured while we track down the bridges using
     418               tbus,tslot.  We keep searching the routing table because
     419               we may end up finding our bridge in it */
     420
     421               int tbus= pbus, tslot= pslot;
     422
     423               for(;;)
     424               {
     425
     426                  for(i=0; bspmap[i].bus > -1; i++)
     427                  {
     428                     if( bspmap[i].bus == tbus && (bspmap[i].slot == tslot || bspmap[i].slot == -1) )
     429                     {
     430                        ismatch = -1;
     431                        /* found a record for this bus, so swizzle the
     432                         * int_pin which we then use to find the
     433                         * interrupt_name.
     434                         */
     435
     436                        if( int_name == 255 )
     437                        {
     438                           /*
     439                           ** FIXME.  I can't believe this little hack
     440                           ** is right.  It does not yield an error in
     441                           ** convienently simple situations.
     442                           */
     443                           if( tbus ) int_pin = (*swizzler)(tslot,int_pin);
     444
     445
     446                           /*
     447                           ** int_pin points to the interrupt channel
     448                           ** this card ends up delivering interrupts
     449                           ** on.  Find the int_name servicing it.
     450                           */
     451                           for( int_name=-1, j=0; bspmap[i].pin_route[j].pin > -1; j++ )
     452                           {
     453                              if( bspmap[i].pin_route[j].pin == int_pin )
     454                              {
     455                                 int_name = bspmap[i].pin_route[j].int_name[0];
     456                                 break;
     457                              }
     458                           }
     459                           if( int_name == -1 )
     460                           {
     461                              printk("pci : Unable to resolve device %d:%d w/ swizzled int pin %i to an interrupt_line.\n", pbus, pslot, int_pin );
     462                           }
     463                           else
     464                           {
     465                              PRINT_MSG();
     466                              pci_write_config_byte(pbus,pslot,0,PCI_INTERRUPT_LINE,(cvalue= int_name, cvalue));
     467                           }
     468                        }
     469                        else
     470                        {
     471                           test_intname(&bspmap[i],pbus,pslot,int_pin,int_name);
     472                        }
     473                        goto donesearch;
     474                     }
     475                  }
     476
     477
     478                  if( !ismatch )
     479                  {
     480                     struct pcibridge   pb;
     481
     482                     /*
     483                     ** Haven't found our bus in the int map, so work
     484                     ** upwards thru the bridges till we find it.
     485                     */
     486
     487                     if( FindPCIbridge( tbus, &pb )== 0 )
     488                     {
     489                        int_pin = (*swizzler)(tslot,int_pin);
     490
     491                        /* our next bridge up is on pb.bus, pb.slot- now
     492                        ** instead of pointing to the device we're
     493                        ** trying to configure, we move from bridge to
     494                        ** bridge.
     495                        */
     496
     497                        tbus = pb.bus;
     498                        tslot = pb.slot;
     499                     }
     500                     else
     501                     {
     502                        printk("pci : No bridge from bus %i towards root found\n", tbus );
     503                        goto donesearch;
     504                     }
     505                     
     506                  }
     507
     508               }
     509            }
     510           donesearch:
     511
     512
     513            if( !ismatch && int_pin != 0 && int_name == 255 )
     514            {
     515               printk("pci : Unable to match device %d:%d with an int routing table entry\n", pbus, pslot  );
     516            }
     517
     518
     519         }
     520      }
     521   }
     522}
     523
     524
     525
     526
     527
     528
     529
     530
     531
     532
    219533/*
    220534 * This routine determines the maximum bus number in the system
     
    229543
    230544  detect_host_bridge();
     545
    231546  /*
    232547   * Scan PCI bus 0 looking for PCI-PCI bridges
Note: See TracChangeset for help on using the changeset viewer.