From: Jan Kiszka <jan.kiszka@siemens.com>
To: Konrad Banachowicz <konradb3@gmail.com>, xenomai@xenomai.org
Subject: Re: [Xenomai] [PATCH] rtcan/peek_pci: add support for 3 and 4 port cards.
Date: Thu, 07 Nov 2013 12:40:10 +0100 [thread overview]
Message-ID: <527B7C1A.8050702@siemens.com> (raw)
In-Reply-To: <1383824038-8266-1-git-send-email-konradb3@gmail.com>
On 2013-11-07 12:33, Konrad Banachowicz wrote:
> ---
> ksrc/drivers/can/sja1000/rtcan_peak_pci.c | 451 ++++++++++++++---------------
> 1 file changed, 224 insertions(+), 227 deletions(-)
>
> diff --git a/ksrc/drivers/can/sja1000/rtcan_peak_pci.c b/ksrc/drivers/can/sja1000/rtcan_peak_pci.c
> index d13a7ff..132d4e8 100644
> --- a/ksrc/drivers/can/sja1000/rtcan_peak_pci.c
> +++ b/ksrc/drivers/can/sja1000/rtcan_peak_pci.c
> @@ -46,13 +46,12 @@ MODULE_DESCRIPTION("RTCAN board driver for PEAK-PCI cards");
> MODULE_SUPPORTED_DEVICE("PEAK-PCI card CAN controller");
> MODULE_LICENSE("GPL");
>
> -struct rtcan_peak_pci
> -{
> - struct pci_dev *pci_dev;
> - struct rtcan_device *slave_dev;
> - int channel;
> - volatile void __iomem *base_addr;
> - volatile void __iomem *conf_addr;
> +struct rtcan_peak_pci {
> + struct pci_dev *pci_dev;
> + struct rtcan_device *slave_dev;
> + int channel;
> + volatile void __iomem *base_addr;
> + volatile void __iomem *conf_addr;
> };
>
> #define PEAK_PCI_CAN_SYS_CLOCK (16000000 / 2)
> @@ -62,8 +61,11 @@ struct rtcan_peak_pci
> #define PELICAN_DEFAULT (SJA_CDR_CAN_MODE )
>
> #define CHANNEL_SINGLE 0 /* this is a single channel device */
> -#define CHANNEL_MASTER 1 /* multi channel device, this device is master */
> -#define CHANNEL_SLAVE 2 /* multi channel device, this is slave */
> +#define CHANNEL_MASTER 0 /* multi channel device, this device is master */
> +#define CHANNEL_SLAVE 1 /* multi channel device, this is slave */
> +#define CHANNEL_SLAVE_1 1 /* multi channel device, this is slave 1*/
> +#define CHANNEL_SLAVE_2 2 /* multi channel device, this is slave 2*/
> +#define CHANNEL_SLAVE_3 3 /* multi channel device, this is slave 3*/
>
> // important PITA registers
> #define PITA_ICR 0x00 // interrupt control register
> @@ -82,282 +84,277 @@ struct rtcan_peak_pci
> #define PCI_CONFIG_PORT_SIZE 0x1000 // size of the config io-memory
> #define PCI_PORT_SIZE 0x0400 // size of a channel io-memory
>
> +static const u16 peak_pci_icr_masks[] = {0x02, 0x01, 0x40, 0x80};
> +
> static struct pci_device_id peak_pci_tbl[] = {
> - {PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
> - {PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
> - {PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
> - {PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
> - {PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
> - {PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
> - {PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
> - { }
> + {PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
> + {PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
> + {PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
> + {PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
> + {PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
> + {PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
> + {PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
> + { }
> };
> MODULE_DEVICE_TABLE (pci, peak_pci_tbl);
>
>
> static u8 rtcan_peak_pci_read_reg(struct rtcan_device *dev, int port)
> {
> - struct rtcan_peak_pci *board = (struct rtcan_peak_pci *)dev->board_priv;
> - return readb(board->base_addr + ((unsigned long)port << 2));
> + struct rtcan_peak_pci *board = (struct rtcan_peak_pci *)dev->board_priv;
> + return readb(board->base_addr + ((unsigned long)port << 2));
> }
>
> static void rtcan_peak_pci_write_reg(struct rtcan_device *dev, int port, u8 data)
> {
> - struct rtcan_peak_pci *board = (struct rtcan_peak_pci *)dev->board_priv;
> - writeb(data, board->base_addr + ((unsigned long)port << 2));
> + struct rtcan_peak_pci *board = (struct rtcan_peak_pci *)dev->board_priv;
> + writeb(data, board->base_addr + ((unsigned long)port << 2));
> }
>
> static void rtcan_peak_pci_irq_ack(struct rtcan_device *dev)
> {
> - struct rtcan_peak_pci *board = (struct rtcan_peak_pci *)dev->board_priv;
> - u16 pita_icr_low;
> -
> - /* Select and clear in Pita stored interrupt */
> - pita_icr_low = readw(board->conf_addr + PITA_ICR);
> - if (board->channel == CHANNEL_SLAVE) {
> - if (pita_icr_low & 0x0001)
> - writew(0x0001, board->conf_addr + PITA_ICR);
> - }
> - else {
> - if (pita_icr_low & 0x0002)
> - writew(0x0002, board->conf_addr + PITA_ICR);
> - }
> + struct rtcan_peak_pci *board = (struct rtcan_peak_pci *)dev->board_priv;
> + u16 pita_icr_low;
> +
> + /* Select and clear in Pita stored interrupt */
> + pita_icr_low = readw(board->conf_addr + PITA_ICR);
> +
> + if (pita_icr_low & peak_pci_icr_masks[board->channel]) {
> + writew(peak_pci_icr_masks[board->channel], board->conf_addr + PITA_ICR);
> + }
> }
>
> static void rtcan_peak_pci_del_chan(struct rtcan_device *dev,
> - int init_step)
> + int init_step)
> {
> - struct rtcan_peak_pci *board;
> - u16 pita_icr_high;
> -
> - if (!dev)
> - return;
> -
> - board = (struct rtcan_peak_pci *)dev->board_priv;
> -
> - switch (init_step) {
> - case 0: /* Full cleanup */
> - printk("Removing %s %s device %s\n",
> - peak_pci_board_name, dev->ctrl_name, dev->name);
> - rtcan_sja1000_unregister(dev);
> - case 5:
> - pita_icr_high = readw(board->conf_addr + PITA_ICR + 2);
> - if (board->channel == CHANNEL_SLAVE) {
> - pita_icr_high &= ~0x0001;
> - } else {
> - pita_icr_high &= ~0x0002;
> - }
> - writew(pita_icr_high, board->conf_addr + PITA_ICR + 2);
> - case 4:
> - iounmap((void *)board->base_addr);
> - case 3:
> - if (board->channel != CHANNEL_SLAVE)
> - iounmap((void *)board->conf_addr);
> - case 2:
> - rtcan_dev_free(dev);
> - case 1:
> - break;
> - }
> + struct rtcan_peak_pci *board;
> + u16 pita_icr_high;
> +
> + if (!dev)
> + return;
> +
> + board = (struct rtcan_peak_pci *)dev->board_priv;
> +
> + switch (init_step) {
> + case 0: /* Full cleanup */
> + printk("Removing %s %s device %s\n",
> + peak_pci_board_name, dev->ctrl_name, dev->name);
> + rtcan_sja1000_unregister(dev);
> + case 5:
> + pita_icr_high = readw(board->conf_addr + PITA_ICR + 2);
> + pita_icr_high &= ~peak_pci_icr_masks[board->channel];
> + writew(pita_icr_high, board->conf_addr + PITA_ICR + 2);
> + case 4:
> + iounmap((void *)board->base_addr);
> + case 3:
> + if (board->channel != CHANNEL_SLAVE)
> + iounmap((void *)board->conf_addr);
> + case 2:
> + rtcan_dev_free(dev);
> + case 1:
> + break;
> + }
>
> }
>
> static int rtcan_peak_pci_add_chan(struct pci_dev *pdev, int channel,
> - struct rtcan_device **master_dev)
> + struct rtcan_device **master_dev)
> {
> - struct rtcan_device *dev;
> - struct rtcan_sja1000 *chip;
> - struct rtcan_peak_pci *board;
> - u16 pita_icr_high;
> - unsigned long addr;
> - int ret, init_step = 1;
> -
> - dev = rtcan_dev_alloc(sizeof(struct rtcan_sja1000),
> - sizeof(struct rtcan_peak_pci));
> - if (dev == NULL)
> - return -ENOMEM;
> - init_step = 2;
> -
> - chip = (struct rtcan_sja1000 *)dev->priv;
> - board = (struct rtcan_peak_pci *)dev->board_priv;
> -
> - board->pci_dev = pdev;
> - board->channel = channel;
> -
> - if (channel != CHANNEL_SLAVE) {
> -
> - addr = pci_resource_start(pdev, 0);
> - board->conf_addr = ioremap(addr, PCI_CONFIG_PORT_SIZE);
> - if (board->conf_addr == 0) {
> - ret = -ENODEV;
> - goto failure;
> - }
> - init_step = 3;
> -
> - /* Set GPIO control register */
> - writew(0x0005, board->conf_addr + PITA_GPIOICR + 2);
> -
> - if (channel == CHANNEL_MASTER)
> - writeb(0x00, board->conf_addr + PITA_GPIOICR); /* enable both */
> - else
> - writeb(0x04, board->conf_addr + PITA_GPIOICR); /* enable single */
> -
> - writeb(0x05, board->conf_addr + PITA_MISC + 3); /* toggle reset */
> - mdelay(5);
> - writeb(0x04, board->conf_addr + PITA_MISC + 3); /* leave parport mux mode */
> - } else {
> - struct rtcan_peak_pci *master_board =
> - (struct rtcan_peak_pci *)(*master_dev)->board_priv;
> - master_board->slave_dev = dev;
> - board->conf_addr = master_board->conf_addr;
> - }
> -
> - addr = pci_resource_start(pdev, 1);
> - if (channel == CHANNEL_SLAVE)
> - addr += 0x400;
> -
> - board->base_addr = ioremap(addr, PCI_PORT_SIZE);
> - if (board->base_addr == 0) {
> - ret = -ENODEV;
> - goto failure;
> - }
> - init_step = 4;
> -
> - dev->board_name = peak_pci_board_name;
> -
> - chip->read_reg = rtcan_peak_pci_read_reg;
> - chip->write_reg = rtcan_peak_pci_write_reg;
> - chip->irq_ack = rtcan_peak_pci_irq_ack;
> -
> - /* Clock frequency in Hz */
> - dev->can_sys_clock = PEAK_PCI_CAN_SYS_CLOCK;
> -
> - /* Output control register */
> - chip->ocr = SJA_OCR_MODE_NORMAL | SJA_OCR_TX0_PUSHPULL;
> -
> - /* Clock divider register */
> - if (channel == CHANNEL_MASTER)
> - chip->cdr = PELICAN_MASTER;
> - else
> - chip->cdr = PELICAN_SINGLE;
> -
> - strncpy(dev->name, RTCAN_DEV_NAME, IFNAMSIZ);
> -
> - /* Register and setup interrupt handling */
> - chip->irq_flags = RTDM_IRQTYPE_SHARED;
> - chip->irq_num = pdev->irq;
> - pita_icr_high = readw(board->conf_addr + PITA_ICR + 2);
> - if (channel == CHANNEL_SLAVE) {
> - pita_icr_high |= 0x0001;
> - } else {
> - pita_icr_high |= 0x0002;
> - }
> - writew(pita_icr_high, board->conf_addr + PITA_ICR + 2);
> - init_step = 5;
> -
> - printk("%s: base_addr=%p conf_addr=%p irq=%d\n", RTCAN_DRV_NAME,
> - board->base_addr, board->conf_addr, chip->irq_num);
> -
> - /* Register SJA1000 device */
> - ret = rtcan_sja1000_register(dev);
> - if (ret) {
> - printk(KERN_ERR
> - "ERROR %d while trying to register SJA1000 device!\n", ret);
> - goto failure;
> - }
> -
> - if (channel != CHANNEL_SLAVE)
> - *master_dev = dev;
> -
> - return 0;
> -
> - failure:
> - rtcan_peak_pci_del_chan(dev, init_step);
> - return ret;
> + struct rtcan_device *dev;
> + struct rtcan_sja1000 *chip;
> + struct rtcan_peak_pci *board;
> + u16 pita_icr_high;
> + unsigned long addr;
> + int ret, init_step = 1;
> +
> + dev = rtcan_dev_alloc(sizeof(struct rtcan_sja1000),
> + sizeof(struct rtcan_peak_pci));
> + if (dev == NULL)
> + return -ENOMEM;
> + init_step = 2;
> +
> + chip = (struct rtcan_sja1000 *)dev->priv;
> + board = (struct rtcan_peak_pci *)dev->board_priv;
> +
> + board->pci_dev = pdev;
> + board->channel = channel;
> +
> + if (channel == CHANNEL_MASTER) {
> +
> + addr = pci_resource_start(pdev, 0);
> + board->conf_addr = ioremap(addr, PCI_CONFIG_PORT_SIZE);
> + if (board->conf_addr == 0) {
> + ret = -ENODEV;
> + goto failure;
> + }
> + init_step = 3;
> +
> + /* Set GPIO control register */
> + writew(0x0005, board->conf_addr + PITA_GPIOICR + 2);
> +
> + if (channel == CHANNEL_MASTER)
> + writeb(0x00, board->conf_addr + PITA_GPIOICR); /* enable both */
> + else
> + writeb(0x04, board->conf_addr + PITA_GPIOICR); /* enable single */
> +
> + writeb(0x05, board->conf_addr + PITA_MISC + 3); /* toggle reset */
> + mdelay(5);
> + writeb(0x04, board->conf_addr + PITA_MISC + 3); /* leave parport mux mode */
> + } else {
> + struct rtcan_peak_pci *master_board =
> + (struct rtcan_peak_pci *)(*master_dev)->board_priv;
> + master_board->slave_dev = dev;
> + board->conf_addr = master_board->conf_addr;
> + }
> +
> + addr = pci_resource_start(pdev, 1) + channel * PCI_PORT_SIZE;
> +
> + board->base_addr = ioremap(addr, PCI_PORT_SIZE);
> + if (board->base_addr == 0) {
> + ret = -ENODEV;
> + goto failure;
> + }
> +
> + init_step = 4;
> +
> + dev->board_name = peak_pci_board_name;
> +
> + chip->read_reg = rtcan_peak_pci_read_reg;
> + chip->write_reg = rtcan_peak_pci_write_reg;
> + chip->irq_ack = rtcan_peak_pci_irq_ack;
> +
> + /* Clock frequency in Hz */
> + dev->can_sys_clock = PEAK_PCI_CAN_SYS_CLOCK;
> +
> + /* Output control register */
> + chip->ocr = SJA_OCR_MODE_NORMAL | SJA_OCR_TX0_PUSHPULL;
> +
> + /* Clock divider register */
> + if (channel == CHANNEL_MASTER)
> + chip->cdr = PELICAN_MASTER;
> + else
> + chip->cdr = PELICAN_SINGLE;
> +
> + strncpy(dev->name, RTCAN_DEV_NAME, IFNAMSIZ);
> +
> + /* Register and setup interrupt handling */
> + chip->irq_flags = RTDM_IRQTYPE_SHARED;
> + chip->irq_num = pdev->irq;
> + pita_icr_high = readw(board->conf_addr + PITA_ICR + 2);
> +
> + pita_icr_high |= peak_pci_icr_masks[channel];
> +
> + writew(pita_icr_high, board->conf_addr + PITA_ICR + 2);
> + init_step = 5;
> +
> + printk("%s: base_addr=%p conf_addr=%p irq=%d\n", RTCAN_DRV_NAME,
> + board->base_addr, board->conf_addr, chip->irq_num);
> +
> + /* Register SJA1000 device */
> + ret = rtcan_sja1000_register(dev);
> + if (ret) {
> + printk(KERN_ERR
> + "ERROR %d while trying to register SJA1000 device!\n", ret);
> + goto failure;
> + }
> +
> + if (channel != CHANNEL_SLAVE)
> + *master_dev = dev;
> +
> + return 0;
> +
> +failure:
> + rtcan_peak_pci_del_chan(dev, init_step);
> + return ret;
> }
>
> static int peak_pci_init_one(struct pci_dev *pdev,
> - const struct pci_device_id *ent)
> + const struct pci_device_id *ent)
> {
> - int ret;
> - u16 sub_sys_id;
> - struct rtcan_device *master_dev = NULL;
> + int ret;
> + int num_channels;
> + int i;
> + u16 sub_sys_id;
> + struct rtcan_device *master_dev = NULL;
> +
> + printk("%s: initializing device %04x:%04x\n",
> + RTCAN_DRV_NAME, pdev->vendor, pdev->device);
>
> - printk("%s: initializing device %04x:%04x\n",
> - RTCAN_DRV_NAME, pdev->vendor, pdev->device);
> + if ((ret = pci_enable_device (pdev)))
> + goto failure;
>
> - if ((ret = pci_enable_device (pdev)))
> - goto failure;
> + if ((ret = pci_request_regions(pdev, RTCAN_DRV_NAME)))
> + goto failure;
>
> - if ((ret = pci_request_regions(pdev, RTCAN_DRV_NAME)))
> - goto failure;
> + if ((ret = pci_read_config_word(pdev, 0x2e, &sub_sys_id)))
> + goto failure_cleanup;
>
> - if ((ret = pci_read_config_word(pdev, 0x2e, &sub_sys_id)))
> - goto failure_cleanup;
> + /* Enable memory space */
> + if ((ret = pci_write_config_word(pdev, 0x04, 2)))
> + goto failure_cleanup;
>
> - /* Enable memory space */
> - if ((ret = pci_write_config_word(pdev, 0x04, 2)))
> - goto failure_cleanup;
> + if ((ret = pci_write_config_word(pdev, 0x44, 0)))
> + goto failure_cleanup;
>
> - if ((ret = pci_write_config_word(pdev, 0x44, 0)))
> - goto failure_cleanup;
> + if (sub_sys_id >= 12) {
> + num_channels = 4;
> + } else if (sub_sys_id >= 12) {
> + num_channels = 3;
> + } else if (sub_sys_id >= 4) {
> + num_channels = 2;
> + } else {
> + num_channels = 1;
> + }
>
> - if (sub_sys_id > 3) {
> - if ((ret = rtcan_peak_pci_add_chan(pdev, CHANNEL_MASTER,
> - &master_dev)))
> - goto failure_cleanup;
> - if ((ret = rtcan_peak_pci_add_chan(pdev, CHANNEL_SLAVE,
> - &master_dev)))
> - goto failure_cleanup;
> - } else {
> - if ((ret = rtcan_peak_pci_add_chan(pdev, CHANNEL_SINGLE,
> - &master_dev)))
> - goto failure_cleanup;
> - }
> + for(i = 0; i < num_channels; i++) {
> + if ((ret = rtcan_peak_pci_add_chan(pdev, i, &master_dev)))
> + goto failure_cleanup;
> + }
>
> - pci_set_drvdata(pdev, master_dev);
> - return 0;
> + pci_set_drvdata(pdev, master_dev);
> + return 0;
>
> - failure_cleanup:
> - if (master_dev)
> - rtcan_peak_pci_del_chan(master_dev, 0);
> +failure_cleanup:
> + if (master_dev)
> + rtcan_peak_pci_del_chan(master_dev, 0);
>
> - pci_release_regions(pdev);
> + pci_release_regions(pdev);
>
> - failure:
> - return ret;
> +failure:
> + return ret;
>
> }
>
> static void peak_pci_remove_one(struct pci_dev *pdev)
> {
> - struct rtcan_device *dev = pci_get_drvdata(pdev);
> - struct rtcan_peak_pci *board = (struct rtcan_peak_pci *)dev->board_priv;
> + struct rtcan_device *dev = pci_get_drvdata(pdev);
> + struct rtcan_peak_pci *board = (struct rtcan_peak_pci *)dev->board_priv;
>
> - if (board->slave_dev)
> - rtcan_peak_pci_del_chan(board->slave_dev, 0);
> - rtcan_peak_pci_del_chan(dev, 0);
> + if (board->slave_dev)
> + rtcan_peak_pci_del_chan(board->slave_dev, 0);
> + rtcan_peak_pci_del_chan(dev, 0);
>
> - pci_release_regions(pdev);
> - pci_disable_device(pdev);
> - pci_set_drvdata(pdev, NULL);
> + pci_release_regions(pdev);
> + pci_disable_device(pdev);
> + pci_set_drvdata(pdev, NULL);
> }
>
> static struct pci_driver rtcan_peak_pci_driver = {
> - .name = RTCAN_DRV_NAME,
> - .id_table = peak_pci_tbl,
> - .probe = peak_pci_init_one,
> - .remove = peak_pci_remove_one,
> + .name = RTCAN_DRV_NAME,
> + .id_table = peak_pci_tbl,
> + .probe = peak_pci_init_one,
> + .remove = peak_pci_remove_one,
> };
>
> static int __init rtcan_peak_pci_init(void)
> {
> - return pci_register_driver(&rtcan_peak_pci_driver);
> + return pci_register_driver(&rtcan_peak_pci_driver);
> }
>
>
> static void __exit rtcan_peak_pci_exit(void)
> {
> - pci_unregister_driver(&rtcan_peak_pci_driver);
> + pci_unregister_driver(&rtcan_peak_pci_driver);
> }
>
> module_init(rtcan_peak_pci_init);
>
Please split functional changes from style fixes. Specifically, a patch
addressing the latter should have no impact on the binary output.
Thanks,
Jan
--
Siemens AG, Corporate Technology, CT RTC ITP SES-DE
Corporate Competence Center Embedded Linux
prev parent reply other threads:[~2013-11-07 11:40 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-11-07 11:33 [Xenomai] [PATCH] rtcan/peek_pci: add support for 3 and 4 port cards Konrad Banachowicz
2013-11-07 11:40 ` Jan Kiszka [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=527B7C1A.8050702@siemens.com \
--to=jan.kiszka@siemens.com \
--cc=konradb3@gmail.com \
--cc=xenomai@xenomai.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.