免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1778 | 回复: 0
打印 上一主题 下一主题

medfield 平台 lvds bridge 驱动与console的关系 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-22 08:51 |只看该作者 |倒序浏览
这也是个I2C 驱动,挂接在 I2C_2 总线上。

初始化如下:

  1. /* ************************************************************************* *\
  2.  * FUNCTION: dsi_lvds_bridge_init
  3.  *
  4.  * DESCRIPTION: Driver Init function for lvds bridge
  5.  *
  6. \* ************************************************************************* */
  7. static int __init dsi_lvds_bridge_init(void)
  8. {
  9.     int ret = 0;
  10.     struct i2c_adapter *adapter = NULL;
  11.     struct i2c_client *client = NULL;
  12.     struct i2c_board_info info;

  13.     printk(KERN_INFO "[DISPLAY] %s: Enter\n", __func__);

  14.     ret = misc_register(&dsi_lvds_bridge_dev);
  15.     if (ret) {
  16.         printk(KERN_ERR "[DISPLAY] %s: Can not register misc device.\n", __func__);
  17.         return ret;
  18.     }

  19.     adapter = i2c_get_adapter(2); /*DV0 is on I2C bus 2 */
  20.     if (!adapter) {
  21.         printk(KERN_ERR "[DISPLAY] %s: Can not get bridge i2c adapter.\n", __func__);
  22.         return 0;
  23.     }

  24.     /* Setup the i2c board info with the device type and
  25.      the device address. */
  26.     memset(&info, 0, sizeof(info));
  27.     strlcpy(info.type, "i2c_disp_brig", sizeof(info.type));

  28.     info.addr = 0x0F; /*I2C2 address 0x0F */

  29.     /* Create the i2c client */
  30.     client = i2c_new_device(adapter, &info);
  31.     if (!client) {
  32.         printk(KERN_ERR "[DISPLAY] %s: ERROR, i2c client=NULL\n", __func__);
  33.         return -1;
  34.     }

  35.     ret = i2c_add_driver(&dsi_lvds_bridge_i2c_driver);

  36.     printk(KERN_INFO "[DISPLAY] %s: Exit, ret = %d\n", __func__, ret);

  37.     return 0;
  38. }

  1. /* ************************************************************************* *\
  2.  * FUNCTION: dsi_lvds_bridge_exit
  3.  *
  4.  * DESCRIPTION: Driver exit function for lvds bridge
  5.  *
  6. \* ************************************************************************* */
  7. static void __exit dsi_lvds_bridge_exit(void)
  8. {
  9.     printk(KERN_INFO "[DISPLAY] %s\n", __func__);

  10.     misc_deregister(&dsi_lvds_bridge_dev);

  11.     i2c_del_driver(&dsi_lvds_bridge_i2c_driver);
  12. }


  13. module_init(dsi_lvds_bridge_init);
  14. module_exit(dsi_lvds_bridge_exit);

初始化用到的几个结构体:

  1. static const struct i2c_device_id dsi_lvds_bridge_id[] = {
  2.     { "i2c_disp_brig", 0 },
  3.     { }
  4. };
  5. MODULE_DEVICE_TABLE(i2c, dsi_lvds_bridge_id);

  6. static struct i2c_driver dsi_lvds_bridge_i2c_driver = {
  7.     .driver = {
  8.         .name = "i2c_disp_brig",
  9.     },
  10.     .id_table = dsi_lvds_bridge_id,
  11.     .probe = dsi_lvds_bridge_probe,
  12.     .remove = dsi_lvds_bridge_remove,
  13. };

  1. static const struct file_operations mipi_dsi_dev_fops = {
  2.     .owner = THIS_MODULE,
  3.     .unlocked_ioctl = dsi_lvds_dev_ioctl,
  4. };

  5. static struct miscdevice dsi_lvds_bridge_dev = {
  6.     .minor = MISC_DYNAMIC_MINOR,
  7.     .name = "mipi_dsi",
  8.     .fops = &mipi_dsi_dev_fops,
  9. };

