All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sergei Shtylyov <sshtylyov@ru.mvista.com>
To: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Cc: linux-ide@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 14/15] ide: rework the code for selecting the best DMA transfer mode
Date: Mon, 22 Jan 2007 22:48:21 +0300	[thread overview]
Message-ID: <45B51505.4040905@ru.mvista.com> (raw)
In-Reply-To: <20070119003233.14846.5450.sendpatchset@localhost.localdomain>

Hello.

Bartlomiej Zolnierkiewicz wrote:

> [PATCH] ide: rework the code for selecting the best DMA transfer mode 

    Here's another portion of comments...

> Depends on the "ide: fix UDMA/MWDMA/SWDMA masks" patch.

> * add ide_hwif_t.filter_udma_mask hook for filtering UDMA mask

    Erm, maybe a shorter method name like udma_filter would go with the others 
better.  But well, that's my taste. :-)

>   (use it in alim15x3, hpt366, siimage and serverworks drivers)
> * add ide_max_dma_mode() for finding best DMA mode for the device
>   (loosely based on some older libata-core.c code)
> * convert ide_dma_speed() users to use ide_max_dma_mode()
> * make ide_rate_filter() take "ide_drive_t *drive" as an argument instead
>   of "u8 mode" and teach it to how to use UDMA mask to do filtering
> * use ide_rate_filter() in hpt366 driver
> * remove no longer needed ide_dma_speed() and *_ratemask()
> * unexport eighty_ninty_three()

> Index: b/drivers/ide/ide-dma.c
> ===================================================================
> --- a/drivers/ide/ide-dma.c
> +++ b/drivers/ide/ide-dma.c
> @@ -705,6 +705,80 @@ int ide_use_dma(ide_drive_t *drive)
>  
>  EXPORT_SYMBOL_GPL(ide_use_dma);
>  
> +static const u8 xfer_mode_bases[] = {
> +	XFER_UDMA_0,
> +	XFER_MW_DMA_0,
> +	XFER_SW_DMA_0,
> +};
> +
> +static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base)
> +{
> +	struct hd_driveid *id = drive->id;
> +	ide_hwif_t *hwif = drive->hwif;
> +	unsigned int mask = 0;
> +
> +	switch(base) {
> +	case XFER_UDMA_0:
> +		if ((id->field_valid & 4) == 0)
> +			break;
> +
> +		mask = id->dma_ultra & hwif->ultra_mask;
> +
> +		if (hwif->filter_udma_mask)
> +			mask &= hwif->filter_udma_mask(drive);
> +
> +		if ((mask & 0x78) && (eighty_ninty_three(drive) == 0))
> +			mask &= 0x07;
> +		break;
> +	case XFER_MW_DMA_0:
> +		mask = id->dma_mword & hwif->mwdma_mask;
> +		break;
> +	case XFER_SW_DMA_0:
> +		mask = id->dma_1word & hwif->swdma_mask;
> +		break;
> +	default:
> +		BUG();
> +		break;
> +	}
> +
> +	return mask;
> +}
> +
> +/**
> + *	ide_max_dma_mode	-	compute DMA speed
> + *	@drive: IDE device
> + *
> + *	Checks the drive capabilities and returns the speed to use
> + *	for the DMA transfer.  Returns 0 if the drive is incapable
> + *	of DMA transfers.
> + */
> +
> +u8 ide_max_dma_mode(ide_drive_t *drive)
> +{
> +	ide_hwif_t *hwif = drive->hwif;
> +	unsigned int mask;
> +	int x, i;
> +	u8 mode = 0;
> +
> +	if (drive->media != ide_disk && hwif->atapi_dma == 0)
> +		return 0;
> +
> +	for (i = 0; i < ARRAY_SIZE(xfer_mode_bases); i++) {
> +		mask = ide_get_mode_mask(drive, xfer_mode_bases[i]);
> +		x = fls(mask) - 1;
> +		if (x >= 0) {
> +			mode = xfer_mode_bases[i] + x;
> +			break;
> +		}
> +	}
> +
> +	printk(KERN_DEBUG "%s: selected mode 0x%x\n", drive->name, mode);
> +
> +	return mode;
> +}
> +
> +EXPORT_SYMBOL_GPL(ide_max_dma_mode);
> +

    I didn't quite like the array/loop approach but well, that's my taste (I'd
rather put the mode-from-mask evaluation to the function and call it thrice)...

