Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

rt_pci.c

Go to the documentation of this file.
00001 /*********************************************************************************/
00002 /* This file has been written by Sergio Perez Alcañiz <serpeal@disca.upv.es>     */
00003 /*            Departamento de Informática de Sistemas y Computadores             */
00004 /*            Universidad Politécnica de Valencia                                */
00005 /*            Valencia (Spain)                                                   */
00006 /*                                                                               */
00007 /* The RTL-lwIP project has been supported by the Spanish Government Research    */
00008 /* Office (CICYT) under grant TIC2002-04123-C03-03                               */
00009 /*                                                                               */
00010 /* Copyright (c) March, 2003 SISTEMAS DE TIEMPO REAL EMPOTRADOS, FIABLES Y       */
00011 /* DISTRIBUIDOS BASADOS EN COMPONENTES                                           */
00012 /*                                                                               */
00013 /*  This program is free software; you can redistribute it and/or modify         */
00014 /*  it under the terms of the GNU General Public License as published by         */
00015 /*  the Free Software Foundation; either version 2 of the License, or            */
00016 /*  (at your option) any later version.                                          */
00017 /*                                                                               */
00018 /*  This program is distributed in the hope that it will be useful,              */
00019 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of               */
00020 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                */
00021 /*  GNU General Public License for more details.                                 */
00022 /*                                                                               */
00023 /*  You should have received a copy of the GNU General Public License            */
00024 /*  along with this program; if not, write to the Free Software                  */
00025 /*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    */
00026 /*                                                                               */
00027 /*  Linking RTL-lwIP statically or dynamically with other modules is making a    */
00028 /*  combined work based on RTL-lwIP.  Thus, the terms and conditions of the GNU  */
00029 /*  General Public License cover the whole combination.                          */
00030 /*                                                                               */
00031 /*  As a special exception, the copyright holders of RTL-lwIP give you           */
00032 /*  permission to link RTL-lwIP with independent modules that communicate with   */
00033 /*  RTL-lwIP solely through the interfaces, regardless of the license terms of   */
00034 /*  these independent modules, and to copy and distribute the resulting combined */
00035 /*  work under terms of your choice, provided that every copy of the combined    */
00036 /*  work is accompanied by a complete copy of the source code of RTL-lwIP (the   */
00037 /*  version of RTL-lwIP used to produce the combined work), being distributed    */
00038 /*  under the terms of the GNU General Public License plus this exception.  An   */
00039 /*  independent module is a module which is not derived from or based on         */
00040 /*  RTL-lwIP.                                                                    */
00041 /*                                                                               */
00042 /*  Note that people who make modified versions of RTL-lwIP are not obligated to */
00043 /*  grant this special exception for their modified versions; it is their choice */
00044 /*  whether to do so.  The GNU General Public License gives permission to        */
00045 /*  release a modified version without this exception; this exception also makes */
00046 /*  it possible to release a modified version which carries forward this         */
00047 /*  exception.                                                                   */
00048 /*                                                                               */
00049 /*  CONTRIBUTORS: -Miguel Masmano Tello <mmasmano@disca.upv.es>                  */
00050 /*                -COMEDI                                                        */
00051 /*                 The Linux Control and Measurement Device Interface            */
00052 /*                 David Schleef <ds@schleef.org>                                */
00053 /*********************************************************************************/
00054 
00055 #include <time.h>
00056 #include "rt_pci.h"
00057 
00058 #ifdef  CONFIG_PCI_DIRECT
00059 #define  PCIBIOS_SUCCESSFUL                0x00
00060 
00061 #define CONFIG_CMD(bus, device_fn, where)   (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
00062 
00063 
00064 /***************************************************************************************/
00079 int rt_pci_enable_wake(struct pci_dev *dev, u32 state, int enable)
00080 {
00081   int pm;
00082   u16 value;
00083   
00084   /* find PCI PM capability in list */
00085   pm = rt_pci_find_capability(dev, PCI_CAP_ID_PM);
00086   
00087   /* If device doesn't support PM Capabilities, but request is to disable
00088    * wake events, it's a nop; otherwise fail */
00089   if (!pm) 
00090     return enable ? -EIO : 0; 
00091   
00092   /* Check device's ability to generate PME# */
00093   rt_pci_read_config_word(dev,pm+PCI_PM_PMC,&value);
00094   
00095   value &= PCI_PM_CAP_PME_MASK;
00096   value >>= ffs(value);   /* First bit of mask */
00097   
00098         /* Check if it can generate PME# from requested state. */
00099   if (!value || !(value & (1 << state))) 
00100     return enable ? -EINVAL : 0;
00101   
00102   rt_pci_read_config_word(dev, pm + PCI_PM_CTRL, &value);
00103   
00104   /* Clear PME_Status by writing 1 to it and enable PME# */
00105   value |= PCI_PM_CTRL_PME_STATUS | PCI_PM_CTRL_PME_ENABLE;
00106   
00107   if (!enable)
00108     value &= ~PCI_PM_CTRL_PME_ENABLE;
00109   
00110   rt_pci_write_config_word(dev, pm + PCI_PM_CTRL, value);
00111   
00112   return 0;
00113 }
00114 
00115 
00116 /***************************************************************************************/
00125 int rt_pci_save_state(struct pci_dev *dev, u32 *buffer)
00126 {
00127         int i;
00128         if (buffer) {
00129                 /* XXX: 100% dword access ok here? */
00130                 for (i = 0; i < 16; i++)
00131                         rt_pci_read_config_dword(dev, i * 4,&buffer[i]);
00132         }
00133         return 0;
00134 }
00135 
00136 
00137 
00138 
00139 
00140 /***************************************************************************************/
00141 int rt_pcibios_read_config_byte(unsigned int bus, unsigned int device_fn,
00142                                unsigned int where, unsigned char *value)
00143 {
00144     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
00145     *value = inb(0xCFC + (where&3));
00146     return PCIBIOS_SUCCESSFUL;
00147 }
00148 
00149 /***************************************************************************************/
00150 int rt_pcibios_read_config_word (unsigned int bus,
00151     unsigned int device_fn, unsigned int where, unsigned short *value)
00152 {
00153     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
00154     *value = inw(0xCFC + (where&2));
00155     return PCIBIOS_SUCCESSFUL;
00156 }
00157 
00158 /***************************************************************************************/
00159 int rt_pcibios_read_config_dword (unsigned int bus, unsigned int device_fn,
00160                                  unsigned int where, unsigned int *value)
00161 {
00162     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
00163     *value = inl(0xCFC);
00164     return PCIBIOS_SUCCESSFUL;
00165 }
00166 
00167 /***************************************************************************************/
00168 int rt_pcibios_write_config_byte (unsigned int bus, unsigned int device_fn,
00169                                  unsigned int where, unsigned char value)
00170 {
00171     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
00172     outb(value, 0xCFC + (where&3));
00173     return PCIBIOS_SUCCESSFUL;
00174 }
00175 
00176 /***************************************************************************************/
00177 int rt_pcibios_write_config_word (unsigned int bus, unsigned int device_fn,
00178                                  unsigned int where, unsigned short value)
00179 {
00180     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
00181     outw(value, 0xCFC + (where&2));
00182     return PCIBIOS_SUCCESSFUL;
00183 }
00184 
00185 /***************************************************************************************/
00186 int rt_pcibios_write_config_dword (unsigned int bus, unsigned int device_fn, unsigned int where, unsigned int value)
00187 {
00188     outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
00189     outl(value, 0xCFC);
00190     return PCIBIOS_SUCCESSFUL;
00191 }
00192 
00193 /***************************************************************************************/
00194 int rt_pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq){
00195   rt_pcibios_write_config_byte ((int) dev->bus, (int) dev->devfn,
00196                              PCI_INTERRUPT_LINE, irq);
00197   rt_pcibios_write_config_byte ((int) dev->bus, (int)dev->devfn,
00198                              PCI_INTERRUPT_PIN, pin);
00199   return 1;
00200 }
00201 
00202 
00203 #undef CONFIG_CMD
00204 
00205 #else    /* CONFIG_PCI_DIRECT  no definido */
00206 
00207 static struct {
00208         unsigned long address;
00209         unsigned short segment;
00210 } bios32_indirect = { 0, KERN_CODE_SEG };
00211 
00212 static long pcibios_entry;
00213 static struct {
00214         unsigned long address;
00215         unsigned short segment;
00216 } pci_indirect = { 0, KERN_CODE_SEG };
00217 
00218 /***************************************************************************************/
00219 static unsigned long bios32_service(unsigned long service)
00220 {
00221         unsigned char return_code;      /* %al */
00222         unsigned long address;          /* %ebx */
00223         unsigned long length;           /* %ecx */
00224         unsigned long entry;            /* %edx */
00225         unsigned long flags;
00226 
00227         save_flags(flags);
00228         __asm__(
00229 #ifdef ABSOLUTE_WITHOUT_ASTERISK
00230                 "lcall (%%edi)"
00231 #else
00232                 "lcall *(%%edi)"
00233 #endif
00234                 : "=a" (return_code),
00235                   "=b" (address),
00236                   "=c" (length),
00237                   "=d" (entry)
00238                 : "0" (service),
00239                   "1" (0),
00240                   "D" (&bios32_indirect));
00241         restore_flags(flags);
00242 
00243         switch (return_code) {
00244                 case 0:
00245                         return address + entry;
00246                 case 0x80:      /* No presente */
00247                         ethernet_printf("bios32_service(%d) : no presente\n", service);
00248                         return 0;
00249                 default: /* No deberia pasar */
00250                         ethernet_printf("bios32_service(%d) : devuelto %#X\n",
00251                                 service, return_code);
00252                         return 0;
00253         }
00254 }
00255 
00256 /***************************************************************************************/
00257 int rt_pcibios_read_config_byte(unsigned int bus,
00258         unsigned int device_fn, unsigned int where, unsigned char *value)
00259 {
00260         unsigned long ret;
00261         unsigned long bx = (bus << 8) | device_fn;
00262         unsigned long flags;
00263 
00264         save_flags(flags);
00265         __asm__(
00266 #ifdef ABSOLUTE_WITHOUT_ASTERISK
00267                 "lcall (%%esi)\n\t"
00268 #else
00269                 "lcall *(%%esi)\n\t"
00270 #endif
00271                 "jc 1f\n\t"
00272                 "xor %%ah, %%ah\n"
00273                 "1:"
00274                 : "=c" (*value),
00275                   "=a" (ret)
00276                 : "1" (PCIBIOS_READ_CONFIG_BYTE),
00277                   "b" (bx),
00278                   "D" ((long) where),
00279                   "S" (&pci_indirect));
00280         restore_flags(flags);
00281         return (int) (ret & 0xff00) >> 8;
00282 }
00283 
00284 /***************************************************************************************/
00285 int rt_pcibios_read_config_word(unsigned int bus,
00286         unsigned int device_fn, unsigned int where, unsigned short *value)
00287 {
00288         unsigned long ret;
00289         unsigned long bx = (bus << 8) | device_fn;
00290         unsigned long flags;
00291 
00292         save_flags(flags);
00293         __asm__(
00294 #ifdef ABSOLUTE_WITHOUT_ASTERISK
00295                 "lcall (%%esi)\n\t"
00296 #else
00297                 "lcall *(%%esi)\n\t"
00298 #endif
00299                 "jc 1f\n\t"
00300                 "xor %%ah, %%ah\n"
00301                 "1:"
00302                 : "=c" (*value),
00303                   "=a" (ret)
00304                 : "1" (PCIBIOS_READ_CONFIG_WORD),
00305                   "b" (bx),
00306                   "D" ((long) where),
00307                   "S" (&pci_indirect));
00308         restore_flags(flags);
00309         return (int) (ret & 0xff00) >> 8;
00310 }
00311 
00312 /***************************************************************************************/
00313 int rt_pcibios_read_config_dword(unsigned int bus,
00314         unsigned int device_fn, unsigned int where, unsigned int *value)
00315 {
00316         unsigned long ret;
00317         unsigned long bx = (bus << 8) | device_fn;
00318         unsigned long flags;
00319 
00320         save_flags(flags);
00321         __asm__(
00322 #ifdef ABSOLUTE_WITHOUT_ASTERISK
00323                 "lcall (%%esi)\n\t"
00324 #else
00325                 "lcall *(%%esi)\n\t"
00326 #endif
00327                 "jc 1f\n\t"
00328                 "xor %%ah, %%ah\n"
00329                 "1:"
00330                 : "=c" (*value),
00331                   "=a" (ret)
00332                 : "1" (PCIBIOS_READ_CONFIG_DWORD),
00333                   "b" (bx),
00334                   "D" ((long) where),
00335                   "S" (&pci_indirect));
00336         restore_flags(flags);
00337         return (int) (ret & 0xff00) >> 8;
00338 }
00339 
00340 /***************************************************************************************/
00341 int rt_pcibios_write_config_byte (unsigned int bus,
00342         unsigned int device_fn, unsigned int where, unsigned char value)
00343 {
00344         unsigned long ret;
00345         unsigned long bx = (bus << 8) | device_fn;
00346         unsigned long flags;
00347 
00348         save_flags(flags); cli();
00349         __asm__(
00350 #ifdef ABSOLUTE_WITHOUT_ASTERISK
00351                 "lcall (%%esi)\n\t"
00352 #else
00353                 "lcall *(%%esi)\n\t"
00354 #endif
00355                 "jc 1f\n\t"
00356                 "xor %%ah, %%ah\n"
00357                 "1:"
00358                 : "=a" (ret)
00359                 : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
00360                   "c" (value),
00361                   "b" (bx),
00362                   "D" ((long) where),
00363                   "S" (&pci_indirect));
00364         restore_flags(flags);
00365         return (int) (ret & 0xff00) >> 8;
00366 }
00367 
00368 
00369 
00370 
00371 /***************************************************************************************/
00372 int rt_pcibios_write_config_word (unsigned int bus,
00373         unsigned int device_fn, unsigned int where, unsigned short value)
00374 {
00375         unsigned long ret;
00376         unsigned long bx = (bus << 8) | device_fn;
00377         unsigned long flags;
00378 
00379         save_flags(flags); cli();
00380         __asm__(
00381 #ifdef ABSOLUTE_WITHOUT_ASTERISK
00382                 "lcall (%%esi)\n\t"
00383 #else
00384                 "lcall *(%%esi)\n\t"
00385 #endif
00386                 "jc 1f\n\t"
00387                 "xor %%ah, %%ah\n"
00388                 "1:"
00389                 : "=a" (ret)
00390                 : "0" (PCIBIOS_WRITE_CONFIG_WORD),
00391                   "c" (value),
00392                   "b" (bx),
00393                   "D" ((long) where),
00394                   "S" (&pci_indirect));
00395         restore_flags(flags);
00396         return (int) (ret & 0xff00) >> 8;
00397 }
00398 
00399 /***************************************************************************************/
00400 int rt_pcibios_write_config_dword (unsigned int bus,
00401         unsigned int device_fn, unsigned int where, unsigned int value)
00402 {
00403         unsigned long ret;
00404         unsigned long bx = (bus << 8) | device_fn;
00405         unsigned long flags;
00406 
00407         save_flags(flags); cli();
00408         __asm__(
00409 #ifdef ABSOLUTE_WITHOUT_ASTERISK
00410                 "lcall (%%esi)\n\t"
00411 #else
00412                 "lcall *(%%esi)\n\t"
00413 #endif
00414                 "jc 1f\n\t"
00415                 "xor %%ah, %%ah\n"
00416                 "1:"
00417                 : "=a" (ret)
00418                 : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
00419                   "c" (value),
00420                   "b" (bx),
00421                   "D" ((long) where),
00422                   "S" (&pci_indirect));
00423         restore_flags(flags);
00424         return (int) (ret & 0xff00) >> 8;
00425 }
00426 
00427 /***************************************************************************************/
00428 static void check_pcibios(void)
00429 {
00430         unsigned long signature;
00431         unsigned char present_status;
00432         unsigned char major_revision;
00433         unsigned char minor_revision;
00434         unsigned long flags;
00435         int pack;
00436 
00437         if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
00438                 pci_indirect.address = pcibios_entry;
00439 
00440                 save_flags(flags);
00441                 __asm__(
00442 #ifdef ABSOLUTE_WITHOUT_ASTERISK
00443                         "lcall (%%edi)\n\t"
00444 #else
00445                         "lcall *(%%edi)\n\t"
00446 #endif
00447                         "jc 1f\n\t"
00448                         "xor %%ah, %%ah\n"
00449                         "1:\tshl $8, %%eax\n\t"
00450                         "movw %%bx, %%ax"
00451                         : "=d" (signature),
00452                           "=a" (pack)
00453                         : "1" (PCIBIOS_PCI_BIOS_PRESENT),
00454                           "D" (&pci_indirect)
00455                         : "bx", "cx");
00456                 restore_flags(flags);
00457 
00458                 present_status = (pack >> 16) & 0xff;
00459                 major_revision = (pack >> 8) & 0xff;
00460                 minor_revision = pack & 0xff;
00461                 if (present_status || (signature != PCI_SIGNATURE)) {
00462                         printf("ERROR: BIOS32 dice PCI BIOS, pero no PCI "
00463                                 "BIOS????\n");
00464                         pcibios_entry = 0;
00465                 }
00466 #if     DEBUG
00467                 if (pcibios_entry) {
00468                         printf ("pcibios_init : PCI BIOS revision %hhX.%hhX"
00469                                 " entrada en %#X\n", major_revision,
00470                                 minor_revision, pcibios_entry);
00471                 }
00472 #endif
00473         }
00474 }
00475 
00476 /***************************************************************************************/
00477 static void pcibios_init(void)
00478 {
00479         union bios32 *check;
00480         unsigned char sum;
00481         int i, length;
00482         unsigned long bios32_entry = 0;
00483 
00484         /*
00485           El procedimiento estandar para localizar el directorio de 
00486           servicios de BIOS32 se tiene que escanear una estructura BIOS32
00487           valida entre los rangos 0xE0000 0xFFFFF
00488          */
00489 
00490         for (check = (union bios32 *) 0xe0000; check <= (union bios32 *) 0xffff0; ++check) {
00491                 if (check->fields.signature != BIOS32_SIGNATURE)
00492                         continue;
00493                 length = check->fields.length * 16;
00494                 if (!length)
00495                         continue;
00496                 sum = 0;
00497                 for (i = 0; i < length ; ++i)
00498                         sum += check->chars[i];
00499                 if (sum != 0)
00500                         continue;
00501                 if (check->fields.revision != 0) {
00502                         printf("pcibios_init : revision no soportada %d en %#X\n", check->fields.revision,(unsigned int) check);
00503                         continue;
00504                 }
00505 #if     DEBUG
00506                 printf("pcibios_init : BIOS32 Service Directory "
00507                         "estructura en %#X\n", check);
00508 #endif
00509                 if (!bios32_entry) {
00510                         if (check->fields.entry >= 0x100000) {
00511                           printf("pcibios_init: entrada en la memoria alta\n");
00512                                 return;
00513                         } else {
00514                                 bios32_entry = check->fields.entry;
00515 #if     DEBUG
00516                                 printf("pcibios_init : BIOS32 Service Directory \nentrada en %#X\n", bios32_entry);
00517 #endif
00518                                 bios32_indirect.address = bios32_entry;
00519                         }
00520                 }
00521         }
00522         if (bios32_entry)
00523                 check_pcibios();
00524 }
00525 
00526 /***************************************************************************************/
00527 int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
00528 {
00529         int ret;
00530 
00531         __asm__(
00532 #ifdef ABSOLUTE_WITHOUT_ASTERISK
00533                 "lcall (%%esi); cld\n\t"
00534 #else
00535                 "lcall *(%%esi); cld\n\t"
00536 #endif
00537                 "jc 1f\n\t"
00538                 "xor %%ah, %%ah\n"
00539                 "1:"
00540                 : "=a" (ret)
00541                 : "0" (PCIBIOS_SET_PCI_HW_INT),
00542                   "b" ((dev->bus << 8) | dev->devfn),
00543                   "c" ((irq << 8) | (pin + 10)),
00544                   "S" (&pci_indirect));
00545         return !(ret & 0xff00);
00546 }
00547 
00548 #endif  /* CONFIG_PCI_DIRECT no definido */
00549 
00550 
00551 /***************************************************************************************/
00552 int rt_pci_set_power_state(struct pci_dev *dev, int state)
00553 {
00554         int pm;
00555         u16 pmcsr;
00556 
00557         /* bound the state we're entering */
00558         if (state > 3) state = 3;
00559 
00560         /* Validate current state:
00561          * Can enter D0 from any state, but if we can only go deeper 
00562          * to sleep if we're already in a low power state
00563          */
00564         if (state > 0 && dev->current_state > state)
00565                 return -EINVAL;
00566         else if (dev->current_state == state) 
00567                 return 0;        /* we're already there */
00568 
00569         /* find PCI PM capability in list */
00570         pm = rt_pci_find_capability(dev, PCI_CAP_ID_PM);
00571         
00572         /* abort if the device doesn't support PM capabilities */
00573         if (!pm) return -EIO; 
00574 
00575         /* check if this device supports the desired state */
00576         if (state == 1 || state == 2) {
00577                 u16 pmc;
00578                 rt_pci_read_config_word(dev,pm + PCI_PM_PMC,&pmc);
00579                 if (state == 1 && !(pmc & PCI_PM_CAP_D1)) return -EIO;
00580                 else if (state == 2 && !(pmc & PCI_PM_CAP_D2)) return -EIO;
00581         }
00582 
00583         /* If we're in D3, force entire word to 0.
00584          * This doesn't affect PME_Status, disables PME_En, and
00585          * sets PowerState to 0.
00586          */
00587         if (dev->current_state >= 3)
00588                 pmcsr = 0;
00589         else {
00590                 rt_pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
00591                 pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
00592                 pmcsr |= state;
00593         }
00594 
00595         /* enter specified state */
00596         rt_pci_write_config_word(dev, pm + PCI_PM_CTRL, pmcsr);
00597 
00598         /* Mandatory power management transition delays */
00599         /* see PCI PM 1.1 5.6.1 table 18 */
00600         if(state == 3 || dev->current_state == 3)
00601         {
00602                 //set_current_state(TASK_UNINTERRUPTIBLE);
00603                 //schedule_timeout(HZ/100);
00604           rtl_delay(200000);
00605         }
00606         else if(state == 2 || dev->current_state == 2)
00607                 rtl_delay(200000);
00608         dev->current_state = state;
00609 
00610         return 0;
00611 }
00612 
00613 
00636 int rt_pci_find_capability(struct pci_dev *dev, int cap)
00637 {
00638         u16 status;
00639         u8 pos, id;
00640         int ttl = 48;
00641 
00642         rt_pci_read_config_word(dev, PCI_STATUS, &status);
00643         if (!(status & PCI_STATUS_CAP_LIST))
00644                 return 0;
00645         switch (dev->hdr_type) {
00646         case PCI_HEADER_TYPE_NORMAL:
00647         case PCI_HEADER_TYPE_BRIDGE:
00648                 rt_pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &pos);
00649                 break;
00650         case PCI_HEADER_TYPE_CARDBUS:
00651                 rt_pci_read_config_byte(dev, PCI_CB_CAPABILITY_LIST, &pos);
00652                 break;
00653         default:
00654                 return 0;
00655         }
00656         while (ttl-- && pos >= 0x40) {
00657                 pos &= ~3;
00658                 rt_pci_read_config_byte(dev, pos + PCI_CAP_LIST_ID, &id);
00659                 if (id == 0xff)
00660                         break;
00661                 if (id == cap)
00662                         return pos;
00663                 rt_pci_read_config_byte(dev, pos + PCI_CAP_LIST_NEXT, &pos);
00664         }
00665         return 0;
00666 }
00667 
00668 
00669 /***************************************************************************************/
00670 /* This function only can be called inside init_module                                 */
00671 /***************************************************************************************/
00672 struct pci_dev * rt_pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from){
00673   return(pci_find_device(vendor, device, from));
00674 }
00675 
00676 /***************************************************************************************/
00677 /* This function only can be called inside init_module                                 */
00678 /***************************************************************************************/
00679 int rt_pci_enable_device(struct pci_dev *dev){
00680   return(pci_enable_device(dev));
00681 }
00682 
00683 
00684 /***************************************************************************************/
00691 int rt_pci_restore_state(struct pci_dev *dev, u32 *buffer)
00692 {
00693         int i;
00694 
00695         if (buffer) {
00696                 for (i = 0; i < 16; i++)
00697                         rt_pci_write_config_dword(dev,i * 4, buffer[i]);
00698         }
00699         /*
00700          * otherwise, write the context information we know from bootup.
00701          * This works around a problem where warm-booting from Windows
00702          * combined with a D3(hot)->D0 transition causes PCI config
00703          * header data to be forgotten.
00704          */     
00705         else {
00706                 for (i = 0; i < 6; i ++)
00707                         rt_pci_write_config_dword(dev,
00708                                                PCI_BASE_ADDRESS_0 + (i * 4),
00709                                                dev->resource[i].start);
00710                 rt_pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
00711         }
00712         return 0;
00713 }

Generated on Wed Jan 14 12:58:56 2004 for RTL-lwIP-0.4 by doxygen 1.3.4