dsi_lvds_bridge_probe()

  1. /* ************************************************************************* *\
  2.  * FUNCTION: dsi_lvds_bridge_probe
  3.  *
  4.  * DESCRIPTION: Probe function for LVDS bridge.
  5.  *
  6. \* ************************************************************************* */
  7. static int dsi_lvds_bridge_probe(struct i2c_client *client, const struct i2c_device_id *id)
  8. {
  9.     printk(KERN_INFO "[DISPLAY] %s: Enter\n", __func__);

  10.     if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
  11.         printk(KERN_ERR "[DISPLAY] %s: Check I2C functionality failed.\n", __func__);
  12.         return -ENODEV;
  13.     }

  14.     dsi_lvds_inst = kzalloc(sizeof(struct dsi_lvds_bridge_instance), GFP_KERNEL);

  15.     if (dsi_lvds_inst == NULL) {
  16.         printk(KERN_ERR "[DISPLAY] %s: Can not allocate memory.\n", __func__);
  17.         return -ENOMEM;
  18.     }

  19.     dsi_lvds_inst->client = client;

  20.     i2c_set_clientdata(client, dsi_lvds_inst);

  21.     dsi_lvds_inst->client->addr = 0x0F;

  22.     printk(KERN_INFO "[DISPLAY] %s: Exit\n", __func__);

  23.     return 0;
  24. }
1. use GPIO to reset lvds state

  1. /* ************************************************************************* *\
  2.  * FUNCTION: dsi_lvds_set_bridge_reset_state
  3.  *
  4.  * DESCRIPTION: This function uses GPIO to force in and out of reset state.
  5. \* ************************************************************************* */
  6. void dsi_lvds_set_bridge_reset_state(int state)
  7. {
  8.     printk(KERN_INFO "[DISPLAY ] %s: state = %d, gpio = %d\n", __func__, state, gpio_get_value(GPIO_MIPI_BRIDGE_RESET));

  9.     if (state) {
  10.         gpio_direction_output(GPIO_MIPI_BRIDGE_RESET, 0);
  11.         gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 0);
  12.         mdelay(10);
  13.     } else {

  14.         gpio_direction_output(GPIO_MIPI_BRIDGE_RESET, 0);
  15.         gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 0); /*Pull MIPI Bridge reset pin to Low */
  16.         mdelay(20);
  17.         gpio_direction_output(GPIO_MIPI_BRIDGE_RESET, 1);
  18.         gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 1); /*Pull MIPI Bridge reset pin to High */
  19.         mdelay(40);
  20.     }
  21. }