> Index: b/drivers/ide/ide-lib.c
> ===================================================================
> --- a/drivers/ide/ide-lib.c
> +++ b/drivers/ide/ide-lib.c
> @@ -69,123 +69,34 @@ char *ide_xfer_verbose (u8 xfer_rate)
>  EXPORT_SYMBOL(ide_xfer_verbose);
>  
>  /**
> - *	ide_dma_speed	-	compute DMA speed
> - *	@drive: drive
> - *	@mode:	modes available
> - *
> - *	Checks the drive capabilities and returns the speed to use
> - *	for the DMA transfer.  Returns 0 if the drive is incapable
> - *	of DMA transfers.
> - */
> - 
> -u8 ide_dma_speed(ide_drive_t *drive, u8 mode)

[...]

> -EXPORT_SYMBOL(ide_dma_speed);

    Alas, my ide_dma_speed() fix is going to be oudated rather quickly... :-)

> Index: b/drivers/ide/pci/hpt366.c
> ===================================================================
> --- a/drivers/ide/pci/hpt366.c
> +++ b/drivers/ide/pci/hpt366.c
> @@ -513,43 +513,31 @@ static int check_in_drive_list(ide_drive
>  	return 0;
>  }
>  
> -static u8 hpt3xx_ratemask(ide_drive_t *drive)
> -{
> -	struct hpt_info *info	= pci_get_drvdata(HWIF(drive)->pci_dev);
> -	u8 mode			= info->max_mode;
> -
> -	if (!eighty_ninty_three(drive) && mode)
> -		mode = min(mode, (u8)1);
> -	return mode;
> -}
> -
>  /*
>   *	Note for the future; the SATA hpt37x we must set
>   *	either PIO or UDMA modes 0,4,5
>   */
> - 
> -static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed)
> +
> +static u8 hpt3xx_filter_udma_mask(ide_drive_t *drive)
>  {
>  	struct hpt_info *info	= pci_get_drvdata(HWIF(drive)->pci_dev);
>  	u8 chip_type		= info->chip_type;
> -	u8 mode			= hpt3xx_ratemask(drive);
> -
> -	if (drive->media != ide_disk)
> -		return min(speed, (u8)XFER_PIO_4);
> +	u8 mode			= info->max_mode;
> +	u8 mask;
>  
>  	switch (mode) {
>  		case 0x04:
> -			speed = min_t(u8, speed, XFER_UDMA_6);
> +			mask = 0x7f;
>  			break;
>  		case 0x03:
> -			speed = min_t(u8, speed, XFER_UDMA_5);
> +			mask = 0x3f;
>  			if (chip_type >= HPT374)
>  				break;
>  			if (!check_in_drive_list(drive, bad_ata100_5))
>  				goto check_bad_ata33;
>  			/* fall thru */
>  		case 0x02:
> -			speed = min_t(u8, speed, XFER_UDMA_4);
> +			mask = 0x1f;
>  
>  			/*
>  			 * CHECK ME, Does this need to be changed to HPT374 ??
> @@ -560,13 +548,13 @@ static u8 hpt3xx_ratefilter(ide_drive_t 
>  			    !check_in_drive_list(drive, bad_ata66_4))
>  				goto check_bad_ata33;
>  
> -			speed = min_t(u8, speed, XFER_UDMA_3);
> +			mask = 0x0f;
>  			if (HPT366_ALLOW_ATA66_3 &&
>  			    !check_in_drive_list(drive, bad_ata66_3))
>  				goto check_bad_ata33;
>  			/* fall thru */
>  		case 0x01:
> -			speed = min_t(u8, speed, XFER_UDMA_2);
> +			mask = 0x07;
>  
>  		check_bad_ata33:
>  			if (chip_type >= HPT370A)
> @@ -576,10 +564,10 @@ static u8 hpt3xx_ratefilter(ide_drive_t 
>  			/* fall thru */
>  		case 0x00:
>  		default:
> -			speed = min_t(u8, speed, XFER_MW_DMA_2);
> +			mask = 0x00;
>  			break;
>  	}
> -	return speed;
> +	return mask;
>  }

    Erm, I see.  This driver will need some redesign because 'struct hpt_info' 
was fitted for the old rate filtering model.  Looks like the 'max_mode' field 
should be replaced by 'ultra_mask' there...

>  static u32 get_speed_setting(u8 speed, struct hpt_info *info)
> @@ -607,12 +595,19 @@ static int hpt36x_tune_chipset(ide_drive
>  	ide_hwif_t *hwif	= HWIF(drive);
>  	struct pci_dev  *dev	= hwif->pci_dev;
>  	struct hpt_info	*info	= pci_get_drvdata(dev);
> -	u8  speed		= hpt3xx_ratefilter(drive, xferspeed);
> +	u8  speed		= ide_rate_filter(drive, xferspeed);
>  	u8  itr_addr		= drive->dn ? 0x44 : 0x40;
> -	u32 itr_mask		= speed < XFER_MW_DMA_0 ? 0x30070000 :
> -				 (speed < XFER_UDMA_0   ? 0xc0070000 : 0xc03800ff);
> -	u32 new_itr		= get_speed_setting(speed, info);
>  	u32 old_itr		= 0;
> +	u32 itr_mask, new_itr;
> +
> +	/* TODO: move this to ide_rate_filter() [ check ->atapi_dma ] */
> +	if (drive->media != ide_disk)
> +		speed = min_t(u8, speed, XFER_PIO_4);
> +

    When I think about it, it seems quite stupid to set a PIO mode instead of 
a requested DMA one.  So, this is actually a questionable piece of code in 
this driver...

    Well, I must note the sorrow fact that both the IDE susbsytem as a whole 
doesn't keep track of PIO/DMA modes separately (having only current_mode) and 
the many drivers also fail to handle the timing registers shared by PIO/DMA 
modes correctly (well, it's actually also a hardware design issue :-).

> +	itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 :
> +		  (speed < XFER_UDMA_0   ? 0xc0070000 : 0xc03800ff);
> +
> +	new_itr = get_speed_setting(speed, info);

    Well, I liked this code where it was. But anyway, it's going to be 
replaced RSN...

> @@ -632,12 +627,19 @@ static int hpt37x_tune_chipset(ide_drive
>  	ide_hwif_t *hwif	= HWIF(drive);
>  	struct pci_dev  *dev	= hwif->pci_dev;
>  	struct hpt_info	*info	= pci_get_drvdata(dev);
> -	u8  speed		= hpt3xx_ratefilter(drive, xferspeed);
> +	u8  speed		= ide_rate_filter(drive, xferspeed);
>  	u8  itr_addr		= 0x40 + (drive->dn * 4);
> -	u32 itr_mask		= speed < XFER_MW_DMA_0 ? 0x303c0000 :
> -				 (speed < XFER_UDMA_0   ? 0xc03c0000 : 0xc1c001ff);
> -	u32 new_itr		= get_speed_setting(speed, info);
>  	u32 old_itr		= 0;
> +	u32 itr_mask, new_itr;
> +
> +	/* TODO: move this to ide_rate_filter() [ check ->atapi_dma ] */
> +	if (drive->media != ide_disk)
> +		speed = min_t(u8, speed, XFER_PIO_4);
> +
> +	itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 :
> +		  (speed < XFER_UDMA_0   ? 0xc03c0000 : 0xc1c001ff);
> +
> +	new_itr = get_speed_setting(speed, info);

    Same comments here...

> Index: b/drivers/ide/pci/serverworks.c
> ===================================================================
> --- a/drivers/ide/pci/serverworks.c
> +++ b/drivers/ide/pci/serverworks.c
> @@ -65,16 +65,16 @@ static int check_in_drive_lists (ide_dri
>  	return 0;
>  }
>  
> -static u8 svwks_ratemask (ide_drive_t *drive)
> +static u8 svwks_filter_udma_mask(ide_drive_t *drive)
>  {
>  	struct pci_dev *dev     = HWIF(drive)->pci_dev;
> -	u8 mode = 0;
> +	u8 mask = 0;

    Hm, this looks like it needs rework...

>  	if (!svwks_revision)
>  		pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision);
>  
>  	if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
> -		return 2;
> +		return 0x1f;
>  	if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
>  		u32 reg = 0;
>  		if (isa_dev)
> @@ -86,25 +86,31 @@ static u8 svwks_ratemask (ide_drive_t *d
>  		if(drive->media == ide_disk)
>  			return 0;
>  		/* Check the OSB4 DMA33 enable bit */
> -		return ((reg & 0x00004000) == 0x00004000) ? 1 : 0;
> +		return ((reg & 0x00004000) == 0x00004000) ? 0x07 : 0;
>  	} else if (svwks_revision < SVWKS_CSB5_REVISION_NEW) {
> -		return 1;
> +		return 0x07;
>  	} else if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) {
> -		u8 btr = 0;
> +		u8 btr = 0, mode;
>  		pci_read_config_byte(dev, 0x5A, &btr);
>  		mode = btr & 0x3;
> -		if (!eighty_ninty_three(drive))
> -			mode = min(mode, (u8)1);
> +
>  		/* If someone decides to do UDMA133 on CSB5 the same
>  		   issue will bite so be inclusive */
>  		if (mode > 2 && check_in_drive_lists(drive, svwks_bad_ata100))
>  			mode = 2;
> +
> +		switch(mode) {
> +		case 2:	 mask = 0x1f; break;
> +		case 1:	 mask = 0x07; break;
> +		default: mask = 0x00; break;
> +		}
>  	}
>  	if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
>  	     (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) &&
>  	    (!(PCI_FUNC(dev->devfn) & 1)))
> -		mode = 2;
> -	return mode;
> +		mask = 0x1f;
> +
> +	return mask;
>  }

    Hm, what was the problem with setting the proper masks based on PCI device 
ID in the init. code?
That'd have greatly simplified the filter...

> Index: b/drivers/ide/pci/siimage.c
> ===================================================================
> --- a/drivers/ide/pci/siimage.c
> +++ b/drivers/ide/pci/siimage.c
> @@ -116,45 +116,41 @@ static inline unsigned long siimage_seld
>  }
>  
>  /**
> - *	siimage_ratemask	-	Compute available modes
> - *	@drive: IDE drive
> + *	sil_filter_udma_mask	-	compute UDMA mask
> + *	@drive: IDE device
> + *
> + *	Compute the available UDMA speeds for the device on the interface.
>   *
> - *	Compute the available speeds for the devices on the interface.
>   *	For the CMD680 this depends on the clocking mode (scsc), for the
> - *	SI3312 SATA controller life is a bit simpler. Enforce UDMA33
> - *	as a limit if there is no 80pin cable present.
> + *	SI3112 SATA controller life is a bit simpler.
>   */
> - 
> -static byte siimage_ratemask (ide_drive_t *drive)
> +
> +static u8 sil_filter_udma_mask(ide_drive_t *drive)
>  {
> -	ide_hwif_t *hwif	= HWIF(drive);
> -	u8 mode	= 0, scsc = 0;
> +	ide_hwif_t *hwif = drive->hwif;
>  	unsigned long base = (unsigned long) hwif->hwif_data;
> +	u8 mask = 0, scsc = 0;
>  
>  	if (hwif->mmio)
>  		scsc = hwif->INB(base + 0x4A);
>  	else
>  		pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc);
>  
> -	if(is_sata(hwif))
> -	{
> -		if(strstr(drive->id->model, "Maxtor"))
> -			return 3;
> -		return 4;
> +	if (is_sata(hwif)) {
> +		mask = strstr(drive->id->model, "Maxtor") ? 0x3f : 0x7f;
> +		goto out;
>  	}
> -	
> +
>  	if ((scsc & 0x30) == 0x10)	/* 133 */
> -		mode = 4;
> +		mask = 0x7f;
>  	else if ((scsc & 0x30) == 0x20)	/* 2xPCI */
> -		mode = 4;
> +		mask = 0x7f;
>  	else if ((scsc & 0x30) == 0x00)	/* 100 */
> -		mode = 3;
> +		mask = 0x3f;
>  	else 	/* Disabled ? */
>  		BUG();

    Most probably this is doable at init. time also...

MBR, Sergei

PS: I understand that the intent wasn not to make this rewrite optimal but
do it quick and with least affect.  And I certainly may handle hpt366.c 
redesign... :-)


  reply	other threads:[~2007-01-22 19:48 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-01-19  0:30 [PATCH 0/15] IDE quilt tree updated Bartlomiej Zolnierkiewicz
2007-01-19  0:31 ` [PATCH 1/15] ACPI support for IDE devices Bartlomiej Zolnierkiewicz
2007-01-19  0:31 ` [PATCH 2/15] via82cxxx/pata_via: correct PCI_DEVICE_ID_VIA_SATA_EIDE ID and add support for CX700 and 8237S Bartlomiej Zolnierkiewicz
2007-01-19  0:31 ` [PATCH 3/15] it8213: fix build and ->ultra_mask Bartlomiej Zolnierkiewicz
2007-01-19  0:31 ` [PATCH 4/15] ide: convert ide_hwif_t.mmio into flag Bartlomiej Zolnierkiewicz
2007-01-19  0:31 ` [PATCH 5/15] hpt34x: hpt34x_tune_chipset() (->speedproc) fix Bartlomiej Zolnierkiewicz
2007-01-19  0:31 ` [PATCH 6/15] atiixp/jmicron/triflex: fix PIO fallback Bartlomiej Zolnierkiewicz
2007-01-19  0:31 ` [PATCH 7/15] piix: cleanup Bartlomiej Zolnierkiewicz
2007-01-19  0:31 ` [PATCH 8/15] ide: disable DMA in ->ide_dma_check for "no IORDY" case Bartlomiej Zolnierkiewicz
2007-01-19 16:26   ` Sergei Shtylyov
     [not found]     ` <58cb370e0701191047h524434eobdb9d86ed614bc71@mail.gmail.com>
2007-01-19 19:11       ` Bartlomiej Zolnierkiewicz
2007-01-19 19:35         ` Sergei Shtylyov
     [not found]           ` <58cb370e0701191200i10119313i4aacae9c504a02e4@mail.gmail.com>
2007-01-19 21:43             ` Bartlomiej Zolnierkiewicz
2007-01-20 17:09               ` Sergei Shtylyov
     [not found]                 ` <58cb370e0701200947p578f4d74g1fee511ded6c9a77@mail.gmail.com>
2007-01-20 18:21                   ` Bartlomiej Zolnierkiewicz
2007-01-20 18:41                     ` Sergei Shtylyov
2007-01-25 17:03                     ` Sergei Shtylyov
2007-01-19  0:32 ` [PATCH 9/15] sgiioc4: fix sgiioc4_ide_dma_check() to enable/disable DMA properly Bartlomiej Zolnierkiewicz
2007-01-19  0:32 ` [PATCH 10/15] ide: add ide_set_dma() helper Bartlomiej Zolnierkiewicz
2007-01-20 20:22   ` Sergei Shtylyov
2007-01-19  0:32 ` [PATCH 11/15] ide: make ide_hwif_t.ide_dma_{host_off,off_quietly} void Bartlomiej Zolnierkiewicz
2007-01-20 20:56   ` Sergei Shtylyov
     [not found]     ` <58cb370e0702021206h205ff983r88fb4bdbea42ed9f@mail.gmail.com>
2007-02-02 22:39       ` Bartlomiej Zolnierkiewicz
2007-01-19  0:32 ` [PATCH 12/15] ide: make ide_hwif_t.ide_dma_host_on void Bartlomiej Zolnierkiewicz
2007-01-20 20:46   ` Sergei Shtylyov
     [not found]     ` <58cb370e0702021128g15cac87ar507c20e78ded9464@mail.gmail.com>
2007-02-02 21:16       ` Bartlomiej Zolnierkiewicz
2007-03-26 17:19   ` Sergei Shtylyov
2007-04-20 20:36     ` Sergei Shtylyov
2007-01-19  0:32 ` [PATCH 13/15] ide: fix UDMA/MWDMA/SWDMA masks Bartlomiej Zolnierkiewicz
2007-01-22 16:19   ` Sergei Shtylyov
     [not found]     ` <58cb370e0702021606v4efa6143lf060e6aab9782c35@mail.gmail.com>
2007-02-03  0:39       ` Bartlomiej Zolnierkiewicz
2007-02-03 16:30         ` Sergei Shtylyov
2007-01-22 18:17   ` Sergei Shtylyov
2007-01-22 18:46     ` Alan
2007-01-22 20:28       ` Sergei Shtylyov
2007-01-22 21:31         ` Alan
2007-01-22 22:39           ` Jeff Garzik
     [not found]             ` <45B6071C.90703@ru.mvista.com>
     [not found]               ` <45B761F8.1060505@ru.mvista.com>
2007-01-25 22:20                 ` Updated SiI h/w docs (was Re: [PATCH 13/15] ide: fix UDMA/MWDMA/SWDMA masks) Jeff Garzik
2007-01-26 13:14                   ` Sergei Shtylyov
2007-01-23 14:51           ` [PATCH 13/15] ide: fix UDMA/MWDMA/SWDMA masks Sergei Shtylyov
2007-01-25 15:40             ` Sergei Shtylyov
2007-01-31 20:38       ` Sergei Shtylyov
2007-01-31 23:24         ` Alan
     [not found]     ` <58cb370e0702021606m4eb6f682xfa4bf769d398cf9@mail.gmail.com>
2007-02-03  0:50       ` Bartlomiej Zolnierkiewicz
2007-01-19  0:32 ` [PATCH 14/15] ide: rework the code for selecting the best DMA transfer mode Bartlomiej Zolnierkiewicz
2007-01-22 19:48   ` Sergei Shtylyov [this message]
     [not found]     ` <58cb370e0702021207o435f39cdsf3abb0d55829fc45@mail.gmail.com>
2007-02-02 23:57       ` Bartlomiej Zolnierkiewicz
2007-01-19  0:32 ` [PATCH 15/15] ide: add ide_tune_dma() helper Bartlomiej Zolnierkiewicz
2007-02-03 13:53 [PATCH 11/15] ide: make ide_hwif_t.ide_dma_{host_off,off_quietly} void Bartlomiej Zolnierkiewicz
2007-02-03 13:53 ` [PATCH 14/15] ide: rework the code for selecting the best DMA transfer mode Bartlomiej Zolnierkiewicz
2007-04-19 19:31   ` Sergei Shtylyov
2007-04-19 19:41     ` Sergei Shtylyov
2007-04-19 19:46       ` Sergei Shtylyov
2007-04-20 15:03       ` Sergei Shtylyov
2007-04-20 18:00         ` Sergei Shtylyov
2007-04-23 22:25           ` Bartlomiej Zolnierkiewicz

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=45B51505.4040905@ru.mvista.com \
    --to=sshtylyov@ru.mvista.com \
    --cc=bzolnier@gmail.com \
    --cc=linux-ide@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.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.