Subject: Re: Promise SATA300 TX4 supported?
To: Simon Burge <simonb@wasabisystems.com>
From: Douglas Wade Needham <cinnion@ka8zrt.com>
List: current-users
Date: 01/19/2006 00:08:43
	version=3.0.3
Sender: current-users-owner@NetBSD.org

I know that my dealer said that Promise has stopped selling him the
SATA 150 and even the SATA II 150 cards, and has EOLed them in favor
of the SATA300s.  So getting the pull-up into 3.0 (or even any future
2.x release if we do one) may be a good idea.

BTW...anyone know what the status of the driver for the cards such as
the SATA II 150 which use the PDC20575 chip?  Here is what scanpci
reports for the card:

    pci bus 0x0000 cardnum 0x0c function 0x00: vendor 0x105a device 0x3d75
     Promise Technology, Inc.  Device unknown

If someone has drivers they are interested in having tested, I can
test them.  Or if someone can point me to the docs for the chip and
perhaps let me know which chip it is similar to, I can see about
taking a stab at it.

Thanks!

- Doug    

Quoting Simon Burge (simonb@wasabisystems.com):
> Timo Schoeler wrote:
> 
> > does anybody know whether the Promise SATA300 TX4 is supported by NetBSD 
> > (3.0)?
> > 
> > NetBSD 3.0 release announcement [1] states that the Promise SATA150 (aka 
> > PDC203xx) is supported via pdcsata(4), which may be the SATA300 TX4's 
> > direct predecessor with a similar/equal chipset...
> 
> I've just picked up one of these myself, and support is in -current but
> not the 3.0 release.  However, the change to support the SATA300 TX4
> patches cleanly back into 3.0 and I'll be submitting a pull-up request
> so that it'll (hopefully!) be in the 3.1 release.
> 
> I've included the "cvs diff" that I'm using from my netbsd-3 source tree
> below.
> 
> Cheers,
> Simon.
> --
> Simon Burge                            <simonb@wasabisystems.com>
> NetBSD Support and Service:         http://www.wasabisystems.com/
> 
> 
> 
> Index: sys/dev/pci/pcidevs
> ===================================================================
> RCS file: /cvsroot/src/sys/dev/pci/pcidevs,v
> retrieving revision 1.701.2.20
> diff -d -p -u -r1.701.2.20 pcidevs
> --- sys/dev/pci/pcidevs	10 Jan 2006 02:10:33 -0000	1.701.2.20
> +++ sys/dev/pci/pcidevs	18 Jan 2006 21:42:47 -0000
> @@ -2418,6 +2418,8 @@ product PROMISE PDC20618	0x6626	PDC20618
>  product PROMISE PDC20619	0x6629	PDC20619 dual Ultra/133 IDE controller
>  product PROMISE PDC20620	0x6620	PDC20620 dual Ultra/133 IDE controller
>  product PROMISE PDC20621	0x6621	PDC20621 dual Ultra/133 IDE controller
> +product PROMISE PDC40718	0x3d17	PDC40718 SATA/300 IDE controller
> +product PROMISE PDC40719	0x3515	PDC40719 SATA/300 IDE controller
>  
>  /* QLogic products */
>  product QLOGIC ISP1020	0x1020	ISP1020
> Index: sys/dev/pci/pcidevs.h
> ===================================================================
> RCS file: /cvsroot/src/sys/dev/pci/pcidevs.h,v
> retrieving revision 1.702.2.19
> diff -d -p -u -r1.702.2.19 pcidevs.h
> --- sys/dev/pci/pcidevs.h	10 Jan 2006 02:12:11 -0000	1.702.2.19
> +++ sys/dev/pci/pcidevs.h	18 Jan 2006 21:42:50 -0000
> @@ -1,4 +1,4 @@
> -/*	$NetBSD: pcidevs.h,v 1.702.2.19 2006/01/10 02:12:11 snj Exp $	*/
> +/*	$NetBSD$	*/
>  
>  /*
>   * THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
> @@ -2425,6 +2425,8 @@
>  #define	PCI_PRODUCT_PROMISE_PDC20619	0x6629		/* PDC20619 dual Ultra/133 IDE controller */
>  #define	PCI_PRODUCT_PROMISE_PDC20620	0x6620		/* PDC20620 dual Ultra/133 IDE controller */
>  #define	PCI_PRODUCT_PROMISE_PDC20621	0x6621		/* PDC20621 dual Ultra/133 IDE controller */
> +#define	PCI_PRODUCT_PROMISE_PDC40718	0x3d17		/* PDC40718 SATA/300 IDE controller */
> +#define	PCI_PRODUCT_PROMISE_PDC40719	0x3515		/* PDC40719 SATA/300 IDE controller */
>  
>  /* QLogic products */
>  #define	PCI_PRODUCT_QLOGIC_ISP1020	0x1020		/* ISP1020 */
> Index: sys/dev/pci/pcidevs_data.h
> ===================================================================
> RCS file: /cvsroot/src/sys/dev/pci/pcidevs_data.h,v
> retrieving revision 1.700.2.19
> diff -d -p -u -r1.700.2.19 pcidevs_data.h
> --- sys/dev/pci/pcidevs_data.h	10 Jan 2006 02:12:11 -0000	1.700.2.19
> +++ sys/dev/pci/pcidevs_data.h	18 Jan 2006 21:42:51 -0000
> @@ -1,4 +1,4 @@
> -/*	$NetBSD: pcidevs_data.h,v 1.700.2.19 2006/01/10 02:12:11 snj Exp $	*/
> +/*	$NetBSD$	*/
>  
>  /*
>   * THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.
> @@ -8148,6 +8148,14 @@ const struct pci_product pci_products[] 
>  	    "PDC20621 dual Ultra/133 IDE controller",
>  	},
>  	{
> +	    PCI_VENDOR_PROMISE, PCI_PRODUCT_PROMISE_PDC40718,
> +	    "PDC40718 SATA/300 IDE controller",
> +	},
> +	{
> +	    PCI_VENDOR_PROMISE, PCI_PRODUCT_PROMISE_PDC40719,
> +	    "PDC40719 SATA/300 IDE controller",
> +	},
> +	{
>  	    PCI_VENDOR_QLOGIC, PCI_PRODUCT_QLOGIC_ISP1020,
>  	    "ISP1020",
>  	},
> @@ -10360,4 +10368,4 @@ const struct pci_product pci_products[] 
>  	    "Video Controller",
>  	},
>  };
> -const int pci_nproducts = 2011;
> +const int pci_nproducts = 2013;
> Index: sys/dev/pci/pdcsata.c
> ===================================================================
> RCS file: /cvsroot/src/sys/dev/pci/pdcsata.c,v
> retrieving revision 1.3
> diff -d -p -u -r1.3 pdcsata.c
> --- sys/dev/pci/pdcsata.c	27 Feb 2005 00:27:33 -0000	1.3
> +++ sys/dev/pci/pdcsata.c	18 Jan 2006 21:42:52 -0000
> @@ -1,4 +1,4 @@
> -/*	$NetBSD: pdcsata.c,v 1.3 2005/02/27 00:27:33 perry Exp $	*/
> +/*	$NetBSD: pdcsata.c,v 1.4 2005/12/04 17:39:03 christos Exp $	*/
>  
>  /*
>   * Copyright (c) 2004, Manuel Bouyer.
> @@ -38,8 +38,12 @@
>  #include <dev/pci/pcidevs.h>
>  #include <dev/pci/pciidereg.h>
>  #include <dev/pci/pciidevar.h>
> +#include <dev/ata/atareg.h>
> +#include <dev/ata/satavar.h>
> +#include <dev/ata/satareg.h>
>  
>  #define PDC203xx_NCHANNELS 4
> +#define PDC40718_NCHANNELS 4
>  
>  #define PDC203xx_BAR_IDEREGS 0x1c /* BAR where the IDE registers are mapped */
>  
> @@ -51,6 +55,11 @@ static int  pdc203xx_dma_init(void *, in
>  static void pdc203xx_dma_start(void *,int ,int);
>  static int  pdc203xx_dma_finish(void *, int, int, int);
>  
> +/* PDC205xx, PDC405xx and PDC407xx. but tested only pdc40718 */
> +static int  pdc205xx_pci_intr(void *);
> +static void pdc205xx_do_reset(struct ata_channel *, int);
> +static void pdc205xx_drv_probe(struct ata_channel *);
> +
>  static int  pdcsata_match(struct device *, struct cfdata *, void *);
>  static void pdcsata_attach(struct device *, struct device *, void *);
>  
> @@ -98,6 +107,16 @@ static const struct pciide_product_desc 
>  	  "Promise PDC20379 SATA150 controller",
>  	  pdcsata_chip_map,
>  	},
> +	{ PCI_PRODUCT_PROMISE_PDC40718,
> +	  0,
> +	  "Promise PDC40718 SATA300 controller",
> +	  pdcsata_chip_map,
> +	},
> +	{ PCI_PRODUCT_PROMISE_PDC40719,
> +	  0,
> +	  "Promise PDC40719 SATA300 controller",
> +	  pdcsata_chip_map,
> +	},
>  	{ 0,
>  	  0,
>  	  NULL,
> @@ -148,8 +167,28 @@ pdcsata_chip_map(struct pciide_softc *sc
>  		return;
>  	}
>  	intrstr = pci_intr_string(pa->pa_pc, intrhandle);
> -	sc->sc_pci_ih = pci_intr_establish(pa->pa_pc,
> -	    intrhandle, IPL_BIO, pdc203xx_pci_intr, sc);
> +
> +	switch (sc->sc_pp->ide_product) {
> +	case PCI_PRODUCT_PROMISE_PDC20318:
> +	case PCI_PRODUCT_PROMISE_PDC20319:
> +	case PCI_PRODUCT_PROMISE_PDC20371:
> +	case PCI_PRODUCT_PROMISE_PDC20375:
> +	case PCI_PRODUCT_PROMISE_PDC20376:
> +	case PCI_PRODUCT_PROMISE_PDC20377:
> +	case PCI_PRODUCT_PROMISE_PDC20378:
> +	case PCI_PRODUCT_PROMISE_PDC20379:
> +	default:
> +		sc->sc_pci_ih = pci_intr_establish(pa->pa_pc,
> +		    intrhandle, IPL_BIO, pdc203xx_pci_intr, sc);
> +		break;
> +
> +	case PCI_PRODUCT_PROMISE_PDC40718:
> +	case PCI_PRODUCT_PROMISE_PDC40719:
> +		sc->sc_pci_ih = pci_intr_establish(pa->pa_pc,
> +		    intrhandle, IPL_BIO, pdc205xx_pci_intr, sc);
> +		break;
> +	}
> +
>  	if (sc->sc_pci_ih == NULL) {
>  		aprint_error("%s: couldn't establish native-PCI interrupt",
>  		    sc->sc_wdcdev.sc_atac.atac_dev.dv_xname);
> @@ -199,10 +238,35 @@ pdcsata_chip_map(struct pciide_softc *sc
>  	sc->sc_wdcdev.sc_atac.atac_udma_cap = 6;
>  	sc->sc_wdcdev.sc_atac.atac_set_modes = pdc203xx_setup_channel;
>  	sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray;
> -	bus_space_write_4(sc->sc_ba5_st, sc->sc_ba5_sh, 0x06c, 0x00ff0033);
> -	sc->sc_wdcdev.sc_atac.atac_nchannels =
> -	    (bus_space_read_4(sc->sc_ba5_st, sc->sc_ba5_sh, 0x48) & 0x02) ?
> -	    PDC203xx_NCHANNELS : 3;
> +
> +	switch (sc->sc_pp->ide_product) {
> +	case PCI_PRODUCT_PROMISE_PDC20318:
> +	case PCI_PRODUCT_PROMISE_PDC20319:
> +	case PCI_PRODUCT_PROMISE_PDC20371:
> +	case PCI_PRODUCT_PROMISE_PDC20375:
> +	case PCI_PRODUCT_PROMISE_PDC20376:
> +	case PCI_PRODUCT_PROMISE_PDC20377:
> +	case PCI_PRODUCT_PROMISE_PDC20378:
> +	case PCI_PRODUCT_PROMISE_PDC20379:
> +	default:
> +		bus_space_write_4(sc->sc_ba5_st, sc->sc_ba5_sh, 0x6c, 0x00ff0033);
> +		sc->sc_wdcdev.sc_atac.atac_nchannels =
> +		    (bus_space_read_4(sc->sc_ba5_st, sc->sc_ba5_sh, 0x48) & 0x02) ?
> +		    PDC203xx_NCHANNELS : 3;
> +
> +		break;
> +
> +	case PCI_PRODUCT_PROMISE_PDC40718:
> +	case PCI_PRODUCT_PROMISE_PDC40719:
> +		bus_space_write_4(sc->sc_ba5_st, sc->sc_ba5_sh, 0x60, 0x00ff00ff);
> +		sc->sc_wdcdev.sc_atac.atac_nchannels = PDC40718_NCHANNELS;
> +
> +		sc->sc_wdcdev.reset = pdc205xx_do_reset;
> +		sc->sc_wdcdev.sc_atac.atac_probe = pdc205xx_drv_probe;
> +
> +		break;
> +	}
> +
>  	wdc_allocate_regs(&sc->sc_wdcdev);
>  
>  	sc->sc_wdcdev.dma_arg = sc;
> @@ -337,6 +401,38 @@ pdc203xx_pci_intr(void *arg)
>  	return rv;
>  }
>  
> +static int
> +pdc205xx_pci_intr(void *arg)
> +{
> +	struct pciide_softc *sc = arg;
> +	struct pciide_channel *cp;
> +	struct ata_channel *wdc_cp;
> +	int i, rv, crv;
> +	u_int32_t scr, status;
> +
> +	rv = 0;
> +	scr = bus_space_read_4(sc->sc_ba5_st, sc->sc_ba5_sh, 0x40);
> +	bus_space_write_4(sc->sc_ba5_st, sc->sc_ba5_sh, 0x40, scr & 0x0000ffff);
> +
> +	status = bus_space_read_4(sc->sc_ba5_st, sc->sc_ba5_sh, 0x60);
> +	bus_space_write_4(sc->sc_ba5_st, sc->sc_ba5_sh, 0x60, status & 0x000000ff);
> +
> +	for (i = 0; i < sc->sc_wdcdev.sc_atac.atac_nchannels; i++) {
> +		cp = &sc->pciide_channels[i];
> +		wdc_cp = &cp->ata_channel;
> +		if (scr & (1 << (i + 1))) {
> +			crv = wdcintr(wdc_cp);
> +			if (crv == 0) {
> +				printf("%s:%d: bogus intr (reg 0x%x)\n",
> +				    sc->sc_wdcdev.sc_atac.atac_dev.dv_xname,
> +				    i, scr);
> +			} else
> +				rv = 1;
> +		}
> +	}
> +	return rv;
> +}
> +
>  static void
>  pdc203xx_irqack(struct ata_channel *chp)
>  {
> @@ -397,3 +493,125 @@ pdc203xx_dma_finish(void *v, int channel
>  
>  	return 0;
>  }
> +
> +#define	PDC205_REGADDR(base,ch)	((base)+((ch)<<8))
> +#define	PDC205_SSTATUS(ch)	PDC205_REGADDR(0x400,ch)
> +#define	PDC205_SERROR(ch)	PDC205_REGADDR(0x404,ch)
> +#define	PDC205_SCONTROL(ch)	PDC205_REGADDR(0x408,ch)
> +#define	PDC205_MULTIPLIER(ch)	PDC205_REGADDR(0x4e8,ch)
> +
> +
> +#define	SCONTROL_WRITE(sc,channel,scontrol)	\
> +	bus_space_write_4((sc)->sc_ba5_st, (sc)->sc_ba5_sh,	\
> +	PDC205_SCONTROL(channel), scontrol)
> +
> +#define	SSTATUS_READ(sc,channel)	\
> +	bus_space_read_4((sc)->sc_ba5_st, (sc)->sc_ba5_sh,	\
> +	PDC205_SSTATUS(channel))
> +
> +
> +
> +static void
> +pdc205xx_do_reset(struct ata_channel *chp, int poll)
> +{
> +	struct pciide_softc *sc = CHAN_TO_PCIIDE(chp);
> +	u_int32_t scontrol;
> +
> +	wdc_do_reset(chp, poll);
> +
> +	/* reset SATA */
> +	scontrol = SControl_DET_INIT | SControl_SPD_ANY | SControl_IPM_NONE;
> +	SCONTROL_WRITE(sc, chp->ch_channel, scontrol);
> +	delay(50*1000);
> +
> +	scontrol &= ~SControl_DET_INIT;
> +	SCONTROL_WRITE(sc, chp->ch_channel, scontrol);
> +	delay(50*1000);
> +}
> +
> +
> +
> +static void
> +pdc205xx_drv_probe(struct ata_channel *chp)
> +{
> +	struct pciide_softc *sc = CHAN_TO_PCIIDE(chp);
> +	struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp);
> +	u_int32_t scontrol, sstatus;
> +	u_int16_t scnt, sn, cl, ch;
> +	int i, s;
> +
> +	/* XXX This should be done by other code. */
> +	for (i = 0; i < 2; i++) {
> +		chp->ch_drive[i].chnl_softc = chp;
> +		chp->ch_drive[i].drive = i;
> +	}
> +
> +	SCONTROL_WRITE(sc, chp->ch_channel, 0);
> +	delay(50*1000);
> +
> +	scontrol = SControl_DET_INIT | SControl_SPD_ANY | SControl_IPM_NONE;
> +	SCONTROL_WRITE(sc,chp->ch_channel,scontrol);
> +	delay(50*1000);
> +
> +	scontrol &= ~SControl_DET_INIT;
> +	SCONTROL_WRITE(sc,chp->ch_channel,scontrol);
> +	delay(50*1000);
> +
> +	sstatus = SSTATUS_READ(sc,chp->ch_channel);
> +
> +	switch (sstatus & SStatus_DET_mask) {
> +	case SStatus_DET_NODEV:
> +		/* No Device; be silent.  */
> +		break;
> +
> +	case SStatus_DET_DEV_NE:
> +		aprint_error("%s: port %d: device connected, but "
> +		    "communication not established\n",
> +		    sc->sc_wdcdev.sc_atac.atac_dev.dv_xname, chp->ch_channel);
> +		break;
> +
> +	case SStatus_DET_OFFLINE:
> +		aprint_error("%s: port %d: PHY offline\n",
> +		    sc->sc_wdcdev.sc_atac.atac_dev.dv_xname, chp->ch_channel);
> +		break;
> +
> +	case SStatus_DET_DEV:
> +		bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0,
> +		    WDSD_IBM);
> +		delay(10);	/* 400ns delay */
> +		scnt = bus_space_read_2(wdr->cmd_iot,
> +		    wdr->cmd_iohs[wd_seccnt], 0);
> +		sn = bus_space_read_2(wdr->cmd_iot,
> +		    wdr->cmd_iohs[wd_sector], 0);
> +		cl = bus_space_read_2(wdr->cmd_iot,
> +		    wdr->cmd_iohs[wd_cyl_lo], 0);
> +		ch = bus_space_read_2(wdr->cmd_iot,
> +		    wdr->cmd_iohs[wd_cyl_hi], 0);
> +#if 0
> +		printf("%s: port %d: scnt=0x%x sn=0x%x cl=0x%x ch=0x%x\n",
> +		    sc->sc_wdcdev.sc_atac.atac_dev.dv_xname, chp->ch_channel,
> +		    scnt, sn, cl, ch);
> +#endif
> +		/*
> +		 * scnt and sn are supposed to be 0x1 for ATAPI, but in some
> +		 * cases we get wrong values here, so ignore it.
> +		 */
> +		s = splbio();
> +		if (cl == 0x14 && ch == 0xeb)
> +			chp->ch_drive[0].drive_flags |= DRIVE_ATAPI;
> +		else
> +			chp->ch_drive[0].drive_flags |= DRIVE_ATA;
> +		splx(s);
> +#if 0
> +		aprint_normal("%s: port %d: device present, speed: %s\n",
> +		    sc->sc_wdcdev.sc_atac.atac_dev.dv_xname, chp->ch_channel,
> +		    sata_speed(sstatus));
> +#endif
> +		break;
> +
> +	default:
> +		aprint_error("%s: port %d: unknown SStatus: 0x%08x\n",
> +		    sc->sc_wdcdev.sc_atac.atac_dev.dv_xname, chp->ch_channel,
> +		    sstatus);
> +	}
> +}

-- 
Douglas Wade Needham - KA8ZRT        UN*X Consultant & UW/BSD kernel programmer
Email:  cinnion @ ka8zrt . com       http://cinnion.ka8zrt.com
Disclaimer: My opinions are my own.  Since I don't want them, why
            should my employer, or anybody else for that matter!