2. dsi_lvds_configure_lvds_bridge () , 用I2C总线,配置lvds bridge设备。

  1. /* ************************************************************************* *\
  2.  * FUNCTION: dsi_lvds_configure_lvds_bridge
  3.  *
  4.  * DESCRIPTION: This function uses I2C interface to set bridge registers.
  5.  * to configure timings and MIPI lanes.
  6. \* ************************************************************************* */
  7. void dsi_lvds_configure_lvds_bridge(struct drm_device *dev)
  8. {
  9.     if (lvds_disp_init) {
  10.         printk(KERN_ALERT "[DISPLAY ] %s is already initialized\n", __func__);
  11.         return;
  12.     }

  13.     printk(KERN_INFO "[DISPLAY ]%s: Enter\n", __func__);

  14.     DSI_I2C_ByteWrite(0x013C, 0x00050006, 6); /*PPI_TX_RX_TA, BTA parameters */
  15.     DSI_I2C_ByteRead(0x013C, 4);
  16.     DSI_I2C_ByteWrite(0x0114, 0x00000004, 6); /*PPI_LPTXTIMCNT */

  17. #ifdef FIXME_MLD // DV0.9 changes
  18.     DSI_I2C_ByteWrite(0x0164, 0x00000007, 6); /*PPI_D0S_CLRSIPOCOUNT */
  19.     DSI_I2C_ByteWrite(0x0168, 0x00000007, 6); /*PPI_D1S_CLRSIPOCOUNT */
  20.     DSI_I2C_ByteWrite(0x016c, 0x00000007, 6); /*PPI_D2S_CLRSIPOCOUNT */
  21.     DSI_I2C_ByteWrite(0x0170, 0x00000007, 6); /*PPI_D3S_CLRSIPOCOUNT */
  22. #else
  23.     DSI_I2C_ByteWrite(0x0164, 0x00000001, 6); /*PPI_D0S_CLRSIPOCOUNT */
  24.     DSI_I2C_ByteWrite(0x0168, 0x00000001, 6); /*PPI_D1S_CLRSIPOCOUNT */
  25.     DSI_I2C_ByteWrite(0x016c, 0x00000001, 6); /*PPI_D2S_CLRSIPOCOUNT */
  26.     DSI_I2C_ByteWrite(0x0170, 0x00000001, 6); /*PPI_D3S_CLRSIPOCOUNT */
  27. #endif
  28.     /*Enabling MIPI & PPI lanes, Enable 4 lanes */
  29.     DSI_I2C_ByteWrite(0x0134, 0x0000001F, 6); /*PPI_LANEENABLE */
  30.     DSI_I2C_ByteWrite(0x0210, 0x0000001F, 6); /*DSI_LANEENABLE */
  31.     DSI_I2C_ByteWrite(0x0104, 0x00000001, 6); /*PPI_SARTPPI */
  32.     DSI_I2C_ByteWrite(0x0204, 0x00000001, 6); /*DSI_SARTPPI */

  33. #ifdef FIXME_MLD
  34.     /*Setting LVDS output frequency */
  35.     DSI_I2C_ByteWrite(0x04A0, 0x00000006, 6); /*LVDS PHY Register 0 (LVPHY0) */

  36.     /*Calculating video panel control settings */
  37.     /*Setting video panel control register */
  38.     DSI_I2C_ByteWrite(0x0450, 0x00000130, 6); /*VPCTRL, Video Path Control, VTGen=ON */

  39.     /*Setting display timing registers */
  40.     DSI_I2C_ByteWrite(0x0454, 0x0064000A, 6); /*HTIM1, HBPR=100, HPW=10 */

  41.     DSI_I2C_ByteWrite(0x0458, 0x00BE0400, 6); /*HTIM2, HFPR=190, HDISPR=1024 */
  42.     DSI_I2C_ByteWrite(0x045c, 0x000F0005, 6); /*VTIM1, VBPR=15, VPW=5 */
  43.     DSI_I2C_ByteWrite(0x0460, 0x000F0258, 6); /*VTIM2, VFPR=15, VDISPR=600 */

  1. #else
  2.     /*Setting LVDS output frequency */
  3.     DSI_I2C_ByteWrite(0x04A0, 0x00048006, 6); /*LVDS PHY Register 0 (LVPHY0) */

  4.     /*Calculating video panel control settings */
  5.     /*Setting video panel control register */
  6.     DSI_I2C_ByteWrite(0x0450, 0x00000120, 6); /*VPCTRL, Video Path Control, VTGen=ON */

  7.     /*Setting display timing registers */
  8.     DSI_I2C_ByteWrite(0x0454, 0x00280028, 6); /*HTIM1, HBPR=100, HPW=10 */

  9.     DSI_I2C_ByteWrite(0x0458, 0x00500500, 6); /*HTIM2, HFPR=190, HDISPR=1024 */
  10.     DSI_I2C_ByteWrite(0x045c, 0x000e000a, 6); /*VTIM1, VBPR=15, VPW=5 */
  11.     DSI_I2C_ByteWrite(0x0460, 0x000e0320, 6); /*VTIM2, VFPR=15, VDISPR=600 */
  12. #endif

  13.     DSI_I2C_ByteWrite(0x0464, 0x00000001, 6); /*VFUEN */

  14.     /*Setting LVDS bit arrangement */
  15.     DSI_I2C_ByteWrite(0x0480, 0x03020100, 6); /*LVMX0003 */
  16.     DSI_I2C_ByteWrite(0x0484, 0x08050704, 6); /*LVMX0407 */
  17.     DSI_I2C_ByteWrite(0x0488, 0x0F0E0A09, 6); /*LVMX0811 */
  18.     DSI_I2C_ByteWrite(0x048C, 0x100D0C0B, 6); /*LVMX1215 */
  19.     DSI_I2C_ByteWrite(0x0490, 0x12111716, 6); /*LVMX1619 */
  20.     DSI_I2C_ByteWrite(0x0494, 0x1B151413, 6); /*LVMX2023 */
  21.     DSI_I2C_ByteWrite(0x0498, 0x061A1918, 6); /*LVMX2427 */

  22. #ifdef FIXME_MLD //DV0.9 changes
  23.     DSI_I2C_ByteWrite(0x049c, 0x00000101, 6); /*LVCFG */
  24. #else
  25.     DSI_I2C_ByteWrite(0x049c, 0x00000001, 6); /*LVCFG */
  26. #endif

  27.     DSI_I2C_ByteWrite(0x0288, 0xFFFFFFFF, 6); /*DSI_INTCLR */

  28.     lvds_disp_init = 1;

  29.     printk(KERN_INFO "[DISPLAY]%s: Exit\n", __func__);

  30. }
