Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2007  Luc Verhaegen <lverhaegen@novell.com>
  3.  * Copyright 2007  Matthias Hopf <mhopf@novell.com>
  4.  * Copyright 2007  Egbert Eich   <eich@novell.com>
  5.  * Copyright 2007  Advanced Micro Devices, Inc.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included in
  15.  * all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23.  * OTHER DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26. //ld -T ld.x -s --shared --image-base 0 --file-alignment 32 -o test.exe test.obj core.lib
  27.  
  28. #include "common.h"
  29. #include "rhd.h"
  30. #include "edid.h"
  31.  
  32. #include "rhd_atombios.h"
  33. #include "rhd_regs.h"
  34. #include "rhd_mc.h"
  35. #include "rhd_atombios.h"
  36. #include "rhd_connector.h"
  37. #include "rhd_output.h"
  38. #include "rhd_biosscratch.h"
  39. #include "rhd_card.h"
  40. #include "rhd_vga.h"
  41. #include "rhd_crtc.h"
  42. #include "rhd_monitor.h"
  43. #include "rhd_modes.h"
  44. #include "rhd_pll.h"
  45. #include "rhd_lut.h"
  46. #include "rhd_i2c.h"
  47.  
  48. #define PG_SW       0x003
  49. #define PG_NOCACHE  0x018
  50.  
  51. void sysSetScreen(int width, int height);
  52.  
  53. static void rhdModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
  54. static void rhdSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode);
  55. static void RHDAdjustFrame(RHDPtr rhdPtr, int x, int y, int flags);
  56. static Bool rhdMapFB(RHDPtr rhdPtr);
  57. static void rhdGetIGPNorthBridgeInfo(RHDPtr rhdPtr);
  58.  
  59. Bool OldSetupConnectors(RHDPtr rhdPtr);
  60. Bool OldConnectorsInit(RHDPtr rhdPtr);
  61.  
  62. int rhdInitHeap(RHDPtr rhdPtr);
  63.  
  64. static enum rhdCardType rhdGetCardType(RHDPtr rhdPtr);
  65.  
  66.  
  67. static u32_t _PciApi(int cmd);
  68. static int SupportedModes;
  69.  
  70. int __stdcall drvEntry(int)__asm__("_drvEntry");
  71.  
  72. typedef struct
  73. {
  74.   unsigned      handle;
  75.   unsigned      io_code;
  76.   void          *input;
  77.   int           inp_size;
  78.   void          *output;
  79.   int           out_size;
  80. }ioctl_t;
  81.  
  82. typedef int (_stdcall *srv_proc_t)(ioctl_t *);
  83.  
  84. int _stdcall srv_proc(ioctl_t *io);
  85.  
  86. extern PciChipset_t   RHDPCIchipsets[];
  87. extern struct rhdCard *RHDCardIdentify(RHDPtr rhdPtr);
  88.  
  89. static struct RHDRec       rhd;
  90. static struct _ScrnInfoRec Scrn;
  91.  
  92. void sysSetScreen(int width, int height)
  93. {
  94.   asm __volatile__
  95.   (
  96.     "dec eax \n\t"
  97.     "dec edx \n\t"
  98.     "call [DWORD PTR __imp__SetScreen] \n\t"
  99.     :
  100.     :"a" (width),"d"(height)
  101.     :"memory","cc"
  102.   );
  103. }
  104.  
  105. static int RegService(char *name, srv_proc_t proc)
  106. {
  107.   int retval;
  108.  
  109.   asm __volatile__
  110.   (
  111.     "push %[t] \n\t"
  112.     "push %[t1] \n\t"
  113.     "call [DWORD PTR __imp__RegService] \n\t"
  114.     :"=eax" (retval)
  115.     :[t] "g" (proc),[t1] "g" (name)
  116.     :"memory", "ebx"
  117.   );
  118.   return retval;
  119. };
  120.  
  121. static u32_t _PciApi(int cmd)
  122. {
  123.   u32_t retval;
  124.  
  125.   asm __volatile__
  126.   (
  127.     "call [DWORD PTR __imp__PciApi]"
  128.     :"=eax" (retval)
  129.     :"a" (cmd)
  130.     :"memory"
  131.   );
  132.   return retval;
  133. };
  134.  
  135. const PciChipset_t *PciDevMatch(CARD16 dev,const PciChipset_t *list)
  136. {
  137.   while(list->device)
  138.   {
  139.     if(dev==list->device)
  140.       return list;
  141.     list++;
  142.   }
  143.   return 0;
  144. }
  145.  
  146. const char *
  147. xf86TokenToString(SymTabPtr table, int token)
  148. {
  149.     int i;
  150.  
  151.     for (i = 0; table[i].token >= 0 && table[i].token != token; i++){};
  152.  
  153.     if (table[i].token < 0)
  154.       return NULL;
  155.     else
  156.       return(table[i].name);
  157. }
  158.  
  159. int FindPciDevice()
  160. {
  161.   const PciChipset_t *dev;
  162.   u32_t bus, last_bus;
  163.  
  164.   if( (last_bus = _PciApi(1))==-1)
  165.     return 0;
  166.  
  167.   for(bus=0;bus<=last_bus;bus++)
  168.   {
  169.     u32_t devfn;
  170.  
  171.     for(devfn=0;devfn<256;devfn++)
  172.     {
  173.       u32_t id;
  174.       id = PciRead32(bus,devfn, 0);
  175.  
  176.       if( (CARD16)id != VENDOR_ATI)
  177.         continue;
  178.  
  179.       if( (dev=PciDevMatch(id>>16,RHDPCIchipsets))!=0)
  180.       {
  181.  
  182.         rhd.PciDeviceID = (id>>16);
  183.  
  184.         rhd.bus = bus;
  185.         rhd.pci.bus = bus;
  186.         rhd.devfn = devfn;
  187.         rhd.pci.devfn = devfn;
  188.         rhd.PciTag = pciTag(bus,(devfn>>3)&0x1F,devfn&0x7);
  189.  
  190.         rhd.ChipSet = dev->family;
  191.        // rhd.IsMobility  = dev->mobility;
  192.        // rhd.IsIGP       = dev->igp;
  193.        // rhd.HasCRTC2    = !dev->nocrtc2;
  194.        // rhd.HasSingleDAC = dev->singledac;
  195.        // rhd.InternalTVOut = !dev->nointtvout;
  196.  
  197.         pciGetInfo(&rhd.pci);
  198.  
  199.         rhd.subvendor_id = rhd.pci.subsysVendor;
  200.         rhd.subdevice_id = rhd.pci.subsysCard;
  201.  
  202.         //rhd.chipset = (char*)xf86TokenToString(RADEONChipsets, rhd.device_id);
  203.  
  204.         return 1;
  205.       };
  206.     };
  207.   };
  208.  
  209.   dbgprintf("Device not found\n");
  210.  
  211.   return 0;
  212. }
  213.  
  214.  
  215. static Bool
  216. rhdMapMMIO()
  217. {
  218.  
  219.   rhd.MMIOMapSize = 1 << rhd.pci.size[RHD_MMIO_BAR];
  220.   rhd.MMIOBase = MapIoMem(rhd.pci.memBase[RHD_MMIO_BAR],
  221.                           rhd.MMIOMapSize,PG_SW+PG_NOCACHE);
  222.   if( !rhd.MMIOBase)
  223.     return 0;
  224.  
  225.   DBG(dbgprintf("Mapped IO at %x (size %x)\n", rhd.MMIOBase, rhd.MMIOMapSize));
  226.  
  227.   return 1;
  228. }
  229.  
  230. #define RADEON_NB_TOM             0x15c
  231. static CARD32
  232. rhdGetVideoRamSize(RHDPtr rhdPtr)
  233. {
  234.   CARD32 RamSize, BARSize;
  235.  
  236.   if (rhdPtr->ChipSet == RHD_RS690)
  237.     RamSize = (_RHDRegRead(rhdPtr, R5XX_CONFIG_MEMSIZE))>>10;
  238.   else
  239.     if (rhdPtr->IsIGP)
  240.     {
  241.       CARD32 tom = _RHDRegRead(rhdPtr, RADEON_NB_TOM);
  242.       RamSize = (((tom >> 16) - (tom & 0xffff) + 1) << 6);
  243.       _RHDRegWrite(rhdPtr,R5XX_CONFIG_MEMSIZE, RamSize<<10);
  244.     }
  245.     else
  246.     {
  247.       if (rhdPtr->ChipSet < RHD_R600)
  248.       {
  249.         RamSize = (_RHDRegRead(rhdPtr, R5XX_CONFIG_MEMSIZE)) >> 10;
  250.         if(RamSize==0) RamSize=8192;
  251.       }
  252.       else
  253.         RamSize = (_RHDRegRead(rhdPtr, R6XX_CONFIG_MEMSIZE)) >> 10;
  254.     };
  255.  
  256.   BARSize = 1 << (rhdPtr->pci.size[RHD_FB_BAR] - 10);
  257.   if(BARSize==0)
  258.     BARSize = 0x20000;
  259.  
  260.   if (RamSize > BARSize) {
  261.     DBG(dbgprintf("The detected amount of videoram"
  262.            " exceeds the PCI BAR aperture.\n"));
  263.     DBG(dbgprintf("Using only %dkB of the total "
  264.            "%dkB.\n", (int) BARSize, (int) RamSize));
  265.     return BARSize;
  266.   }
  267.   else return RamSize;
  268. }
  269.  
  270.  
  271. Bool RHDScalePolicy(struct rhdMonitor *Monitor, struct rhdConnector *Connector)
  272. {
  273.     if (!Monitor || !Monitor->UseFixedModes || !Monitor->NativeMode)
  274.         return FALSE;
  275.  
  276.     if (Connector->Type != RHD_CONNECTOR_PANEL)
  277.         return FALSE;
  278.  
  279.     return TRUE;
  280. }
  281.  
  282. static void
  283. rhdOutputConnectorCheck(struct rhdConnector *Connector)
  284. {
  285.     struct rhdOutput *Output;
  286.     int i;
  287.  
  288.     /* First, try to sense */
  289.     for (i = 0; i < 2; i++) {
  290.         Output = Connector->Output[i];
  291.         if (Output && Output->Sense) {
  292.             /*
  293.              * This is ugly and needs to change when the TV support patches are in.
  294.              * The problem here is that the Output struct can be used for two connectors
  295.              * and thus two different devices
  296.              */
  297.             if (Output->SensedType == RHD_SENSED_NONE) {
  298.              /* Do this before sensing as AtomBIOS sense needs this info */
  299.                 if ((Output->SensedType = Output->Sense(Output, Connector)) != RHD_SENSED_NONE) {
  300.                     RHDOutputPrintSensedType(Output);
  301.                     Output->Connector = Connector;
  302.                     break;
  303.                  }
  304.             }
  305.         }
  306.     }
  307.  
  308.     if (i == 2) {
  309.         /* now just enable the ones without sensing */
  310.         for (i = 0; i < 2; i++) {
  311.             Output = Connector->Output[i];
  312.             if (Output && !Output->Sense) {
  313.                 Output->Connector = Connector;
  314.                 break;
  315.             }
  316.         }
  317.     }
  318. }
  319.  
  320. /*
  321.  *
  322.  */
  323. static Bool
  324. rhdModeLayoutSelect(RHDPtr rhdPtr)
  325. {
  326.   struct rhdOutput *Output;
  327.   struct rhdConnector *Connector;
  328.   Bool Found = FALSE;
  329.   char *ignore = NULL;
  330.   Bool ConnectorIsDMS59 = FALSE;
  331.   int i = 0;
  332.  
  333.   RHDFUNC(rhdPtr);
  334.  
  335.   /* housekeeping */
  336.   rhdPtr->Crtc[0]->PLL = rhdPtr->PLLs[0];
  337.   rhdPtr->Crtc[0]->LUT = rhdPtr->LUT[0];
  338.  
  339.   rhdPtr->Crtc[1]->PLL = rhdPtr->PLLs[1];
  340.   rhdPtr->Crtc[1]->LUT = rhdPtr->LUT[1];
  341.  
  342.   /* start layout afresh */
  343.   for (Output = rhdPtr->Outputs; Output; Output = Output->Next)
  344.   {
  345.     Output->Active = FALSE;
  346.     Output->Crtc = NULL;
  347.     Output->Connector = NULL;
  348.   }
  349.  
  350.     /* quick and dirty option so that some output choice exists */
  351. //  ignore = xf86GetOptValString(rhdPtr->Options, OPTION_IGNORECONNECTOR);
  352.  
  353.     /* handle cards with DMS-59 connectors appropriately. The DMS-59 to VGA
  354.        adapter does not raise HPD at all, so we need a fallback there. */
  355.   if (rhdPtr->Card)
  356.   {
  357.     ConnectorIsDMS59 = rhdPtr->Card->flags & RHD_CARD_FLAG_DMS59;
  358.     if (ConnectorIsDMS59)
  359.             xf86DrvMsg(rhdPtr->scrnIndex, X_INFO, "Card %s has a DMS-59"
  360.                        " connector.\n", rhdPtr->Card->name);
  361.   }
  362.  
  363.     /* Check on the basis of Connector->HPD */
  364.   for (i = 0; i < RHD_CONNECTORS_MAX; i++)
  365.   {
  366.     Connector = rhdPtr->Connector[i];
  367.  
  368.     if (!Connector)
  369.             continue;
  370.  
  371.  
  372.         if (Connector->HPDCheck) {
  373.             if (Connector->HPDCheck(Connector)) {
  374.           Connector->HPDAttached = TRUE;
  375.           rhdOutputConnectorCheck(Connector);
  376.             } else {
  377.           Connector->HPDAttached = FALSE;
  378.           if (ConnectorIsDMS59)
  379.             rhdOutputConnectorCheck(Connector);
  380.             }
  381.         } else
  382.       rhdOutputConnectorCheck(Connector);
  383.   }
  384.  
  385.   i = 0; /* counter for CRTCs */
  386.   for (Output = rhdPtr->Outputs; Output; Output = Output->Next)
  387.         if (Output->Connector) {
  388.       struct rhdMonitor *Monitor = NULL;
  389.  
  390.       Connector = Output->Connector;
  391.  
  392.       Monitor = RHDMonitorInit(Connector);
  393.  
  394.             if (!Monitor && (Connector->Type == RHD_CONNECTOR_PANEL)) {
  395.                 xf86DrvMsg(rhdPtr->scrnIndex, X_WARNING, "Unable to attach a"
  396.                            " monitor to connector \"%s\"\n", Connector->Name);
  397.         Output->Active = FALSE;
  398.             } else if (!Output->AllocFree || Output->AllocFree(Output, RHD_OUTPUT_ALLOC)){
  399.         Connector->Monitor = Monitor;
  400.  
  401.         Output->Active = TRUE;
  402.  
  403.         Output->Crtc = rhdPtr->Crtc[i & 1]; /* ;) */
  404.         i++;
  405.  
  406.         Output->Crtc->Active = TRUE;
  407.  
  408.                 if (RHDScalePolicy(Monitor, Connector)) {
  409.                     Output->Crtc->ScaledToMode = RHDModeCopy(Monitor->NativeMode);
  410.                     xf86DrvMsg(rhdPtr->scrnIndex, X_INFO,
  411.                                "Crtc[%i]: found native mode from Monitor[%s]: ",
  412.                                Output->Crtc->Id, Monitor->Name);
  413.                     RHDPrintModeline(Output->Crtc->ScaledToMode);
  414.                 }
  415.         Found = TRUE;
  416.  
  417.                 if (Monitor) {
  418.   /* If this is a DVI attached monitor, enable reduced blanking.
  419.    * TODO: iiyama vm pro 453: CRT with DVI-D == No reduced.
  420.    */
  421.           if ((Output->Id == RHD_OUTPUT_TMDSA) ||
  422.               (Output->Id == RHD_OUTPUT_LVTMA) ||
  423.               (Output->Id == RHD_OUTPUT_KLDSKP_LVTMA) ||
  424.               (Output->Id == RHD_OUTPUT_UNIPHYA) ||
  425.               (Output->Id == RHD_OUTPUT_UNIPHYB))
  426.             Monitor->ReducedAllowed = TRUE;
  427.  
  428.                     /* allow user to override settings globally */
  429.           if (rhdPtr->forceReduced.set)
  430.             Monitor->ReducedAllowed = rhdPtr->forceReduced.val.bool;
  431.  
  432.           xf86DrvMsg(rhdPtr->scrnIndex, X_INFO,
  433.                      "Connector \"%s\" uses Monitor \"%s\":\n",
  434.                       Connector->Name, Monitor->Name);
  435.           RHDMonitorPrint(Monitor);
  436.                 } else
  437.           xf86DrvMsg(rhdPtr->scrnIndex, X_WARNING,
  438.                      "Connector \"%s\": Failed to retrieve Monitor"
  439.                      " information.\n", Connector->Name);
  440.       }
  441.     }
  442.  
  443.     /* Now validate the scaled modes attached to crtcs */
  444.     for (i = 0; i < 2; i++) {
  445.       struct rhdCrtc *crtc = rhdPtr->Crtc[i];
  446.         if (crtc->ScaledToMode && RHDValidateScaledToMode(crtc, crtc->ScaledToMode) != MODE_OK) {
  447.             xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "Crtc[%i]: scaled mode invalid.\n", crtc->Id);
  448.             xfree(crtc->ScaledToMode);
  449.             crtc->ScaledToMode = NULL;
  450.       }
  451.     }
  452.   return Found;
  453. }
  454.  
  455.      /*
  456.  *
  457.  */
  458. static void
  459. rhdModeLayoutPrint(RHDPtr rhdPtr)
  460. {
  461.     struct rhdCrtc *Crtc;
  462.     struct rhdOutput *Output;
  463.     Bool Found;
  464.  
  465.     xf86DrvMsg(rhdPtr->scrnIndex, X_INFO, "Listing modesetting layout:\n\n");
  466.  
  467.     /* CRTC 1 */
  468.     Crtc = rhdPtr->Crtc[0];
  469.     if (Crtc->Active) {
  470.         xf86Msg(X_NONE, "\t%s: tied to %s and %s:\n",
  471.                 Crtc->Name, Crtc->PLL->Name, Crtc->LUT->Name);
  472.  
  473.         Found = FALSE;
  474.         for (Output = rhdPtr->Outputs; Output; Output = Output->Next)
  475.             if (Output->Active && (Output->Crtc == Crtc)) {
  476.                 if (!Found) {
  477.                     xf86Msg(X_NONE, "\t\tOutputs: %s (%s)",
  478.                             Output->Name, Output->Connector->Name);
  479.                     Found = TRUE;
  480.                 } else
  481.                     xf86Msg(X_NONE, ", %s (%s)", Output->Name,
  482.                             Output->Connector->Name);
  483.             }
  484.  
  485.         if (!Found)
  486.             xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR,
  487.                        "%s is active without outputs\n", Crtc->Name);
  488.         else
  489.              xf86Msg(X_NONE, "\n");
  490.     } else
  491.         xf86Msg(X_NONE, "\t%s: unused\n", Crtc->Name);
  492.     xf86Msg(X_NONE, "\n");
  493.  
  494.     /* CRTC 2 */
  495.     Crtc = rhdPtr->Crtc[1];
  496.     if (Crtc->Active) {
  497.         xf86Msg(X_NONE, "\t%s: tied to %s and %s:\n",
  498.                 Crtc->Name, Crtc->PLL->Name, Crtc->LUT->Name);
  499.  
  500.         Found = FALSE;
  501.         for (Output = rhdPtr->Outputs; Output; Output = Output->Next)
  502.             if (Output->Active && (Output->Crtc == Crtc)) {
  503.                 if (!Found) {
  504.                     xf86Msg(X_NONE, "\t\tOutputs: %s (%s)",
  505.                             Output->Name, Output->Connector->Name);
  506.                     Found = TRUE;
  507.                 } else
  508.                     xf86Msg(X_NONE, ", %s (%s)", Output->Name,
  509.                             Output->Connector->Name);
  510.             }
  511.  
  512.         if (!Found)
  513.             xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR,
  514.                        "%s is active without outputs\n", Crtc->Name);
  515.         else
  516.             xf86Msg(X_NONE, "\n");
  517.     } else
  518.         xf86Msg(X_NONE, "\t%s: unused\n", Crtc->Name);
  519.     xf86Msg(X_NONE, "\n");
  520.  
  521.     /* Print out unused Outputs */
  522.     Found = FALSE;
  523.     for (Output = rhdPtr->Outputs; Output; Output = Output->Next)
  524.         if (!Output->Active) {
  525.             if (!Found) {
  526.                 xf86Msg(X_NONE, "\t\tUnused Outputs: %s", Output->Name);
  527.                 Found = TRUE;
  528.             } else
  529.                 xf86Msg(X_NONE, ", %s", Output->Name);
  530.         }
  531.  
  532.     if (Found)
  533.         xf86Msg(X_NONE, "\n");
  534.     xf86Msg(X_NONE, "\n");
  535. }
  536.  
  537.  
  538. DisplayModePtr
  539. rhdCreateModesListAndValidate(ScrnInfoPtr pScrn, Bool Silent);
  540. void RHDPrintModeline(DisplayModePtr mode);
  541.  
  542. int RHDPreInit()
  543. {
  544.     RHDI2CDataArg i2cArg;
  545.     RHDPtr rhdPtr = &rhd;
  546.  
  547.     /* We need access to IO space already */
  548.     if (!rhdMapMMIO()) {
  549.         dbgprintf("Failed to map MMIO.\n");
  550.         return 0;
  551.     };
  552.  
  553.  
  554.     if (RHDIsIGP(rhd.ChipSet))
  555.         rhdGetIGPNorthBridgeInfo(&rhd);
  556.  
  557.     rhd.Card = RHDCardIdentify(&rhd);
  558.     if (rhd.Card)
  559.         dbgprintf("Detected an %s on a %s\n", rhd.chipset_name, rhd.Card->name);
  560.     else
  561.         dbgprintf("Detected an %s on an unidentified card\n", rhd.chipset_name);
  562.  
  563.     if (rhdPtr->Card && rhdPtr->Card->flags & RHD_CARD_FLAG_HPDSWAP &&
  564.         rhdPtr->hpdUsage == RHD_HPD_USAGE_AUTO)
  565.         rhdPtr->hpdUsage = RHD_HPD_USAGE_AUTO_SWAP;
  566.     if (rhdPtr->Card && rhdPtr->Card->flags & RHD_CARD_FLAG_HPDOFF &&
  567.         rhdPtr->hpdUsage == RHD_HPD_USAGE_AUTO)
  568.         rhdPtr->hpdUsage = RHD_HPD_USAGE_AUTO_OFF;
  569.  
  570.     rhdPtr->cardType = rhdGetCardType(rhdPtr);
  571.  
  572.  
  573.     {
  574.         AtomBiosArgRec atomBiosArg;
  575.  
  576.         rhd.UseAtomFlags = (RHD_ATOMBIOS_ON << RHD_ATOMBIOS_CRTC)    |
  577.                            (RHD_ATOMBIOS_ON << RHD_ATOMBIOS_OUTPUT)  |
  578.                            (RHD_ATOMBIOS_ON << RHD_ATOMBIOS_PLL);
  579.  
  580.    // rhd.UseAtomFlags = 0;
  581.  
  582.         if (RHDAtomBiosFunc(&rhd, NULL, ATOMBIOS_INIT, &atomBiosArg) == ATOM_SUCCESS)
  583.         {
  584.             rhd.atomBIOS = atomBiosArg.atomhandle;
  585.         }
  586.     }
  587.  
  588.     rhd.videoRam = rhdGetVideoRamSize(&rhd);
  589.     if (!rhd.videoRam)
  590.     {
  591.         dbgprintf("No Video RAM detected.\n");
  592.             goto error1;
  593.         }
  594.     dbgprintf("VideoRAM: %d kByte\n",rhd.videoRam);
  595.  
  596.     if (rhd.atomBIOS)                        /* for testing functions */
  597.     {
  598.         AtomBiosArgRec atomBiosArg;
  599.  
  600.         atomBiosArg.fb.start = rhd.FbFreeStart;
  601.         atomBiosArg.fb.size = rhd.FbFreeSize;
  602.         if (RHDAtomBiosFunc(&rhd, rhd.atomBIOS, ATOMBIOS_ALLOCATE_FB_SCRATCH,
  603.                             &atomBiosArg) == ATOM_SUCCESS)
  604.         {
  605.             rhd.FbFreeStart = atomBiosArg.fb.start;
  606.             rhd.FbFreeSize = atomBiosArg.fb.size;
  607.         };
  608.         RHDAtomBiosFunc(&rhd, rhd.atomBIOS, GET_DEFAULT_ENGINE_CLOCK, &atomBiosArg);
  609.         RHDAtomBiosFunc(&rhd, rhd.atomBIOS, GET_DEFAULT_MEMORY_CLOCK, &atomBiosArg);
  610.         RHDAtomBiosFunc(&rhd, rhd.atomBIOS, GET_MAX_PIXEL_CLOCK_PLL_OUTPUT, &atomBiosArg);
  611.         RHDAtomBiosFunc(&rhd, rhd.atomBIOS, GET_MIN_PIXEL_CLOCK_PLL_OUTPUT, &atomBiosArg);
  612.         RHDAtomBiosFunc(&rhd, rhd.atomBIOS, GET_MAX_PIXEL_CLOCK_PLL_INPUT, &atomBiosArg);
  613.         RHDAtomBiosFunc(&rhd, rhd.atomBIOS, GET_MIN_PIXEL_CLOCK_PLL_INPUT, &atomBiosArg);
  614.         RHDAtomBiosFunc(&rhd, rhd.atomBIOS, GET_MAX_PIXEL_CLK, &atomBiosArg);
  615.         RHDAtomBiosFunc(&rhd, rhd.atomBIOS, GET_REF_CLOCK, &atomBiosArg);
  616.     }
  617.  
  618.  
  619.     rhd.FbFreeStart = 0;
  620.     rhd.FbFreeSize = rhd.videoRam << 10;
  621.  
  622.  
  623.     if (RHDI2CFunc((int)&rhd, NULL, RHD_I2C_INIT, &i2cArg) == RHD_I2C_SUCCESS)
  624.         rhd.I2C = i2cArg.I2CBusList;
  625.     else
  626.     {
  627.         dbgprintf("I2C init failed\n");
  628.         goto error1;
  629.     };
  630.  
  631.     if (!rhd.atomBIOS)
  632.     {
  633.         dbgprintf("No ATOMBIOS detected.  Done.\n");
  634.         return 0;
  635.     }
  636.  
  637. //  rhdMapFB(&rhd);
  638.  
  639.     Scrn.rhdPtr       = &rhd;
  640.     Scrn.driverName   = "Radeon HD driver";
  641.     Scrn.bitsPerPixel = 32;
  642.     Scrn.depth        = 32;
  643.     Scrn.virtualX     = 1280;
  644.     Scrn.virtualY     = 1024;
  645.     Scrn.displayWidth = 1280;
  646.  
  647.     rhd.pScrn = &Scrn;
  648.  
  649.     rhd.FbScanoutStart = 0;
  650.     rhd.FbScanoutSize  = 8*1024*1024;
  651.     rhd.FbFreeStart    = 8*1024*1024;
  652.     rhd.FbFreeSize     = rhd.FbMapSize - 8*1024*1024;
  653.  
  654.     rhdInitHeap(&rhd);
  655.  
  656.     RHDVGAInit(&rhd);
  657.     RHDMCInit(&rhd);
  658.  
  659.     if (!RHDCrtcsInit(&rhd))
  660.         RHDAtomCrtcsInit(&rhd);
  661.     if (!RHDPLLsInit(&rhd))
  662.         RHDAtomPLLsInit(&rhd);
  663.  
  664.     RHDLUTsInit(&rhd);
  665.  
  666.     if (!RHDConnectorsInit(&rhd, rhd.Card))
  667.     {
  668.         dbgprintf("Card information has invalid connector information\n");
  669.         goto error1;
  670.     }
  671.  
  672.     {
  673.         struct rhdAtomOutputDeviceList *OutputDeviceList = NULL;
  674.  
  675.         if (rhdPtr->Card
  676.             && rhdPtr->Card->ConnectorInfo[0].Type != RHD_CONNECTOR_NONE
  677.             && (rhdPtr->Card->DeviceInfo[0][0] != atomNone
  678.             || rhdPtr->Card->DeviceInfo[0][1] != atomNone))
  679.         {
  680.             int i, k = 0;
  681.  
  682.             for (i = 0; i < RHD_CONNECTORS_MAX; i++)
  683.             {
  684.                 int j;
  685.                 if (rhdPtr->Card->ConnectorInfo[i].Type == RHD_CONNECTOR_NONE)
  686.                     break;
  687.                 for (j = 0; j < MAX_OUTPUTS_PER_CONNECTOR; j++)
  688.                 {
  689.                     if (rhdPtr->Card->ConnectorInfo[i].Output[j] != RHD_OUTPUT_NONE)
  690.                     {
  691.                         if (!(OutputDeviceList =
  692.                              (struct rhdAtomOutputDeviceList *)
  693.                               xrealloc(OutputDeviceList,
  694.                                        sizeof (struct rhdAtomOutputDeviceList) * (k + 1))))
  695.                             break;
  696.                         OutputDeviceList[k].ConnectorType = rhdPtr->Card->ConnectorInfo[i].Type;
  697.                         OutputDeviceList[k].DeviceId = rhdPtr->Card->DeviceInfo[i][j];
  698.                         OutputDeviceList[k].OutputType = rhdPtr->Card->ConnectorInfo[i].Output[j];
  699.                         dbgprintf("OutputDevice: C: 0x%2.2x O: 0x%2.2x DevID: 0x%2.2x\n",
  700.                                    OutputDeviceList[k].ConnectorType,
  701.                                    OutputDeviceList[k].OutputType,
  702.                                    OutputDeviceList[k].DeviceId);
  703.                         k++;
  704.                     }
  705.                 }
  706.             }
  707.         }
  708.         else
  709.         {
  710.             AtomBiosArgRec data;
  711.  
  712.             data.chipset = rhdPtr->ChipSet;
  713.             if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
  714.                                 ATOMBIOS_GET_OUTPUT_DEVICE_LIST, &data) == ATOM_SUCCESS)
  715.                 OutputDeviceList = data.OutputDeviceList;
  716.         }
  717.  
  718.         if (OutputDeviceList)
  719.         {
  720.             struct rhdOutput *Output;
  721.  
  722.             for (Output = rhdPtr->Outputs; Output; Output = Output->Next)
  723.                 RHDAtomSetupOutputDriverPrivate(OutputDeviceList, Output);
  724.             xfree(OutputDeviceList);
  725.         }
  726.     }
  727.  
  728.  
  729.     if (!rhdModeLayoutSelect(&rhd))
  730.     {
  731.         dbgprintf("Failed to detect a connected monitor\n");
  732.         goto error1;
  733.         }
  734.  
  735.     RHDConfigMonitorSet(&rhd, FALSE);
  736.     rhdModeLayoutPrint(&rhd);
  737.  
  738.     {
  739.         DisplayModePtr Modes, tmp;
  740.  
  741.         Modes = RHDModesPoolCreate(&Scrn, FALSE);
  742.         Scrn.modePool = Modes;
  743.  
  744.         tmp = Modes;
  745.         SupportedModes=0;
  746.         while(tmp)
  747.         {
  748.             dbgprintf("%dx%d@%3.1fHz\n",tmp->CrtcHDisplay,
  749.                       tmp->CrtcVDisplay,tmp->VRefresh);
  750.             tmp=tmp->next;
  751.             SupportedModes++;
  752.         };
  753. //    rhdModeInit(&Scrn,Modes);
  754.     //RHDAdjustFrame(&rhd,0,0,0);
  755.     };
  756.     dbgprintf("All done\n");
  757.     return 1;
  758.  
  759. error1:
  760.     return 0;
  761. };
  762.  
  763. int __stdcall drvEntry(int action)
  764. {
  765.     int i;
  766.  
  767.     if(action != 1)
  768.         return 0;
  769.  
  770.     if(!dbg_open("/rd/1/drivers/ati.txt"))
  771.     {
  772.         printf("Can't open /rd/1/drivers/ati.txt\nExit\n");
  773.         return 0;
  774.     }
  775.     if(!FindPciDevice())
  776.         return 0;
  777.  
  778.     rhd.scrnIndex = (int)&rhd;
  779.  
  780.     for(i=0;i<6;i++)
  781.     {
  782.         if(rhd.pci.memBase[i])
  783.             dbgprintf("Memory base_%d 0x%x size 0x%x\n",
  784.                       i,rhd.pci.memBase[i],(1<<rhd.pci.size[i]));
  785.     };
  786.     for(i=0;i<6;i++)
  787.     {
  788.         if(rhd.pci.ioBase[i])
  789.             dbgprintf("Io base_%d 0x%x size 0x%x\n",
  790.                       i,rhd.pci.ioBase[i],(1<<rhd.pci.size[i]));
  791.     };
  792.     if(RHDPreInit()==0)
  793.         return 0;
  794.  
  795.     return RegService("RHD", srv_proc);
  796. };
  797.  
  798.  
  799. void usleep(u32_t delay)
  800. {
  801.   if(!delay) delay++;
  802.   delay*=1000;
  803.  
  804.   asm(
  805.      "1:\n\t"
  806.       "xor eax, eax \n\t"
  807.       "cpuid \n\t"
  808.       "dec edi \n\t"
  809.       "jnz 1b"
  810.       :
  811.       :"D"(delay)
  812.       :"eax","ebx","ecx","edx"
  813.      );
  814. }
  815.  
  816.  
  817. //git://anongit.freedesktop.org/git/xorg/xserver
  818. //git://anongit.freedesktop.org/git/xorg/lib/libpciaccess
  819.  
  820. int KernelFree(void *p)
  821. {
  822.  
  823.   return 0;
  824. }
  825.  
  826. static void
  827. rhdPrepareMode(RHDPtr rhdPtr)
  828. {
  829.     RHDFUNC(rhdPtr);
  830.  
  831.     /* no active outputs == no mess */
  832.     RHDOutputsPower(rhdPtr, RHD_POWER_RESET);
  833. }
  834.  
  835. /*
  836.  * */static void
  837. rhdModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
  838. {
  839.     RHDPtr rhdPtr = pScrn->rhdPtr;
  840.  
  841.     RHDFUNC(rhdPtr);
  842.  
  843.     rhdSetMode(pScrn, mode);
  844. }
  845.  
  846. /* * */static void
  847. rhdSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
  848. {
  849.     RHDPtr rhdPtr = RHDPTR(pScrn);
  850.     int i;
  851.  
  852.     RHDFUNC(rhdPtr);
  853.  
  854.     xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting up \"%s\" (%dx%d@%3.1fHz)\n",
  855.                mode->name, mode->CrtcHDisplay, mode->CrtcVDisplay,
  856.                mode->VRefresh);
  857.  
  858.     /* Set up D1/D2 and appendages */
  859.     for (i = 0; i < 2; i++) {
  860.         struct rhdCrtc *Crtc;
  861.  
  862.         Crtc = rhdPtr->Crtc[i];
  863.         if (Crtc->Active) {
  864.             Crtc->FBSet(Crtc, pScrn->displayWidth, pScrn->virtualX, pScrn->virtualY,
  865.                         pScrn->depth, rhdPtr->FbScanoutStart);
  866.             if (Crtc->ScaledToMode) {
  867.                 Crtc->ModeSet(Crtc, Crtc->ScaledToMode);
  868.                 if (Crtc->ScaleSet)
  869.                     Crtc->ScaleSet(Crtc, Crtc->ScaleType, mode, Crtc->ScaledToMode);
  870.             } else {
  871.                 Crtc->ModeSet(Crtc, mode);
  872.                 if (Crtc->ScaleSet)
  873.                     Crtc->ScaleSet(Crtc, RHD_CRTC_SCALE_TYPE_NONE, mode, NULL);
  874.             }
  875.             RHDPLLSet(Crtc->PLL, mode->Clock);
  876.             Crtc->LUTSelect(Crtc, Crtc->LUT);
  877.             RHDOutputsMode(rhdPtr, Crtc, Crtc->ScaledToMode
  878.                            ? Crtc->ScaledToMode : mode);
  879.         }
  880.     }
  881.  
  882.     /* shut down that what we don't use */
  883.     RHDPLLsShutdownInactive(rhdPtr);
  884.     RHDOutputsShutdownInactive(rhdPtr);
  885.  
  886.     if (rhdPtr->Crtc[0]->Active)
  887.         rhdPtr->Crtc[0]->Power(rhdPtr->Crtc[0], RHD_POWER_ON);
  888.     else
  889.         rhdPtr->Crtc[0]->Power(rhdPtr->Crtc[0], RHD_POWER_SHUTDOWN);
  890.  
  891.     if (rhdPtr->Crtc[1]->Active)
  892.         rhdPtr->Crtc[1]->Power(rhdPtr->Crtc[1], RHD_POWER_ON);
  893.     else
  894.         rhdPtr->Crtc[1]->Power(rhdPtr->Crtc[1], RHD_POWER_SHUTDOWN);
  895.  
  896.     RHDOutputsPower(rhdPtr, RHD_POWER_ON);
  897. }
  898.  
  899.  
  900.  
  901. static void
  902. RHDAdjustFrame(RHDPtr rhdPtr, int x, int y, int flags)
  903. {
  904. //    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
  905. //    RHDPtr rhdPtr = RHDPTR(pScrn);
  906.     struct rhdCrtc *Crtc;
  907.  
  908.         Crtc = rhdPtr->Crtc[0];
  909.   if (Crtc->Active)
  910.     Crtc->FrameSet(Crtc, x, y);
  911.  
  912.         Crtc = rhdPtr->Crtc[1];
  913.   if ( Crtc->Active)
  914.             Crtc->FrameSet(Crtc, x, y);
  915.  
  916. }
  917.  
  918. static Bool
  919. rhdMapFB(RHDPtr rhdPtr)
  920. {
  921.     CARD32 membase;
  922.     RHDFUNC(rhdPtr);
  923.  
  924.     rhdPtr->FbMapSize = 1 << rhdPtr->pci.size[RHD_FB_BAR];
  925.     membase = rhdPtr->pci.memBase[RHD_FB_BAR];
  926.  
  927.     rhdPtr->FbBase = MapIoMem(membase, rhdPtr->FbMapSize,PG_SW+PG_NOCACHE);
  928.  
  929.     if (!rhdPtr->FbBase)
  930.         return FALSE;
  931.  
  932.     /* These devices have an internal address reference, which some other
  933.      * address registers in there also use. This can be different from the
  934.      * address in the BAR */
  935.     if (rhdPtr->ChipSet < RHD_R600)
  936.       rhdPtr->FbIntAddress = _RHDRegRead(rhdPtr, HDP_FB_LOCATION)<< 16;
  937.     else
  938.       rhdPtr->FbIntAddress = _RHDRegRead(rhdPtr, R6XX_CONFIG_FB_BASE);
  939.  
  940.     if (rhdPtr->FbIntAddress != membase)
  941.       dbgprintf("PCI FB Address (BAR) is at "
  942.                 "0x%08X while card Internal Address is 0x%08X\n",
  943.                 (unsigned int) membase,rhdPtr->FbIntAddress);
  944.     dbgprintf("Mapped FB at %p (size 0x%08X)\n",rhdPtr->FbBase, rhdPtr->FbMapSize);
  945.     return TRUE;
  946. }
  947.  
  948.  
  949. #define ERR_PARAM  -1
  950.  
  951. #pragma pack (push,1)
  952. typedef struct
  953. {
  954.   short width;
  955.   short height;
  956.   short bpp;
  957.   short freq;
  958. }mode_t;
  959. #pragma pack (pop)
  960.  
  961. int get_modes(mode_t *mode, int count)
  962. {
  963.   if(count==0)
  964.     count = SupportedModes;
  965.   else
  966.   {
  967.     DisplayModePtr tmp;
  968.     int i;
  969.  
  970.     if(count>SupportedModes)
  971.       count = SupportedModes;
  972.  
  973.     for(i=0,tmp = Scrn.modePool;i<count;i++,tmp=tmp->next,mode++)
  974.     {
  975.       mode->width = tmp->CrtcHDisplay;
  976.       mode->height = tmp->CrtcVDisplay;
  977.       mode->bpp = 32;
  978.       mode->freq = (short)__builtin_ceilf(tmp->VRefresh);
  979.     }
  980.   }
  981.   return count;
  982. }
  983.  
  984. int set_mode(mode_t *mode)
  985. {
  986.   DisplayModePtr tmp;
  987.   int i;
  988.  
  989.   for(i=0,tmp = Scrn.modePool;i<SupportedModes;i++,tmp=tmp->next)
  990.   {
  991.     if( (mode->width == tmp->CrtcHDisplay) &&
  992.         (mode->height == tmp->CrtcVDisplay) &&
  993.         (mode->freq ==  (short)__builtin_ceilf(tmp->VRefresh)))
  994.     {
  995.       Scrn.virtualX = mode->width ;
  996.       Scrn.virtualY = mode->height;
  997.       Scrn.displayWidth = mode->width;
  998.       rhdModeInit(&Scrn,tmp);
  999.       sysSetScreen(mode->width,mode->height);
  1000.       dbgprintf("set_mode OK\n");
  1001.       return 1;
  1002.     };
  1003.   }
  1004.   return 0;
  1005. };
  1006.  
  1007. #define API_VERSION     0x01000100
  1008.  
  1009. #define SRV_GETVERSION  0
  1010. #define SRV_ENUM_MODES  1
  1011. #define SRV_SET_MODE    2
  1012.  
  1013. int _stdcall srv_proc(ioctl_t *io)
  1014. {
  1015.   u32_t *inp;
  1016.   u32_t *outp;
  1017.  
  1018.   inp = io->input;
  1019.   outp = io->output;
  1020.  
  1021.   switch(io->io_code)
  1022.   {
  1023.     case SRV_GETVERSION:
  1024.       if(io->out_size==4)
  1025.       {
  1026.         *(u32_t*)io->output = API_VERSION;
  1027.         return 0;
  1028.       }
  1029.       break;
  1030.     case SRV_ENUM_MODES:
  1031.       if(io->inp_size==8)
  1032.       {
  1033.         int count;
  1034.         count = get_modes((mode_t*)(*inp),(int)*(inp+1));
  1035.  
  1036.         if(io->out_size==4)
  1037.         {
  1038.           *outp = count;
  1039.           return 0;
  1040.         }
  1041.       };
  1042.       break;
  1043.     case SRV_SET_MODE:
  1044.       if(io->inp_size==8)
  1045.       {
  1046.         int err;
  1047.         err = set_mode((mode_t*)inp);
  1048.  
  1049.         if(io->out_size==4)
  1050.         {
  1051.           *outp = err;
  1052.           return 0;
  1053.         }
  1054.       };
  1055.       break;
  1056.  
  1057.   };
  1058.  
  1059.   return -1;
  1060. }
  1061.  
  1062.  
  1063. CARD32
  1064. _RHDReadMC(int scrnIndex, CARD32 addr)
  1065. {
  1066.     RHDPtr rhdPtr = (RHDPtr)scrnIndex;
  1067.     CARD32 ret;
  1068.  
  1069.     if (rhdPtr->ChipSet < RHD_RS600) {
  1070.       _RHDRegWrite(rhdPtr, MC_IND_INDEX, addr);
  1071.       ret = _RHDRegRead(rhdPtr, MC_IND_DATA);
  1072.     } else if (rhdPtr->ChipSet == RHD_RS600) {
  1073.       _RHDRegWrite(rhdPtr, RS60_MC_NB_MC_INDEX, addr);
  1074.       ret = _RHDRegRead(rhdPtr, RS60_MC_NB_MC_DATA);
  1075.     } else if (rhdPtr->ChipSet == RHD_RS690 || rhdPtr->ChipSet == RHD_RS740) {
  1076.         pciWriteLong(rhdPtr->NBPciTag, RS69_MC_INDEX, addr & ~RS69_MC_IND_WR_EN);
  1077.         ret = pciReadLong(rhdPtr->NBPciTag, RS69_MC_DATA);
  1078.     } else {
  1079.         pciWriteLong(rhdPtr->NBPciTag, RS78_NB_MC_IND_INDEX, (addr & ~RS78_MC_IND_WR_EN));
  1080.         ret = pciReadLong(rhdPtr->NBPciTag, RS78_NB_MC_IND_DATA);
  1081.     }
  1082.  
  1083.     RHDDebug(scrnIndex,"%s(0x%08X) = 0x%08X\n",__func__,(unsigned int)addr,
  1084.              (unsigned int)ret);
  1085.     return ret;
  1086. }
  1087.  
  1088. void
  1089. _RHDWriteMC(int scrnIndex, CARD32 addr, CARD32 data)
  1090. {
  1091.     RHDPtr rhdPtr = (RHDPtr)scrnIndex;
  1092.  
  1093.     RHDDebug(scrnIndex,"%s(0x%08X, 0x%08X)\n",__func__,(unsigned int)addr,
  1094.              (unsigned int)data);
  1095.  
  1096.     if (rhdPtr->ChipSet < RHD_RS600) {
  1097.       _RHDRegWrite(rhdPtr, MC_IND_INDEX, addr | MC_IND_WR_EN);
  1098.       _RHDRegWrite(rhdPtr, MC_IND_DATA, data);
  1099.     } else if (rhdPtr->ChipSet == RHD_RS600) {
  1100.       _RHDRegWrite(rhdPtr, RS60_MC_NB_MC_INDEX, addr | RS60_NB_MC_IND_WR_EN);
  1101.       _RHDRegWrite(rhdPtr, RS60_MC_NB_MC_DATA, data);
  1102.     } else if (rhdPtr->ChipSet == RHD_RS690 || rhdPtr->ChipSet == RHD_RS740) {
  1103.       pciWriteLong(rhdPtr->NBPciTag, RS69_MC_INDEX, addr | RS69_MC_IND_WR_EN);
  1104.       pciWriteLong(rhdPtr->NBPciTag, RS69_MC_DATA, data);
  1105.     } else  {
  1106.       pciWriteLong(rhdPtr->NBPciTag, RS78_NB_MC_IND_INDEX, addr | RS78_MC_IND_WR_EN);
  1107.       pciWriteLong(rhdPtr->NBPciTag, RS78_NB_MC_IND_DATA, data);
  1108.     }
  1109. }
  1110.  
  1111. /*
  1112.  *
  1113.  */
  1114. static void
  1115. rhdGetIGPNorthBridgeInfo(RHDPtr rhdPtr)
  1116. {
  1117.     switch (rhdPtr->ChipSet)
  1118.     {
  1119.         case RHD_RS600:
  1120.             break;
  1121.         case RHD_RS690:
  1122.         case RHD_RS740:
  1123.         case RHD_RS780:
  1124.             rhdPtr->NBPciTag = pciTag(0,0,0);
  1125.             break;
  1126.         default:
  1127.             break;
  1128.     }
  1129. }
  1130.  
  1131. static enum rhdCardType
  1132. rhdGetCardType(RHDPtr rhdPtr)
  1133. {
  1134.     CARD32 cmd_stat;
  1135.  
  1136.     if (rhdPtr->ChipSet == RHD_RS780)
  1137.         return RHD_CARD_PCIE;
  1138.  
  1139.     cmd_stat = pciReadLong(rhdPtr->PciTag, PCI_CMD_STAT_REG);
  1140.  
  1141.     if (cmd_stat & 0x100000) {
  1142.         CARD32 cap_ptr, cap_id;
  1143.  
  1144.         cap_ptr = pciReadLong(rhdPtr->PciTag, 0x34);
  1145.         cap_ptr &= 0xfc;
  1146.  
  1147.         while (cap_ptr)
  1148.         {
  1149.             cap_id = pciReadLong(rhdPtr->PciTag, cap_ptr);
  1150.             switch (cap_id & 0xff) {
  1151.                 case RHD_PCI_CAPID_AGP:
  1152.                     xf86DrvMsg(rhdPtr->scrnIndex, X_INFO, "AGP Card Detected\n");
  1153.                     return RHD_CARD_AGP;
  1154.                 case RHD_PCI_CAPID_PCIE:
  1155.                     xf86DrvMsg(rhdPtr->scrnIndex, X_INFO, "PCIE Card Detected\n");
  1156.                     return RHD_CARD_PCIE;
  1157.             }
  1158.             cap_ptr = (cap_id >> 8) & 0xff;
  1159.         }
  1160.     }
  1161.     return RHD_CARD_NONE;
  1162. }
  1163.  
  1164.  
  1165.