Changeset 63 for GPL/trunk/lib32/pci.c


Ignore:
Timestamp:
Jan 3, 2006, 11:33:10 PM (20 years ago)
Author:
vladest
Message:

(Patches by Ruediger Ihle)
Support for IRQs > 15
Fixed resource manager registration
Fixed crash on APM suspend/resume and system shutdown

File:
1 edited

Legend:

Unmodified
Added
Removed
  • GPL/trunk/lib32/pci.c

    r35 r63  
    4141#include <osspci.h>
    4242
     43#define MAX_PCI_BUSSES          16
     44#define MAX_PCI_DEVICES         16
     45
    4346struct pci_dev pci_devices[MAX_PCI_DEVICES] = {0};
    4447struct pci_bus pci_busses[MAX_PCI_BUSSES] = {0};
    4548
    46 HRESMGR hResMgr = 0;
    47 
    4849BOOL    fSuspended = FALSE;
    4950extern int nrCardsDetected;
    50 //******************************************************************************
    51 //******************************************************************************
    52 OSSRET OSS32_APMResume()
    53 {
    54     int i;
    55     struct pci_driver *driver;
    56 
    57     dprintf(("OSS32_APMResume"));
    58     for(i=0;i<MAX_PCI_DEVICES;i++)
    59     {
    60         if(pci_devices[i].devfn)
    61         {
    62             driver = pci_devices[i].pcidriver;
    63             if(driver && driver->resume) {
    64                 driver->resume(&pci_devices[i]);
    65                 fSuspended = FALSE;
    66             }
    67         }
    68     }
    69     fSuspended = FALSE;
    70     return OSSERR_SUCCESS;
    71 }
    72 //******************************************************************************
    73 //******************************************************************************
    74 OSSRET OSS32_APMSuspend()
    75 {
    76     int i;
    77     struct pci_driver *driver;
    78 
    79     dprintf(("OSS32_APMSuspend"));
    80     fSuspended = TRUE;
    81     for(i=0;i<MAX_PCI_DEVICES;i++)
    82     {
    83         if(pci_devices[i].devfn)
    84         {
    85             driver = pci_devices[i].pcidriver;
    86             if(driver && driver->suspend) {
    87                 driver->suspend(&pci_devices[i], SNDRV_CTL_POWER_D3cold);
    88             }
    89         }
    90     }
    91     return OSSERR_SUCCESS;
    92 }
    93 //******************************************************************************
    94 //******************************************************************************
    95 int pcidev_prepare(struct pci_dev *dev)
    96 {
    97     dprintf(("pcidev_prepare %x not implemented", dev));
    98     return 1; //todo: correct return value??
    99 }
    100 //******************************************************************************
    101 //******************************************************************************
    102 int pcidev_activate(struct pci_dev *dev)
    103 {
    104     dprintf(("pcidev_activate %x not implemented", dev));
    105     return 1; //todo: correct return value??
    106 }
    107 //******************************************************************************
    108 //******************************************************************************
    109 int pcidev_deactivate(struct pci_dev *dev)
    110 {
    111     dprintf(("pcidev_deactivate %x not implemented", dev));
    112     return 1; //todo: correct return value??
    113 }
     51
    11452
    11553#define PCI_CONFIG_ENABLE       0x80000000
    11654#define PCI_CONFIG_ADDRESS      0xCF8
    11755#define PCI_CONFIG_DATA         0xCFC
    118 /*
    119  * get number of devices of given PCIID
    120  */
    121 int pci_get_dev_num(ULONG pciId)
    122 {
    123     ULONG devNr, busNr, funcNr, temp, cfgaddrreg, detectedId;
    124     int found = 0;
     56
     57
     58//******************************************************************************
     59#define CONFIG_CMD(dev, where)  \
     60    (PCI_CONFIG_ENABLE | (dev->bus->number<<16) | (dev->devfn<<8) | (where & ~3))
     61//******************************************************************************
     62int pci_read_config_byte(struct pci_dev *dev, int where, u8 *value)
     63{
     64    outl(CONFIG_CMD(dev,where), PCI_CONFIG_ADDRESS);
     65    *value = inb(PCI_CONFIG_DATA + (where&3));
     66    return PCIBIOS_SUCCESSFUL;
     67}
     68//******************************************************************************
     69//******************************************************************************
     70int pci_read_config_word(struct pci_dev *dev, int where, u16 *value)
     71{
     72    outl(CONFIG_CMD(dev,where), PCI_CONFIG_ADDRESS);
     73    *value = inw(PCI_CONFIG_DATA + (where&2));
     74    return PCIBIOS_SUCCESSFUL;
     75}
     76//******************************************************************************
     77//******************************************************************************
     78int pci_read_config_dword(struct pci_dev *dev, int where, u32 *value)
     79{
     80    outl(CONFIG_CMD(dev,where), PCI_CONFIG_ADDRESS);
     81    *value = inl(PCI_CONFIG_DATA);
     82    return PCIBIOS_SUCCESSFUL;
     83}
     84//******************************************************************************
     85//******************************************************************************
     86int pci_write_config_byte(struct pci_dev *dev, int where, u8 value)
     87{
     88    outl(CONFIG_CMD(dev,where), PCI_CONFIG_ADDRESS);
     89    outb(value, PCI_CONFIG_DATA + (where&3));
     90    return PCIBIOS_SUCCESSFUL;
     91}
     92//******************************************************************************
     93//******************************************************************************
     94int pci_write_config_word(struct pci_dev *dev, int where, u16 value)
     95{
     96    outl(CONFIG_CMD(dev,where), PCI_CONFIG_ADDRESS);
     97    outw(value, PCI_CONFIG_DATA + (where&2));
     98    return PCIBIOS_SUCCESSFUL;
     99}
     100//******************************************************************************
     101//******************************************************************************
     102int pci_write_config_dword(struct pci_dev *dev, int where, u32 value)
     103{
     104    outl(CONFIG_CMD(dev,where), PCI_CONFIG_ADDRESS);
     105    outl(value, PCI_CONFIG_DATA);
     106    return PCIBIOS_SUCCESSFUL;
     107}
     108//******************************************************************************
     109//******************************************************************************
     110int pcidev_prepare(struct pci_dev *dev)
     111{
     112    dprintf(("pcidev_prepare %x not implemented", dev));
     113    return 1; //todo: correct return value??
     114}
     115//******************************************************************************
     116//******************************************************************************
     117int pcidev_activate(struct pci_dev *dev)
     118{
     119    dprintf(("pcidev_activate %x not implemented", dev));
     120    return 1; //todo: correct return value??
     121}
     122//******************************************************************************
     123//******************************************************************************
     124int pcidev_deactivate(struct pci_dev *dev)
     125{
     126    dprintf(("pcidev_deactivate %x not implemented", dev));
     127    return 1; //todo: correct return value??
     128}
     129
     130
     131
     132//******************************************************************************
     133//******************************************************************************
     134static int pci_query_device(unsigned int vendor, unsigned int device,
     135                            struct pci_dev near *pcidev, int idx)
     136{
     137    int         resNo, addr, found = 0;
     138    u32         devNr, busNr, funcNr, detectedId, pciId, cfgaddrreg, temp, temp2;
     139    u8          headerType;
     140
     141    pciId = (device << 16) | vendor;
    125142
    126143    cfgaddrreg = inl(PCI_CONFIG_ADDRESS);
     
    131148            for(funcNr=0;funcNr<8;funcNr++)
    132149            {
    133                 temp = ((ULONG)((ULONG)devNr<<11UL) + ((ULONG)busNr<<16UL) + ((ULONG)funcNr << 8UL));
    134 
    135                 outl(PCI_CONFIG_ENABLE|temp, PCI_CONFIG_ADDRESS);
     150                headerType = 0;
     151                temp = PCI_CONFIG_ENABLE | (busNr<<16) | (devNr<<11) | (funcNr<<8);
     152                outl(temp, PCI_CONFIG_ADDRESS);
    136153                detectedId = inl(PCI_CONFIG_DATA);
    137 //                printk("det: %x, need: %x\n", detectedId, pciId);
    138                 if(detectedId == pciId)
    139                     found++;
     154                if( detectedId != 0xffffffff )
     155                {
     156                    outl(temp | (PCI_HEADER_TYPE & ~3), PCI_CONFIG_ADDRESS);
     157                    headerType = inb(PCI_CONFIG_DATA + (PCI_HEADER_TYPE & 3));
     158                }
     159                //              printk("det: %x (%x), need: %x\n", detectedId, headerType, pciId);
     160
     161                if( detectedId == pciId &&
     162                   (headerType & 0x7f) == PCI_HEADER_TYPE_NORMAL )
     163                {
     164                    if( found++ == idx )
     165                    {
     166                        memset((void near *)pcidev, 0, sizeof(struct pci_dev));
     167
     168                        pcidev->vendor      = vendor;
     169                        pcidev->device      = device;
     170                        pcidev->bus         = &pci_busses[busNr];
     171                        pcidev->bus->number = busNr;
     172                        pcidev->devfn       = (devNr << 3) | funcNr;
     173                        pcidev->hdr_type    = headerType & 0x7f;
     174
     175                        pcidev->prepare    = pcidev_prepare;
     176                        pcidev->activate   = pcidev_activate;
     177                        pcidev->deactivate = pcidev_deactivate;
     178                        pcidev->active     = 1;
     179                        pcidev->ro         = 0;
     180                        pcidev->sibling    = NULL;
     181                        pcidev->next       = NULL;
     182                        pcidev->dma_mask   = 0xFFFFFFFF;
     183
     184                        // Subsystem ID
     185                        pci_read_config_word(pcidev, PCI_SUBSYSTEM_VENDOR_ID,
     186                                             &pcidev->subsystem_vendor);
     187                        pci_read_config_word(pcidev, PCI_SUBSYSTEM_ID,
     188                                             &pcidev->subsystem_device);
     189
     190                        // I/O  and MEM
     191                        resNo = 0;
     192                        for( addr = PCI_BASE_ADDRESS_0; addr <= PCI_BASE_ADDRESS_5; addr += 4 )
     193                        {
     194                            pci_read_config_dword(pcidev, addr, &temp);
     195                            if( temp != 0 && temp != 0xffffffff )
     196                            {
     197                                pci_write_config_dword(pcidev, addr, 0xffffffff);
     198                                pci_read_config_dword(pcidev, addr, &temp2);
     199                                pci_write_config_dword(pcidev, addr, temp);
     200
     201                                if( temp & PCI_BASE_ADDRESS_SPACE_IO )
     202                                {
     203                                    pcidev->resource[resNo].flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO;
     204                                    pcidev->resource[resNo].start = temp & PCI_BASE_ADDRESS_IO_MASK;
     205                                    pcidev->resource[resNo].end   = pcidev->resource[resNo].start +
     206                                        ~(temp2 & PCI_BASE_ADDRESS_IO_MASK) + 1;
     207                                }
     208                                else
     209                                {
     210                                    pcidev->resource[resNo].flags = IORESOURCE_MEM | IORESOURCE_MEM_WRITEABLE;
     211                                    pcidev->resource[resNo].start = temp & PCI_BASE_ADDRESS_MEM_MASK;
     212                                    pcidev->resource[resNo].end   = pcidev->resource[resNo].start +
     213                                        ~(temp2 & PCI_BASE_ADDRESS_MEM_MASK) + 1;
     214                                }
     215
     216                                resNo++;
     217
     218                            }
     219                        }
     220
     221                        // IRQ and PIN
     222                        pci_read_config_dword(pcidev, PCI_INTERRUPT_LINE, &temp);
     223                        if( (u8)temp && (u8)temp != 0xff )
     224                        {
     225                            pcidev->irq_resource[0].flags = IORESOURCE_IRQ;
     226                            pcidev->irq_resource[0].start =
     227                                pcidev->irq_resource[0].end   = temp & 0xffff;
     228                            pcidev->irq = (u8)temp;
     229                        }
     230
     231                        return 1;
     232                    }
     233                }
     234
     235                // don't need to check more, if function 0 not present or single
     236                if( funcNr == 0 && !(headerType & 0x80) )               break;
    140237            }
    141238        }
    142    }
    143 
    144     if(!found) {
    145         outl(cfgaddrreg, PCI_CONFIG_ADDRESS);
    146         return 0;
    147     }
    148     return found;
    149 }
    150 //******************************************************************************
    151 //TODO: Doesn't completely fill in the pci_dev structure
    152 //******************************************************************************
    153 int FindPCIDevice(unsigned int vendor, unsigned int device, struct pci_dev near *pcidev, int idx)
    154 {
    155     IDC_RESOURCE idcres;
    156     int i, residx = 0;
    157 
    158     pcidev->prepare    = pcidev_prepare;
    159     pcidev->activate   = pcidev_activate;
    160     pcidev->deactivate = pcidev_deactivate;
    161     pcidev->active     = 1;
    162     pcidev->ro         = 0;
    163     pcidev->sibling    = NULL;
    164     pcidev->next       = NULL;
    165     pcidev->vendor     = vendor;
    166     pcidev->device     = device;
    167     pcidev->dma_mask   = 0xFFFFFFFF;
    168 
    169 
    170     //    printk("FindPCIDevice vend: %x, id: %x\n",vendor, device);
    171     hResMgr = 0;
    172     hResMgr = RMFindPCIDevice(vendor, device, &idcres, idx);
    173     if(hResMgr == 0) {
    174         return FALSE;
    175     }
    176     pcidev->devfn = idcres.devfn;
    177     //pcidev->devfn = idcres.devfn + 1;
    178 
    179     for(i=0;i<MAX_RES_IO;i++) {
    180         if(idcres.io[i] != 0xffff) {
    181             pcidev->resource[residx].name  = 0;
    182             pcidev->resource[residx].child = 0;
    183             pcidev->resource[residx].sibling = 0;
    184             pcidev->resource[residx].parent = 0;
    185             pcidev->resource[residx].start = idcres.io[i];
    186             pcidev->resource[residx].end   = idcres.io[i] + idcres.iolength[i]; //inclusive??
    187             pcidev->resource[residx].flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO;
    188 
    189             residx++;
    190         }
    191     }
    192     for(i=0;i<MAX_RES_MEM;i++) {
    193         if(idcres.mem[i] != 0xffffffff) {
    194             pcidev->resource[residx].name  = 0;
    195             pcidev->resource[residx].child = 0;
    196             pcidev->resource[residx].sibling = 0;
    197             pcidev->resource[residx].parent = 0;
    198             pcidev->resource[residx].start = idcres.mem[i];
    199             pcidev->resource[residx].end   = idcres.mem[i] + idcres.memlength[i]; //inclusive??
    200             pcidev->resource[residx].flags = IORESOURCE_MEM | IORESOURCE_MEM_WRITEABLE;
    201             printk("residx: %i start: %x\n", residx, pcidev->resource[residx].start);
    202             residx++;
    203         }
    204     }
    205     for(i=0;i<MAX_RES_DMA;i++) {
    206         if(idcres.dma[i] != 0xffff) {
    207             pcidev->dma_resource[i].name  = 0;
    208             pcidev->dma_resource[i].child = 0;
    209             pcidev->dma_resource[i].sibling = 0;
    210             pcidev->dma_resource[i].parent = 0;
    211             pcidev->dma_resource[i].start = idcres.dma[i];
    212             pcidev->dma_resource[i].end   = idcres.dma[i];
    213             //todo: 8/16 bits
    214             pcidev->dma_resource[i].flags = IORESOURCE_DMA;
    215         }
    216     }
    217     for(i=0;i<MAX_RES_IRQ;i++) {
    218         if(idcres.irq[i] != 0xffff) {
    219             pcidev->irq_resource[i].name  = 0;
    220             pcidev->irq_resource[i].child = 0;
    221             pcidev->irq_resource[i].sibling = 0;
    222             pcidev->irq_resource[i].parent = 0;
    223             pcidev->irq_resource[i].start = idcres.irq[i];
    224             pcidev->irq_resource[i].end   = idcres.irq[i];
    225             //todo: irq flags
    226             pcidev->irq_resource[9].flags = IORESOURCE_IRQ;
    227         }
    228     }
    229     if(pcidev->irq_resource[0].start != 0xffff) {
    230          pcidev->irq = pcidev->irq_resource[0].start;
    231     }
    232     else pcidev->irq = 0;
    233 
    234     if(idcres.busnr > MAX_PCI_BUSSES) {
    235         DebugInt3();
    236         return FALSE;
    237     }
    238     pcidev->bus = &pci_busses[idcres.busnr];
    239     pcidev->bus->number = idcres.busnr;
    240 
    241     pci_read_config_word(pcidev, PCI_SUBSYSTEM_VENDOR_ID, &pcidev->subsystem_vendor);
    242     pci_read_config_word(pcidev, PCI_SUBSYSTEM_ID, &pcidev->subsystem_device);
    243 
    244     return TRUE;
    245 }
     239    }
     240    outl(cfgaddrreg, PCI_CONFIG_ADDRESS);
     241    return 0;
     242
     243}
     244
    246245//******************************************************************************
    247246//******************************************************************************
     
    249248{
    250249    int i, idx;
    251     HRESMGR hResMgrTmp = 0;
    252250
    253251    if((int)from < 8) {
    254252        idx = (int)from; // dirty hack
    255 //        return 0;
     253        //        return 0;
    256254    } else
    257255        idx = 0;
    258 //    printk("searching device. vendor %x, pci id %x, idx %i\n",vendor,device, idx);
    259     //not very pretty
    260     if(hResMgr) {
    261         hResMgrTmp = hResMgr;
    262         hResMgr    = 0;
    263     }
     256
    264257    for(i=0;i<MAX_PCI_DEVICES;i++)
    265258    {
    266259        if(pci_devices[i].devfn == 0)
    267260        {
    268             if(FindPCIDevice(vendor, device, (struct pci_dev near *)&pci_devices[i], idx) == TRUE) {
    269                 if(hResMgrTmp) {
    270                     RMDestroy(hResMgr);
    271                     hResMgr = hResMgrTmp;
    272                 }
    273 //                pci_read_config_dword(&pci_devices[i], PCI_CLASS_REVISION, &pci_devices[i]._class);
    274 //                if (((pci_devices[i]._class >> 8) & 0xffff) == PCI_CLASS_MULTIMEDIA_AUDIO)
    275                     return &pci_devices[i];
    276             }
    277 #ifdef DEBUG
    278                 printk("wrong device. vendor %x, pci id %x\n",vendor,device);
    279 #endif
    280             break;
    281         }
    282     }
    283     if(hResMgrTmp) {
    284         RMDestroy(hResMgr);
    285         hResMgr = hResMgrTmp;
    286     }
    287     return 0;
    288 }
    289 //******************************************************************************
    290 //******************************************************************************
    291 struct resource * __request_region(struct resource *a, unsigned long start, unsigned long n, const char *name)
    292 {
    293         struct resource *resource;
     261            if( pci_query_device(vendor, device, (struct pci_dev near *)&pci_devices[i], idx) )
     262                return &pci_devices[i];
     263            else
     264                break;
     265        }
     266    }
     267
     268    return NULL;
     269}
     270//******************************************************************************
     271//******************************************************************************
     272struct resource * __request_region(struct resource *a, unsigned long start,
     273                                   unsigned long n, const char *name)
     274{
     275    struct resource *resource;
    294276
    295277    if(a->flags & IORESOURCE_MEM) {
    296         if(RMRequestMem(hResMgr, start, n) == FALSE) {
     278        if(RMRequestMem(/*hResMgr,*/ start, n) == FALSE) {
    297279            printk("RMRequestIO failed for io %x, length %x\n", start, n);
    298280            return NULL;
    299281        }
    300282    }
    301     else
    302     if(a->flags & IORESOURCE_IO) {
    303         if(RMRequestIO(hResMgr, start, n) == FALSE) {
     283    else if(a->flags & IORESOURCE_IO) {
     284        if(RMRequestIO(/*hResMgr,*/ start, n) == FALSE) {
    304285            printk("RMRequestIO failed for io %x, length %x\n", start, n);
    305286            return NULL;
     
    307288    }
    308289
    309         resource = kmalloc(sizeof(struct resource), GFP_KERNEL);
    310         if (resource == NULL)
    311                 return NULL;
    312         resource->name  = name;
    313         resource->start = start;
    314         resource->end   = start + n - 1;
    315         resource->flags = a->flags;
    316         return resource;
    317 }
    318 //******************************************************************************
    319 //******************************************************************************
    320 void __release_region(struct resource *resource, unsigned long b, unsigned long c)
    321 {
    322     if(resource) {
    323         kfree(resource);
     290    resource = kmalloc(sizeof(struct resource), GFP_KERNEL);
     291    if (resource == NULL)
     292        return NULL;
     293    resource->name  = name;
     294    resource->start = start;
     295    resource->end     = start + n; // - 1;
     296    resource->flags = a->flags;
     297    resource->parent  =
     298        resource->child   = NULL;
     299
     300    // insert in list
     301    resource->sibling = a->sibling;
     302    a->sibling = resource;
     303
     304    return resource;
     305}
     306//******************************************************************************
     307//******************************************************************************
     308void __release_region(struct resource *a,
     309                      unsigned long start, unsigned long n)
     310{
     311    struct resource     *resource;
     312    struct resource     **ppres = &a->sibling;
     313    unsigned long       end = start + n; // - 1;
     314
     315    while( *ppres )
     316    {
     317        resource = *ppres;
     318
     319        if( resource->start == start && resource->end == end )
     320        {
     321            // remove from list
     322            *ppres = resource->sibling;
     323            kfree(resource);
     324            return;
     325        }
     326
     327        ppres = &resource->sibling;
    324328    }
    325329}
     
    335339}
    336340//******************************************************************************
    337 #define CONFIG_CMD(dev, where)   (0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | (where & ~3))
    338 //******************************************************************************
    339 int pci_read_config_byte(struct pci_dev *dev, int where, u8 *value)
    340 {
    341     outl(CONFIG_CMD(dev,where), 0xCF8);
    342     *value = inb(0xCFC + (where&3));
    343     return PCIBIOS_SUCCESSFUL;
    344 }
    345 //******************************************************************************
    346 //******************************************************************************
    347 int pci_read_config_word(struct pci_dev *dev, int where, u16 *value)
    348 {
    349     outl(CONFIG_CMD(dev,where), 0xCF8);
    350     *value = inw(0xCFC + (where&2));
    351     return PCIBIOS_SUCCESSFUL;
    352 }
    353 //******************************************************************************
    354 //******************************************************************************
    355 int pci_read_config_dword(struct pci_dev *dev, int where, u32 *value)
    356 {
    357     outl(CONFIG_CMD(dev,where), 0xCF8);
    358     *value = inl(0xCFC);
    359     return PCIBIOS_SUCCESSFUL;
    360 }
    361 //******************************************************************************
    362 //******************************************************************************
    363 int pci_write_config_byte(struct pci_dev *dev, int where, u8 value)
    364 {
    365     outl(CONFIG_CMD(dev,where), 0xCF8);
    366     outb(value, 0xCFC + (where&3));
    367     return PCIBIOS_SUCCESSFUL;
    368 }
    369 //******************************************************************************
    370 //******************************************************************************
    371 int pci_write_config_word(struct pci_dev *dev, int where, u16 value)
    372 {
    373     outl(CONFIG_CMD(dev,where), 0xCF8);
    374     outw(value, 0xCFC + (where&2));
    375     return PCIBIOS_SUCCESSFUL;
    376 }
    377 //******************************************************************************
    378 //******************************************************************************
    379 int pci_write_config_dword(struct pci_dev *dev, int where, u32 value)
    380 {
    381     outl(CONFIG_CMD(dev,where), 0xCF8);
    382     outl(value, 0xCFC);
    383     return PCIBIOS_SUCCESSFUL;
    384 }
    385 //******************************************************************************
    386341//******************************************************************************
    387342int pcibios_present(void)
     
    409364int pci_find_capability(struct pci_dev *dev, int cap)
    410365{
    411         u16 status;
    412         u8 pos, id;
    413         int ttl = 48;
    414 
    415         pci_read_config_word(dev, PCI_STATUS, &status);
    416         if (!(status & PCI_STATUS_CAP_LIST))
    417                 return 0;
    418         pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &pos);
    419         while (ttl-- && pos >= 0x40) {
    420                 pos &= ~3;
    421                 pci_read_config_byte(dev, pos + PCI_CAP_LIST_ID, &id);
    422                 if (id == 0xff)
    423                         break;
    424                 if (id == cap)
    425                         return pos;
    426                 pci_read_config_byte(dev, pos + PCI_CAP_LIST_NEXT, &pos);
    427         }
    428         return 0;
     366    u16 status;
     367    u8 pos, id;
     368    int ttl = 48;
     369
     370    pci_read_config_word(dev, PCI_STATUS, &status);
     371    if (!(status & PCI_STATUS_CAP_LIST))
     372        return 0;
     373    pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &pos);
     374    while (ttl-- && pos >= 0x40) {
     375        pos &= ~3;
     376        pci_read_config_byte(dev, pos + PCI_CAP_LIST_ID, &id);
     377        if (id == 0xff)
     378            break;
     379        if (id == cap)
     380            return pos;
     381        pci_read_config_byte(dev, pos + PCI_CAP_LIST_NEXT, &pos);
     382    }
     383    return 0;
    429384}
    430385//******************************************************************************
     
    437392int pci_set_power_state(struct pci_dev *dev, int new_state)
    438393{
    439         u32 base[5], romaddr;
    440         u16 pci_command, pwr_command;
    441         u8  pci_latency, pci_cacheline;
    442         int i, old_state;
    443         int pm = pci_find_capability(dev, PCI_CAP_ID_PM);
    444 
    445         if (!pm)
    446                 return 0;
    447         pci_read_config_word(dev, pm + PCI_PM_CTRL, &pwr_command);
    448         old_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
    449         if (old_state == new_state)
    450                 return old_state;
    451         if (old_state == 3) {
    452                 pci_read_config_word(dev, PCI_COMMAND, &pci_command);
    453                 pci_write_config_word(dev, PCI_COMMAND, pci_command & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
    454                 for (i = 0; i < 5; i++)
    455                         pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + i*4, &base[i]);
    456                 pci_read_config_dword(dev, PCI_ROM_ADDRESS, &romaddr);
    457                 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
    458                 pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &pci_cacheline);
    459                 pci_write_config_word(dev, pm + PCI_PM_CTRL, new_state);
    460                 for (i = 0; i < 5; i++)
    461                         pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + i*4, base[i]);
    462                 pci_write_config_dword(dev, PCI_ROM_ADDRESS, romaddr);
    463                 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
    464                 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cacheline);
    465                 pci_write_config_byte(dev, PCI_LATENCY_TIMER, pci_latency);
    466                 pci_write_config_word(dev, PCI_COMMAND, pci_command);
    467         } else
    468                 pci_write_config_word(dev, pm + PCI_PM_CTRL, (pwr_command & ~PCI_PM_CTRL_STATE_MASK) | new_state);
    469         return old_state;
     394    u32 base[5], romaddr;
     395    u16 pci_command, pwr_command;
     396    u8  pci_latency, pci_cacheline;
     397    int i, old_state;
     398    int pm = pci_find_capability(dev, PCI_CAP_ID_PM);
     399
     400    if (!pm)
     401        return 0;
     402    pci_read_config_word(dev, pm + PCI_PM_CTRL, &pwr_command);
     403    old_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
     404    if (old_state == new_state)
     405        return old_state;
     406    if (old_state == 3) {
     407        pci_read_config_word(dev, PCI_COMMAND, &pci_command);
     408        pci_write_config_word(dev, PCI_COMMAND, pci_command & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
     409        for (i = 0; i < 5; i++)
     410            pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + i*4, &base[i]);
     411        pci_read_config_dword(dev, PCI_ROM_ADDRESS, &romaddr);
     412        pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
     413        pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &pci_cacheline);
     414        pci_write_config_word(dev, pm + PCI_PM_CTRL, new_state);
     415        for (i = 0; i < 5; i++)
     416            pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + i*4, base[i]);
     417        pci_write_config_dword(dev, PCI_ROM_ADDRESS, romaddr);
     418        pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
     419        pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cacheline);
     420        pci_write_config_byte(dev, PCI_LATENCY_TIMER, pci_latency);
     421        pci_write_config_word(dev, PCI_COMMAND, pci_command);
     422    } else
     423        pci_write_config_word(dev, pm + PCI_PM_CTRL, (pwr_command & ~PCI_PM_CTRL_STATE_MASK) | new_state);
     424    return old_state;
    470425}
    471426//******************************************************************************
     
    478433int pci_enable_device(struct pci_dev *dev)
    479434{
    480         u16 pci_command;
    481 
    482         printk("pci_enable_device %x\n", dev);
    483 
    484         pci_read_config_word(dev, PCI_COMMAND, &pci_command);
    485         pci_write_config_word(dev, PCI_COMMAND, pci_command | (PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
    486         pci_set_power_state(dev, 0);
    487         return 0;
     435    u16 pci_command;
     436
     437    printk("pci_enable_device %x\n", dev);
     438
     439    pci_read_config_word(dev, PCI_COMMAND, &pci_command);
     440    pci_write_config_word(dev, PCI_COMMAND, pci_command | (PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
     441    pci_set_power_state(dev, 0);
     442    return 0;
    488443}
    489444//******************************************************************************
     
    491446int pci_register_driver(struct pci_driver *driver)
    492447{
    493     struct pci_dev *pcidev = NULL;
    494     int i = 0, j;
    495     int dev_num;
    496     ULONG pcidevid;
    497 
    498     while(driver->id_table[i].vendor)
     448    int i, j, dev_num;
     449    struct pci_dev *pcidev;
     450
     451    for( i = 0; driver->id_table[i].vendor; i++)
    499452    {
    500         pcidevid = ((ULONG)driver->id_table[i].device << 16) |
    501             (ULONG)driver->id_table[i].vendor;
    502         dev_num = pci_get_dev_num(pcidevid);
    503 
    504         if (dev_num) {
    505             printk("found: %i number of %x, id: %x\n",dev_num,driver->id_table[i].vendor, driver->id_table[i].device);
    506 
    507             for (j=0; j < dev_num; j++) // dirty hack for multiply cards with same PCIID
    508             {
    509                 pcidev = pci_find_device(driver->id_table[i].vendor, driver->id_table[i].device, (struct pci_dev *)j);
    510                 //        printk("checking pci vend: %x, id: %x %i\n",driver->id_table[i].vendor, driver->id_table[i].device, i);
    511 #ifdef DEBUG
    512                 //        dprintf(("checked device: vendor %x, pci id %x, pcidev %x, probe %x",
    513                 //                 driver->id_table[i].vendor,driver->id_table[i].device, pcidev, driver->probe));
    514 #endif
    515                 if(pcidev && driver->probe) {
    516                     printk("found: %x, id: %x idx %i\n",driver->id_table[i].vendor, driver->id_table[i].device, j);
    517 
    518                     if(driver->probe(pcidev, &driver->id_table[i]) == 0) {
    519                         //remove resource manager object for this device and
    520                         //register resources with RM
    521                         RMFinialize(hResMgr);
    522                         hResMgr = 0;
    523 
    524                         //save driver pointer for suspend/resume calls
    525                         pcidev->pcidriver = (void *)driver;
    526                         pcidev->current_state = 4;
    527                         //return 1;
    528                     }
    529                     else pcidev->devfn = 0;
    530 
    531                     RMDestroy(hResMgr);
    532                     hResMgr = 0;
     453        dev_num = 0;
     454        while( (pcidev = pci_find_device(driver->id_table[i].vendor,
     455                                         driver->id_table[i].device,
     456                                         (struct pci_dev *)dev_num)) != NULL )
     457        {
     458            RMInit();
     459            if( driver->probe) {
     460                printk("found: %x, id: %x idx %i\n",driver->id_table[i].vendor, driver->id_table[i].device, dev_num);
     461
     462                if(driver->probe(pcidev, &driver->id_table[i]) == 0) {
     463                    pcidev->pcidriver = (void *)driver;
     464                    pcidev->current_state = 4;
     465
     466                    // create adapter
     467                    RMDone((driver->id_table[i].vendor << 16) | driver->id_table[i].device);
     468
     469                    return 1;
    533470                }
    534             } // for j
    535             return dev_num;
    536         }
    537         i++;
     471                else pcidev->devfn = 0;
     472            }
     473
     474            RMDone(0);
     475
     476            dev_num++;
     477
     478        }
    538479    }
    539480    return 0;
     
    578519void pci_set_master(struct pci_dev *dev)
    579520{
    580         u16 cmd;
    581 
    582         pci_read_config_word(dev, PCI_COMMAND, &cmd);
    583         if (! (cmd & PCI_COMMAND_MASTER)) {
     521    u16 cmd;
     522
     523    pci_read_config_word(dev, PCI_COMMAND, &cmd);
     524    if (! (cmd & PCI_COMMAND_MASTER)) {
    584525        dprintf(("pci_set_master %x", dev));
    585                 cmd |= PCI_COMMAND_MASTER;
    586                 pci_write_config_word(dev, PCI_COMMAND, cmd);
    587         }
     526        cmd |= PCI_COMMAND_MASTER;
     527        pci_write_config_word(dev, PCI_COMMAND, cmd);
     528    }
    588529    return;
    589530}
     
    722663int pci_orig_save_state(struct pci_dev *dev, u32 *buffer)
    723664{
    724         int i;
    725         if (buffer) {
    726                 /* XXX: 100% dword access ok here? */
    727                 for (i = 0; i < 16; i++)
    728                         pci_read_config_dword(dev, i * 4,&buffer[i]);
    729         }
    730         return 0;
     665    int i;
     666    if (buffer) {
     667        /* XXX: 100% dword access ok here? */
     668        for (i = 0; i < 16; i++)
     669            pci_read_config_dword(dev, i * 4,&buffer[i]);
     670    }
     671    return 0;
    731672}
    732673
     
    740681pci_orig_restore_state(struct pci_dev *dev, u32 *buffer)
    741682{
    742         int i;
    743 
    744         if (buffer) {
    745                 for (i = 0; i < 16; i++)
    746                         pci_write_config_dword(dev,i * 4, buffer[i]);
    747         }
    748         /*
    749         * otherwise, write the context information we know from bootup.
    750         * This works around a problem where warm-booting from Windows
    751         * combined with a D3(hot)->D0 transition causes PCI config
    752         * header data to be forgotten.
    753         */
    754         else {
    755                 for (i = 0; i < 6; i ++)
    756                         pci_write_config_dword(dev,
    757                                                PCI_BASE_ADDRESS_0 + (i * 4),
    758                                                dev->resource[i].start);
    759                 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
    760         }
    761         return 0;
     683    int i;
     684
     685    if (buffer) {
     686        for (i = 0; i < 16; i++)
     687            pci_write_config_dword(dev,i * 4, buffer[i]);
     688    }
     689    /*
     690    * otherwise, write the context information we know from bootup.
     691    * This works around a problem where warm-booting from Windows
     692    * combined with a D3(hot)->D0 transition causes PCI config
     693    * header data to be forgotten.
     694    */
     695    else {
     696        for (i = 0; i < 6; i ++)
     697            pci_write_config_dword(dev,
     698                                   PCI_BASE_ADDRESS_0 + (i * 4),
     699                                   dev->resource[i].start);
     700        pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
     701    }
     702    return 0;
    762703}
    763704
    764705struct saved_config_tbl {
    765         struct pci_dev *pci;
    766         u32 config[16];
     706    struct pci_dev *pci;
     707    u32 config[16];
    767708};
    768709static struct saved_config_tbl saved_tbl[16];
     
    770711void pci_save_state(struct pci_dev *pci)
    771712{
    772         int i;
    773         /* FIXME: mutex needed for race? */
    774         for (i = 0; i < ARRAY_SIZE(saved_tbl); i++) {
    775                 if (! saved_tbl[i].pci) {
    776                         saved_tbl[i].pci = pci;
    777                         pci_orig_save_state(pci, saved_tbl[i].config);
    778                         return;
    779                 }
    780         }
    781         printk(KERN_DEBUG "snd: no pci config space found!\n");
     713    int i;
     714    /* FIXME: mutex needed for race? */
     715    for (i = 0; i < ARRAY_SIZE(saved_tbl); i++) {
     716        if (! saved_tbl[i].pci) {
     717            saved_tbl[i].pci = pci;
     718            pci_orig_save_state(pci, saved_tbl[i].config);
     719            return;
     720        }
     721    }
     722    printk(KERN_DEBUG "snd: no pci config space found!\n");
    782723}
    783724
    784725void pci_restore_state(struct pci_dev *pci)
    785726{
    786         int i;
    787         /* FIXME: mutex needed for race? */
    788         for (i = 0; i < ARRAY_SIZE(saved_tbl); i++) {
    789                 if (saved_tbl[i].pci == pci) {
    790                         saved_tbl[i].pci = NULL;
    791                         pci_orig_restore_state(pci, saved_tbl[i].config);
    792                         return;
    793                 }
    794         }
    795         printk(KERN_DEBUG "snd: no saved pci config!\n");
     727    int i;
     728    /* FIXME: mutex needed for race? */
     729    for (i = 0; i < ARRAY_SIZE(saved_tbl); i++) {
     730        if (saved_tbl[i].pci == pci) {
     731            saved_tbl[i].pci = NULL;
     732            pci_orig_restore_state(pci, saved_tbl[i].config);
     733            return;
     734        }
     735    }
     736    printk(KERN_DEBUG "snd: no saved pci config!\n");
    796737}
    797738
     
    809750int pci_request_region(struct pci_dev *pdev, int bar, char *res_name)
    810751{
    811         int flags;
    812 
    813         if (pci_resource_len(pdev, bar) == 0)
    814                 return 0;
    815         flags = pci_get_flags(pdev, bar);
    816         if (flags & IORESOURCE_IO) {
    817                 if (check_region(pci_resource_start(pdev, bar), pci_resource_len(pdev, bar)))
    818                     goto err_out;
    819                 request_region(pci_resource_start(pdev, bar),
    820                                pci_resource_len(pdev, bar), res_name);
    821         }
    822         return 0;
     752    int flags;
     753
     754    if (pci_resource_len(pdev, bar) == 0)
     755        return 0;
     756    flags = pci_get_flags(pdev, bar);
     757    if (flags & IORESOURCE_IO) {
     758        if (check_region(pci_resource_start(pdev, bar), pci_resource_len(pdev, bar)))
     759            goto err_out;
     760        request_region(pci_resource_start(pdev, bar),
     761                       pci_resource_len(pdev, bar), res_name);
     762    }
     763    else if (flags & IORESOURCE_MEM) {
     764        if (check_mem_region(pci_resource_start(pdev, bar), pci_resource_len(pdev, bar)))
     765            goto err_out;
     766        request_mem_region(pci_resource_start(pdev, bar),
     767                           pci_resource_len(pdev, bar), res_name);
     768    }
     769
     770    return 0;
    823771
    824772err_out:
    825         printk(KERN_WARNING "PCI: Unable to reserve %s region #%d:%lx@%lx for device %s\n",
    826                 flags & IORESOURCE_IO ? "I/O" : "mem",
    827                 bar + 1, /* PCI BAR # */
    828                 pci_resource_len(pdev, bar), pci_resource_start(pdev, bar),
    829                 res_name);
    830         return -EBUSY;
     773    printk(KERN_WARNING "PCI: Unable to reserve %s region #%d:%lx@%lx for device %s\n",
     774           flags & IORESOURCE_IO ? "I/O" : "mem",
     775           bar + 1, /* PCI BAR # */
     776           pci_resource_len(pdev, bar), pci_resource_start(pdev, bar),
     777           res_name);
     778    return -EBUSY;
    831779}
    832780
    833781void pci_release_region(struct pci_dev *pdev, int bar)
    834782{
    835         int flags;
    836 
    837         if (pci_resource_len(pdev, bar) == 0)
    838                 return;
    839         flags = pci_get_flags(pdev, bar);
    840         if (flags & IORESOURCE_IO) {
    841                 release_region(pci_resource_start(pdev, bar),
    842                                pci_resource_len(pdev, bar));
    843         }
     783    int flags;
     784
     785    if (pci_resource_len(pdev, bar) == 0)
     786        return;
     787    flags = pci_get_flags(pdev, bar);
     788    if (flags & IORESOURCE_IO) {
     789        release_region(pci_resource_start(pdev, bar),
     790                       pci_resource_len(pdev, bar));
     791    }
     792    else if (flags & IORESOURCE_MEM) {
     793        release_mem_region(pci_resource_start(pdev, bar),
     794                           pci_resource_len(pdev, bar));
     795    }
    844796}
    845797
    846798int pci_request_regions(struct pci_dev *pdev, char *res_name)
    847799{
    848         int i;
    849 
    850         for (i = 0; i < 6; i++)
    851                 if (pci_request_region(pdev, i, res_name))
    852                         goto err;
    853         return 0;
    854  err:
    855         while (--i >= 0)
    856                 pci_release_region(pdev, i);
    857         return -EBUSY;
     800    int i;
     801
     802    for (i = 0; i < 6; i++)
     803        if (pci_request_region(pdev, i, res_name))
     804            goto err;
     805    return 0;
     806    err:
     807        while (--i >= 0)
     808            pci_release_region(pdev, i);
     809        return -EBUSY;
    858810}
    859811
    860812void pci_release_regions(struct pci_dev *pdev)
    861813{
    862         int i;
    863         for (i = 0; i < 6; i++)
    864                 pci_release_region(pdev, i);
     814    int i;
     815    for (i = 0; i < 6; i++)
     816        pci_release_region(pdev, i);
    865817}
    866818
     
    886838int snd_pci_dev_present(const struct pci_device_id *ids)
    887839{
    888         while (ids->vendor || ids->subvendor) {
    889                 if (pci_find_device(ids->vendor, ids->subvendor, NULL))
    890                         return 1;
    891                 ids++;
    892         }
    893         return 0;
     840    while (ids->vendor || ids->subvendor) {
     841        if (pci_find_device(ids->vendor, ids->subvendor, NULL))
     842            return 1;
     843        ids++;
     844    }
     845    return 0;
    894846}
    895847
     
    940892}
    941893#endif
     894
     895
     896//******************************************************************************
     897//******************************************************************************
     898OSSRET OSS32_APMResume()
     899{
     900    int i;
     901    struct pci_driver *driver;
     902
     903    dprintf(("OSS32_APMResume"));
     904
     905    for(i=0;i<MAX_PCI_DEVICES;i++)
     906    {
     907        if(pci_devices[i].devfn)
     908        {
     909            driver = pci_devices[i].pcidriver;
     910            if(driver && driver->resume) {
     911                driver->resume(&pci_devices[i]);
     912                //              fSuspended = FALSE;
     913            }
     914        }
     915    }
     916
     917    fSuspended = FALSE;
     918
     919    return OSSERR_SUCCESS;
     920}
     921//******************************************************************************
     922//******************************************************************************
     923OSSRET OSS32_APMSuspend()
     924{
     925    int i;
     926    struct pci_driver *driver;
     927
     928    dprintf(("OSS32_APMSuspend"));
     929
     930    fSuspended = TRUE;
     931
     932    for(i=0;i<MAX_PCI_DEVICES;i++)
     933    {
     934        if(pci_devices[i].devfn)
     935        {
     936            driver = pci_devices[i].pcidriver;
     937            if(driver && driver->suspend) {
     938                driver->suspend(&pci_devices[i], SNDRV_CTL_POWER_D3cold);
     939            }
     940        }
     941    }
     942
     943    return OSSERR_SUCCESS;
     944}
     945
Note: See TracChangeset for help on using the changeset viewer.