3. panel on/off

  1. /* ************************************************************************* *\
  2.  * FUNCTION: dsi_lvds_toshiba_bridge_panel_off
  3.  *
  4.  * DESCRIPTION: This function uses GPIO to turn OFF panel.
  5. \* ************************************************************************* */
  6. void dsi_lvds_toshiba_bridge_panel_off(void)
  7. {
  8.     printk(KERN_INFO "[DISPLAY ] %s\n", __func__);

  9.     gpio_direction_output(GPIO_MIPI_LCD_STBYB, 0);
  10.     gpio_set_value_cansleep(GPIO_MIPI_LCD_STBYB, 0); /*Pull LCD_STBYB pin to Low */
  11.     mdelay(1);

  12.     gpio_direction_output(GPIO_MIPI_PANEL_RESET, 0);
  13.     gpio_set_value_cansleep(GPIO_MIPI_PANEL_RESET, 0);
  14.     mdelay(1);
  15. }

  16. /* ************************************************************************* *\
  17.  * FUNCTION: dsi_lvds_toshiba_bridge_panel_on
  18.  *
  19.  * DESCRIPTION: This function uses GPIO to turn ON panel.
  20. \* ************************************************************************* */
  21. void dsi_lvds_toshiba_bridge_panel_on(void)
  22. {
  23.     printk(KERN_INFO "[DISPLAY ] %s\n", __func__);

  24.     /* set following pin to low */
  25.     gpio_direction_output(GPIO_MIPI_LCD_STBYB, 0);
  26.     gpio_set_value_cansleep(GPIO_MIPI_LCD_STBYB, 0); /*Pull LCD_STBYB pin to Low */

  27.     gpio_direction_output(GPIO_MIPI_PANEL_RESET, 0);
  28.     gpio_set_value_cansleep(GPIO_MIPI_PANEL_RESET, 0);

  29.     gpio_direction_output(GPIO_MIPI_LCD_VADD, 0);
  30.     gpio_set_value_cansleep(GPIO_MIPI_LCD_VADD, 0);

  31.     gpio_direction_output(GPIO_MIPI_LCD_BIAS_EN, 0);
  32.     gpio_set_value_cansleep(GPIO_MIPI_LCD_BIAS_EN, 0);
  33.     mdelay(10);

  34.     /* STBYB */
  35.     gpio_direction_output(GPIO_MIPI_LCD_STBYB, 1);
  36.     gpio_set_value_cansleep(GPIO_MIPI_LCD_STBYB, 1); /*Pull LCD_STBYB pin to High */
  37.     mdelay(10);

  38.     /* VADD */
  39.     gpio_direction_output(GPIO_MIPI_LCD_VADD, 1);
  40.     mdelay(50);

  41.     /* RESET */
  42.     gpio_direction_output(GPIO_MIPI_PANEL_RESET, 1);
  43.     gpio_set_value_cansleep(GPIO_MIPI_PANEL_RESET, 1);
  44.     mdelay(100);

  45.     /* BIAS */
  46.     gpio_direction_output(GPIO_MIPI_LCD_BIAS_EN, 1);
  47.     gpio_set_value_cansleep(GPIO_MIPI_LCD_BIAS_EN, 1);

  48. }
4. init  / deinit

  1. /* ************************************************************************* *\
  2.  * FUNCTION: dsi_lvds_init_lvds_bridge
  3.  *
  4.  * DESCRIPTION: This function does all one time init. Currently defining
  5.  * GPIOs only.
  6. \* ************************************************************************* */
  7. void dsi_lvds_init_lvds_bridge(struct drm_device *dev)
  8. {
  9.     /* request GPIOs */
  10.     gpio_request(GPIO_MIPI_BRIDGE_RESET, "display");
  11.     gpio_request(GPIO_MIPI_PANEL_RESET , "display");
  12.     gpio_request(GPIO_MIPI_LCD_STBYB, "display");
  13.     gpio_request(GPIO_MIPI_LCD_BIAS_EN, "display");
  14.     gpio_request(GPIO_MIPI_LCD_VADD, "display");
  15. }

  16. /* ************************************************************************* *\
  17.  * FUNCTION: dsi_lvds_deinit_lvds_bridge
  18.  *
  19.  * DESCRIPTION: This function does is called during deinit time.
  20.  *
  21. \* ************************************************************************* */
  22. void dsi_lvds_deinit_lvds_bridge(struct drm_device *dev)
  23. {
  24.     if (!lvds_disp_init) {
  25.         printk(KERN_ALERT "[DISPLAY ] %s has not initialized\n", __func__);
  26.         return;
  27.     }

  28.     printk(KERN_INFO "[DISPLAY ] Enter %s\n", __func__);


  29.     lvds_disp_init = 0;
  30. }
5. get params

  1. /* ************************************************************************* *\
  2.  * FUNCTION: dsi_lvds_bridge_get_display_params
  3.  *
  4.  * DESCRIPTION: This function is a callback to get the panel resolution and
  5.  * timing settings.
  6.  *
  7. \* ************************************************************************* */
  8. void dsi_lvds_bridge_get_display_params(struct drm_display_mode *mode)
  9. {
  10. #ifdef FIXME_MLD // Changes for DV0.9 display
  11. /* This settings is for 1024*600 panel*/
  12.     mode->hdisplay = 1024;
  13.     mode->vdisplay = 600;
  14.     mode->hsync_start = 1655;
  15.     mode->hsync_end = 1665;
  16.     mode->htotal = 1765;
  17.     mode->vsync_start = 615;
  18.     mode->vsync_end = 620;
  19.     mode->vtotal = 635;
  20.     mode->clock = 33324;
  21. #else
  22.     mode->hdisplay = 1200;
  23.     mode->vdisplay = 800;
  24.     mode->hsync_start = 1360;
  25.     mode->hsync_end = 1400;
  26.     mode->htotal = 1440;
  27.     mode->vsync_start = 814;
  28.     mode->vsync_end = 824;
  29.     mode->vtotal = 838;
  30.     mode->clock = 33324;
  31. #endif //end FIXME_MLD

  32.     printk(KERN_INFO "[DISPLAY]: hdisplay(w) is %d\n", mode->hdisplay);
  33.     printk(KERN_INFO "[DISPLAY]: vdisplay(h) is %d\n", mode->vdisplay);
  34.     printk(KERN_INFO "[DISPLAY]: HSS is %d\n", mode->hsync_start);
  35.     printk(KERN_INFO "[DISPLAY]: HSE is %d\n", mode->hsync_end);
  36.     printk(KERN_INFO "[DISPLAY]: htotal is %d\n", mode->htotal);
  37.     printk(KERN_INFO "[DISPLAY]: VSS is %d\n", mode->vsync_start);
  38.     printk(KERN_INFO "[DISPLAY]: VSE is %d\n", mode->vsync_end);
  39.     printk(KERN_INFO "[DISPLAY]: vtotal is %d\n", mode->vtotal);
  40.     printk(KERN_INFO "[DISPLAY]: clock is %d\n", mode->clock);
  41. }

7. 具体动作: read / write

  1. /* ************************************************************************* *\
  2.  * FUNCTION: DSI_I2C_ByteRead
  3.  *
  4.  * DESCRIPTION: Local functions to read I2C registers
  5.  *
  6. \* ************************************************************************* */
  7. static int DSI_I2C_ByteRead(u16 reg, int count)
  8. {
  9.     if (dsi_lvds_inst->client)
  10.         return __DSI_I2C_ByteRead(reg, count);
  11.     else
  12.         return -EIO;
  13. }

  1. /* ************************************************************************* *\
  2.  * FUNCTION: __DSI_I2C_ByteRead
  3.  *
  4.  * DESCRIPTION: Local functions to process read req for I2C registers
  5.  *
  6. \* ************************************************************************* */
  7. static int __DSI_I2C_ByteRead(u16 reg, int count)
  8. {
  9.     char rxData[4] = {0};
  10.     char regData[2] = {0};
  11.     struct i2c_msg msgs[] = {
  12.         {
  13.          .addr = dsi_lvds_inst->client->addr,
  14.          .flags = 0,
  15.          .len = 2,
  16.          },
  17.         {
  18.          .addr = dsi_lvds_inst->client->addr,
  19.          .flags = I2C_M_RD,
  20.          .len = count - 2,
  21.          },
  22.     };

  23.     regData[0] = (reg & 0xFF00) >> 8;
  24.     regData[1] = reg & 0xFF;

  25.     msgs[0].buf = regData;
  26.     msgs[1].buf = rxData;

  27.     printk(KERN_INFO "Register: 0x%x\n", reg);
  28.     if (i2c_transfer(dsi_lvds_inst->client->adapter, msgs, 2) < 0) {
  29.         printk(KERN_ERR "[DISPLAY] %s: transfer error\n", __func__);
  30.         return -EIO;
  31.     } else if (count > 2) {
  32.         int i = 0;
  33.         for (i = count - 3; i > -1; --i)
  34.             printk(KERN_INFO "%02x ", rxData[i]);
  35.         printk(KERN_INFO "\n");
  36.         return rxData[0];
  37.     }
  38.     return 0;
  39. }

  1. /* ************************************************************************* *\
  2.  * FUNCTION: DSI_I2C_ByteWrite
  3.  *
  4.  * DESCRIPTION: Local functions to issue write req for I2C registers
  5.  *
  6. \* ************************************************************************* */
  7. static int DSI_I2C_ByteWrite(u16 reg, u32 data, int count)
  8. {
  9.     if (dsi_lvds_inst->client)
  10.         return __DSI_I2C_ByteWrite(reg, data, count);
  11.     else
  12.         return -EIO;
  13. }

  1. /* ************************************************************************* *\
  2.  * FUNCTION: __DSI_I2C_ByteWrite
  3.  *
  4.  * DESCRIPTION: Local functions to process write req for I2C registers
  5.  *
  6. \* ************************************************************************* */
  7. static int __DSI_I2C_ByteWrite(u16 reg, u32 data, int count)
  8. {
  9.     char txData[6] = {0};
  10.     struct i2c_msg msg[] = {
  11.         {
  12.          .addr = dsi_lvds_inst->client->addr,
  13.          .flags = 0,
  14.          .len = count,
  15.          },
  16.     };

  17.     /*Set the register */
  18.     txData[0] = (reg & 0xFF00) >> 8;
  19.     txData[1] = reg & 0xFF;

  20.     if (count == 6) {
  21.         /*Set the data */
  22.         txData[2] = (data & 0xFF);
  23.         txData[3] = (data & 0xFF00) >> 8;
  24.         txData[4] = (data & 0xFF0000) >> 16;
  25.         txData[5] = (data & 0xFF000000) >> 24;
  26.     } else {
  27.         /* Not valid for this bridge chipset */
  28.     }

  29.     printk(KERN_INFO "[DISPLAY] %s: addr = %x, reg = %x, data = %x\n",
  30.         __func__, dsi_lvds_inst->client->addr, reg, data);

  31.     msg[0].buf = txData;

  32.     if (i2c_transfer(dsi_lvds_inst->client->adapter, msg, 1) < 0) {
  33.         printk(KERN_ERR "[DISPLAY] %s: transfer error\n", __func__);
  34.         return -EIO;
  35.     } else {
  36.         return 0;
  37.     }
  38. }








您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP