File:  [DragonFly] / src / sys / dev / disk / ct / Attic / bshw_machdep.c
Revision 1.4: download - view: text, annotated - select for diffs
Wed Aug 27 10:35:16 2003 UTC (10 years, 7 months ago) by rob
Branches: MAIN
CVS tags: HEAD
remove __P() from this directory

    1: /* $FreeBSD: src/sys/dev/ct/bshw_machdep.c,v 1.3.2.1 2001/07/26 02:32:18 nyan Exp $ */
    2: /* $DragonFly: src/sys/dev/disk/ct/bshw_machdep.c,v 1.4 2003/08/27 10:35:16 rob Exp $ */
    3: /*	$NecBSD: bshw_machdep.c,v 1.8.12.6 2001/06/29 06:28:05 honda Exp $	*/
    4: /*	$NetBSD$	*/
    5: 
    6: /*
    7:  * [NetBSD for NEC PC-98 series]
    8:  *  Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
    9:  *	NetBSD/pc98 porting staff. All rights reserved.
   10:  * 
   11:  *  Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
   12:  *	Naofumi HONDA.  All rights reserved.
   13:  *
   14:  *  Redistribution and use in source and binary forms, with or without
   15:  *  modification, are permitted provided that the following conditions
   16:  *  are met:
   17:  *  1. Redistributions of source code must retain the above copyright
   18:  *     notice, this list of conditions and the following disclaimer.
   19:  *  2. Redistributions in binary form must reproduce the above copyright
   20:  *     notice, this list of conditions and the following disclaimer in the
   21:  *     documentation and/or other materials provided with the distribution.
   22:  *  3. The name of the author may not be used to endorse or promote products
   23:  *     derived from this software without specific prior written permission.
   24:  * 
   25:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   26:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   27:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   28:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   29:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   30:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   31:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   33:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   34:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   35:  * POSSIBILITY OF SUCH DAMAGE.
   36:  */
   37: 
   38: #include "opt_ddb.h"
   39: 
   40: #include <sys/param.h>
   41: #include <sys/systm.h>
   42: #include <sys/kernel.h>
   43: #if defined(__FreeBSD__) && __FreeBSD_version > 500001
   44: #include <sys/bio.h>
   45: #endif	/* __ FreeBSD__ */
   46: #include <sys/buf.h>
   47: #include <sys/queue.h>
   48: #include <sys/malloc.h>
   49: #include <sys/errno.h>
   50: 
   51: #include <vm/vm.h>
   52: 
   53: #ifdef __NetBSD__
   54: #include <sys/device.h>
   55: 
   56: #include <machine/bus.h>
   57: #include <machine/intr.h>
   58: 
   59: #include <dev/scsipi/scsi_all.h>
   60: #include <dev/scsipi/scsipi_all.h>
   61: #include <dev/scsipi/scsiconf.h>
   62: #include <dev/scsipi/scsi_disk.h>
   63: 
   64: #include <machine/dvcfg.h>
   65: #include <machine/physio_proc.h>
   66: 
   67: #include <i386/Cbus/dev/scsi_low.h>
   68: 
   69: #include <dev/ic/wd33c93reg.h>
   70: #include <i386/Cbus/dev/ct/ctvar.h>
   71: #include <i386/Cbus/dev/ct/ct_machdep.h>
   72: #include <i386/Cbus/dev/ct/bshwvar.h>
   73: #endif /* __NetBSD__ */
   74: 
   75: #ifdef __FreeBSD__
   76: #include <machine/bus.h>
   77: #include <machine/clock.h>
   78: #include <machine/md_var.h>
   79: 
   80: #include <machine/dvcfg.h>
   81: #include <machine/physio_proc.h>
   82: 
   83: #include <bus/cam/scsi/scsi_low.h>
   84: 
   85: #include <dev/ic/wd33c93reg.h>
   86: #include "ctvar.h"
   87: #include "ct_machdep.h"
   88: #include "bshwvar.h"
   89: 
   90: #include <vm/pmap.h>
   91: #endif /* __FreeBSD__ */
   92: 
   93: #define	BSHW_IO_CONTROL_FLAGS	0
   94: 
   95: u_int bshw_io_control = BSHW_IO_CONTROL_FLAGS;
   96: int bshw_data_read_bytes = 4096;
   97: int bshw_data_write_bytes = 4096;
   98: 
   99: /*********************************************************
  100:  * OS dep part
  101:  *********************************************************/
  102: #ifdef	__NetBSD__
  103: #define	BSHW_PAGE_SIZE NBPG
  104: #endif	/* __NetBSD__ */
  105: 
  106: #ifdef	__FreeBSD__
  107: #define	BSHW_PAGE_SIZE PAGE_SIZE
  108: typedef	unsigned long vaddr_t;
  109: #endif /* __FreeBSD__ */
  110: 
  111: /*********************************************************
  112:  * GENERIC MACHDEP FUNCTIONS
  113:  *********************************************************/
  114: void
  115: bshw_synch_setup(ct, ti)
  116: 	struct ct_softc *ct;
  117: 	struct targ_info *ti;
  118: {
  119: 	struct ct_bus_access_handle *chp = &ct->sc_ch;
  120: 	struct ct_targ_info *cti = (void *) ti;
  121: 	struct bshw_softc *bs = ct->ct_hw;
  122: 	struct bshw *hw = bs->sc_hw;
  123: 
  124: 	if (hw->hw_sregaddr == 0)
  125: 		return;
  126: 
  127: 	ct_cr_write_1(chp, hw->hw_sregaddr + ti->ti_id, cti->cti_syncreg);
  128: 	if (hw->hw_flags & BSHW_DOUBLE_DMACHAN)
  129: 	{
  130: 		ct_cr_write_1(chp, hw->hw_sregaddr + ti->ti_id + 8, 
  131: 			      cti->cti_syncreg);
  132: 	}
  133: }
  134: 
  135: void
  136: bshw_bus_reset(ct)
  137: 	struct ct_softc *ct;
  138: {
  139: 	struct scsi_low_softc *slp = &ct->sc_sclow;
  140: 	struct ct_bus_access_handle *chp = &ct->sc_ch;
  141: 	struct bshw_softc *bs = ct->ct_hw;
  142: 	struct bshw *hw = bs->sc_hw;
  143: 	bus_addr_t offs;
  144: 	u_int8_t regv;
  145: 	int i;
  146: 
  147: 	/* open hardware busmaster mode */
  148: 	if (hw->hw_dma_init != NULL && ((*hw->hw_dma_init)(ct)) != 0)
  149: 	{
  150: 		printf("%s: change mode using external DMA (%x)\n",
  151: 		    slp->sl_xname, (u_int)ct_cr_read_1(chp, 0x37));
  152: 	}
  153: 
  154: 	/* clear hardware synch registers */
  155: 	offs = hw->hw_sregaddr;
  156: 	if (offs != 0)
  157: 	{
  158: 		for (i = 0; i < 8; i ++, offs ++)
  159: 		{
  160: 			ct_cr_write_1(chp, offs, 0);
  161: 			if ((hw->hw_flags & BSHW_DOUBLE_DMACHAN) != 0)
  162: 				ct_cr_write_1(chp, offs + 8, 0);
  163: 		}
  164: 	}
  165: 
  166: 	/* disable interrupt & assert reset */
  167: 	regv = ct_cr_read_1(chp, wd3s_mbank);
  168: 	regv |= MBR_RST;
  169: 	regv &= ~MBR_IEN;
  170: 	ct_cr_write_1(chp, wd3s_mbank, regv);
  171: 
  172: 	SCSI_LOW_DELAY(500000);
  173: 
  174: 	/* reset signal off */
  175: 	regv &= ~MBR_RST;
  176: 	ct_cr_write_1(chp, wd3s_mbank, regv);
  177: 
  178: 	/* interrupt enable */
  179: 	regv |= MBR_IEN;
  180: 	ct_cr_write_1(chp, wd3s_mbank, regv);
  181: }
  182: 
  183: /* probe */
  184: int
  185: bshw_read_settings(chp, bs)
  186: 	struct ct_bus_access_handle *chp;
  187: 	struct bshw_softc *bs;
  188: {
  189: 	static int irq_tbl[] = { 3, 5, 6, 9, 12, 13 };
  190: 
  191: 	bs->sc_hostid = (ct_cr_read_1(chp, wd3s_auxc) & AUXCR_HIDM);
  192: 	bs->sc_irq = irq_tbl[(ct_cr_read_1(chp, wd3s_auxc) >> 3) & 7];
  193: 	bs->sc_drq = ct_cmdp_read_1(chp) & 3;
  194: 	return 0;
  195: }
  196: 
  197: /*********************************************************
  198:  * DMA PIO TRANSFER (SMIT)
  199:  *********************************************************/
  200: #define	LC_SMIT_TIMEOUT	2	/* 2 sec: timeout for a fifo status ready */
  201: #define	LC_SMIT_OFFSET	0x1000
  202: #define	LC_FSZ		DEV_BSIZE
  203: #define	LC_SFSZ		0x0c
  204: #define	LC_REST		(LC_FSZ - LC_SFSZ)
  205: 
  206: #define	BSHW_LC_FSET	0x36
  207: #define	BSHW_LC_FCTRL	0x44
  208: #define	FCTRL_EN	0x01
  209: #define	FCTRL_WRITE	0x02
  210: 
  211: #define	SF_ABORT	0x08
  212: #define	SF_RDY		0x10
  213: 
  214: static __inline void bshw_lc_smit_start (struct ct_softc *, int, u_int);
  215: static __inline void bshw_lc_smit_stop (struct ct_softc *);
  216: static int bshw_lc_smit_fstat (struct ct_softc *, int, int);
  217: 
  218: static __inline void
  219: bshw_lc_smit_stop(ct)
  220: 	struct ct_softc *ct;
  221: {
  222: 	struct ct_bus_access_handle *chp = &ct->sc_ch;
  223: 
  224: 	ct_cr_write_1(chp, BSHW_LC_FCTRL, 0);
  225: 	ct_cmdp_write_1(chp, CMDP_DMER);
  226: }
  227: 
  228: static __inline void
  229: bshw_lc_smit_start(ct, count, direction)
  230: 	struct ct_softc *ct;
  231: 	int count;
  232: 	u_int direction;
  233: {
  234: 	struct ct_bus_access_handle *chp = &ct->sc_ch;
  235: 	u_int8_t pval, val;
  236: 
  237: 	val = ct_cr_read_1(chp, BSHW_LC_FSET);
  238: 	cthw_set_count(chp, count);
  239: 
  240: 	pval = FCTRL_EN;
  241: 	if (direction == SCSI_LOW_WRITE)
  242: 		pval |= (val & 0xe0) | FCTRL_WRITE;
  243: 	ct_cr_write_1(chp, BSHW_LC_FCTRL, pval);
  244: 	ct_cr_write_1(chp, wd3s_cmd, WD3S_TFR_INFO);
  245: }
  246: 
  247: static int
  248: bshw_lc_smit_fstat(ct, wc, read)
  249: 	struct ct_softc *ct;
  250: 	int wc, read;
  251: {
  252: 	struct ct_bus_access_handle *chp = &ct->sc_ch;
  253: 	u_int8_t stat;
  254: 
  255: 	while (wc -- > 0)
  256: 	{
  257: 		chp->ch_bus_weight(chp);
  258: 		stat = ct_cmdp_read_1(chp);
  259: 		if (read == SCSI_LOW_READ)
  260: 		{
  261: 			if ((stat & SF_RDY) != 0)
  262: 				return 0;
  263: 			if ((stat & SF_ABORT) != 0)
  264: 				return EIO;
  265: 		}
  266: 		else
  267: 		{
  268: 			if ((stat & SF_ABORT) != 0)
  269: 				return EIO;
  270: 			if ((stat & SF_RDY) != 0)
  271: 				return 0;
  272: 		}
  273: 	}
  274: 
  275: 	printf("%s: SMIT fifo status timeout\n", ct->sc_sclow.sl_xname);
  276: 	return EIO;
  277: }
  278: 
  279: void
  280: bshw_smit_xfer_stop(ct)
  281: 	struct ct_softc *ct;
  282: {
  283: 	struct scsi_low_softc *slp = &ct->sc_sclow;
  284: 	struct bshw_softc *bs = ct->ct_hw;
  285: 	struct targ_info *ti;
  286: 	struct sc_p *sp = &slp->sl_scp;
  287: 	u_int count;
  288: 
  289: 	bshw_lc_smit_stop(ct);
  290: 
  291: 	ti = slp->sl_Tnexus;
  292: 	if (ti == NULL)
  293: 		return;
  294: 
  295: 	if (ti->ti_phase == PH_DATA)
  296: 	{
  297: 		count = cthw_get_count(&ct->sc_ch);
  298: 		if (count < bs->sc_sdatalen)
  299: 		{
  300: 			if (sp->scp_direction == SCSI_LOW_READ &&
  301: 			    count != bs->sc_edatalen)
  302: 				goto bad;
  303: 
  304: 			count = bs->sc_sdatalen - count;
  305: 			if (count > (u_int) sp->scp_datalen)
  306: 				goto bad;
  307: 
  308: 			sp->scp_data += count;
  309: 			sp->scp_datalen -= count;
  310: 		}
  311: 		else if (count > bs->sc_sdatalen)
  312: 		{
  313: bad:
  314: 			printf("%s: smit_xfer_end: cnt error\n", slp->sl_xname);
  315: 			slp->sl_error |= PDMAERR;
  316: 		}
  317: 		scsi_low_data_finish(slp);
  318: 	}
  319: 	else
  320: 	{
  321: 		printf("%s: smit_xfer_end: phase miss\n", slp->sl_xname);
  322: 		slp->sl_error |= PDMAERR;
  323: 	}
  324: }
  325: 
  326: int
  327: bshw_smit_xfer_start(ct)
  328: 	struct ct_softc *ct;
  329: {
  330: 	struct scsi_low_softc *slp = &ct->sc_sclow;
  331: 	struct ct_bus_access_handle *chp = &ct->sc_ch;
  332: 	struct bshw_softc *bs = ct->ct_hw;
  333: 	struct sc_p *sp = &slp->sl_scp;
  334: 	struct targ_info *ti = slp->sl_Tnexus;
  335: 	struct ct_targ_info *cti = (void *) ti;
  336: 	u_int datalen, count, io_control;
  337: 	int wc;
  338: 	u_int8_t *data;
  339: 
  340: 	io_control = bs->sc_io_control | bshw_io_control;
  341: 	if ((io_control & BSHW_SMIT_BLOCK) != 0)
  342: 		return EINVAL;
  343: 
  344: 	if ((slp->sl_scp.scp_datalen % DEV_BSIZE) != 0)
  345: 		return EINVAL;
  346: 
  347: 	datalen = sp->scp_datalen;
  348: 	if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
  349: 	{
  350: 		if ((io_control & BSHW_READ_INTERRUPT_DRIVEN) != 0 &&
  351: 		     datalen > bshw_data_read_bytes)
  352: 			datalen = bshw_data_read_bytes;
  353: 	}
  354: 	else 
  355: 	{
  356: 	        if ((io_control & BSHW_WRITE_INTERRUPT_DRIVEN) != 0 &&
  357: 		    datalen > bshw_data_write_bytes)
  358: 			datalen = bshw_data_write_bytes;
  359: 	}
  360: 
  361: 	bs->sc_sdatalen = datalen;
  362: 	data = sp->scp_data;
  363:  	wc = LC_SMIT_TIMEOUT * 1024 * 1024;
  364: 
  365: 	ct_cr_write_1(chp, wd3s_ctrl, ct->sc_creg | CR_DMA);
  366: 	bshw_lc_smit_start(ct, datalen, sp->scp_direction);
  367: 
  368: 	if (sp->scp_direction == SCSI_LOW_READ)
  369: 	{
  370: 		do
  371: 		{
  372: 			if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_READ))
  373: 				break;
  374: 
  375: 			count = (datalen > LC_FSZ ? LC_FSZ : datalen);
  376: 			bus_space_read_region_4(chp->ch_memt, chp->ch_memh,
  377: 				LC_SMIT_OFFSET, (u_int32_t *) data, count >> 2);
  378: 			data += count;
  379: 			datalen -= count;
  380: 		}
  381: 		while (datalen > 0);
  382: 
  383: 		bs->sc_edatalen = datalen;
  384: 	}
  385: 	else
  386: 	{
  387: 		do
  388: 		{
  389: 			if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE))
  390: 				break;
  391: 			if (cti->cti_syncreg == 0)
  392: 			{
  393: 				/* XXX:
  394: 				 * If async transfer, reconfirm a scsi phase
  395: 				 * again. Unless C bus might hang up.
  396: 			 	 */
  397: 				if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE))
  398: 					break;
  399: 			}
  400: 
  401: 			count = (datalen > LC_SFSZ ? LC_SFSZ : datalen);
  402: 			bus_space_write_region_4(chp->ch_memt, chp->ch_memh,
  403: 				LC_SMIT_OFFSET, (u_int32_t *) data, count >> 2);
  404: 			data += count;
  405: 			datalen -= count;
  406: 
  407: 			if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE))
  408: 				break;
  409: 
  410: 			count = (datalen > LC_REST ? LC_REST : datalen);
  411: 			bus_space_write_region_4(chp->ch_memt, chp->ch_memh,
  412: 						 LC_SMIT_OFFSET + LC_SFSZ, 
  413: 						 (u_int32_t *) data, count >> 2);
  414: 			data += count;
  415: 			datalen -= count;
  416: 		}
  417: 		while (datalen > 0);
  418: 	}
  419: 	return 0;
  420: }
  421: 
  422: /*********************************************************
  423:  * DMA TRANSFER (BS)
  424:  *********************************************************/
  425: static __inline void bshw_dma_write_1 \
  426: 	(struct ct_bus_access_handle *, bus_addr_t, u_int8_t);
  427: static void bshw_dmastart (struct ct_softc *);
  428: static void bshw_dmadone (struct ct_softc *);
  429: 
  430: int
  431: bshw_dma_xfer_start(ct)
  432: 	struct ct_softc *ct;
  433: {
  434: 	struct scsi_low_softc *slp = &ct->sc_sclow;
  435: 	struct sc_p *sp = &slp->sl_scp;
  436: 	struct ct_bus_access_handle *chp = &ct->sc_ch;
  437: 	struct bshw_softc *bs = ct->ct_hw;
  438: 	vaddr_t va, endva, phys, nphys;
  439: 	u_int io_control;
  440: 
  441: 	io_control = bs->sc_io_control | bshw_io_control;
  442: 	if ((io_control & BSHW_DMA_BLOCK) != 0 && sp->scp_datalen < 256)
  443: 		return EINVAL;
  444: 
  445: 	ct_cr_write_1(chp, wd3s_ctrl, ct->sc_creg | CR_DMA);
  446: 	phys = vtophys((vaddr_t) sp->scp_data);
  447: 	if (phys >= bs->sc_minphys)
  448: 	{
  449: 		/* setup segaddr */
  450: 		bs->sc_segaddr = bs->sc_bounce_phys;
  451: 		/* setup seglen */
  452: 		bs->sc_seglen = sp->scp_datalen;
  453: 		if (bs->sc_seglen > bs->sc_bounce_size)
  454: 			bs->sc_seglen = bs->sc_bounce_size;
  455: 		/* setup bufp */
  456: 		bs->sc_bufp = bs->sc_bounce_addr;
  457: 		if (sp->scp_direction == SCSI_LOW_WRITE)
  458: 			bcopy(sp->scp_data, bs->sc_bufp, bs->sc_seglen);
  459: 	}
  460: 	else
  461: 	{
  462: 		/* setup segaddr */
  463: 		bs->sc_segaddr = (u_int8_t *) phys;
  464: 		/* setup seglen */
  465: 		endva = (vaddr_t) round_page((vaddr_t) sp->scp_data + sp->scp_datalen);
  466: 		for (va = (vaddr_t) sp->scp_data; ; phys = nphys)
  467: 		{
  468: 			if ((va += BSHW_PAGE_SIZE) >= endva)
  469: 			{
  470: 				bs->sc_seglen = sp->scp_datalen;
  471: 				break;
  472: 			}
  473: 
  474: 			nphys = vtophys(va);
  475: 			if (phys + BSHW_PAGE_SIZE != nphys || nphys >= bs->sc_minphys)
  476: 			{
  477: 				bs->sc_seglen =
  478: 				    (u_int8_t *) trunc_page(va) - sp->scp_data;
  479: 				break;
  480: 			}
  481: 		}
  482: 		/* setup bufp */
  483: 		bs->sc_bufp = NULL;
  484: 	}
  485: 
  486: 	bshw_dmastart(ct);
  487: 	cthw_set_count(chp, bs->sc_seglen);
  488: 	ct_cr_write_1(chp, wd3s_cmd, WD3S_TFR_INFO);
  489: 	return 0;
  490: }
  491: 
  492: void
  493: bshw_dma_xfer_stop(ct)
  494: 	struct ct_softc *ct;
  495: {
  496: 	struct scsi_low_softc *slp = &ct->sc_sclow;
  497: 	struct sc_p *sp = &slp->sl_scp;
  498: 	struct bshw_softc *bs = ct->ct_hw;
  499: 	struct targ_info *ti;
  500: 	u_int count, transbytes;
  501: 
  502: 	bshw_dmadone(ct);
  503: 
  504:  	ti = slp->sl_Tnexus;
  505: 	if (ti == NULL)
  506: 		return;
  507: 
  508: 	if (ti->ti_phase == PH_DATA)
  509: 	{
  510: 		count = cthw_get_count(&ct->sc_ch);
  511: 		if (count < (u_int) bs->sc_seglen)
  512: 		{
  513: 			transbytes = bs->sc_seglen - count;
  514: 			if (bs->sc_bufp != NULL &&
  515: 			    sp->scp_direction == SCSI_LOW_READ)
  516: 				bcopy(bs->sc_bufp, sp->scp_data, transbytes);
  517: 
  518: 			sp->scp_data += transbytes;
  519: 			sp->scp_datalen -= transbytes;
  520: 		}
  521: 		else if (count > (u_int) bs->sc_seglen)
  522: 		{
  523: 			printf("%s: port data %x != seglen %x\n",
  524: 				slp->sl_xname, count, bs->sc_seglen);
  525: 			slp->sl_error |= PDMAERR;
  526: 		}
  527: 
  528: 		scsi_low_data_finish(slp);
  529: 	}
  530: 	else
  531: 	{
  532: 		printf("%s: extra DMA interrupt\n", slp->sl_xname);
  533: 		slp->sl_error |= PDMAERR;
  534: 	}
  535: 
  536: 	bs->sc_bufp = NULL;
  537: }
  538: 
  539: /* common dma settings */
  540: #undef	DMA1_SMSK
  541: #define DMA1_SMSK	(0x15)
  542: #undef	DMA1_MODE
  543: #define DMA1_MODE	(0x17)
  544: #undef	DMA1_FFC
  545: #define DMA1_FFC	(0x19)
  546: #undef	DMA1_CHN
  547: #define DMA1_CHN(c)	(0x01 + ((c) << 2))
  548: 
  549: #define DMA37SM_SET	0x04
  550: #define	DMA37MD_WRITE	0x04
  551: #define	DMA37MD_READ	0x08
  552: #define	DMA37MD_SINGLE	0x40
  553: 
  554: static bus_addr_t dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 };
  555: 
  556: static __inline void 
  557: bshw_dma_write_1(chp, port, val)
  558: 	struct ct_bus_access_handle *chp;
  559: 	bus_addr_t port;
  560: 	u_int8_t val;
  561: {
  562: 
  563: 	CT_BUS_WEIGHT(chp);
  564: 	outb(port, val);
  565: }
  566: 
  567: static void
  568: bshw_dmastart(ct)
  569: 	struct ct_softc *ct;
  570: {
  571: 	struct scsi_low_softc *slp = &ct->sc_sclow;
  572: 	struct bshw_softc *bs = ct->ct_hw;
  573: 	struct ct_bus_access_handle *chp = &ct->sc_ch;
  574: 	int chan = bs->sc_drq;
  575: 	bus_addr_t waport;
  576: 	u_int8_t regv, *phys = bs->sc_segaddr;
  577: 	u_int nbytes = bs->sc_seglen;
  578: 
  579: 	/* flush cpu cache */
  580: 	(*bs->sc_dmasync_before) (ct);
  581: 
  582: 	/*
  583: 	 * Program one of DMA channels 0..3. These are
  584: 	 * byte mode channels.
  585: 	 */
  586: 	/* set dma channel mode, and reset address ff */
  587: 
  588: 	if (slp->sl_scp.scp_direction == SCSI_LOW_READ)
  589: 		regv = DMA37MD_WRITE | DMA37MD_SINGLE | chan;
  590: 	else
  591: 		regv = DMA37MD_READ | DMA37MD_SINGLE | chan;
  592: 
  593: 	bshw_dma_write_1(chp, DMA1_MODE, regv);
  594: 	bshw_dma_write_1(chp, DMA1_FFC, 0);
  595: 
  596: 	/* send start address */
  597: 	waport = DMA1_CHN(chan);
  598: 	bshw_dma_write_1(chp, waport, (u_int) phys);
  599: 	bshw_dma_write_1(chp, waport, ((u_int) phys) >> 8);
  600: 	bshw_dma_write_1(chp, dmapageport[chan], ((u_int) phys) >> 16);
  601: 
  602: 	/* send count */
  603: 	bshw_dma_write_1(chp, waport + 2, --nbytes);
  604: 	bshw_dma_write_1(chp, waport + 2, nbytes >> 8);
  605: 
  606: 	/* vendor unique hook */
  607: 	if (bs->sc_hw->hw_dma_start)
  608: 		(*bs->sc_hw->hw_dma_start)(ct);
  609: 
  610: 	bshw_dma_write_1(chp, DMA1_SMSK, chan);
  611: 	ct_cmdp_write_1(chp, CMDP_DMES);
  612: }
  613: 
  614: static void
  615: bshw_dmadone(ct)
  616: 	struct ct_softc *ct;
  617: {
  618: 	struct bshw_softc *bs = ct->ct_hw;
  619: 	struct ct_bus_access_handle *chp = &ct->sc_ch;
  620: 
  621: 	bshw_dma_write_1(chp, DMA1_SMSK, (bs->sc_drq | DMA37SM_SET));
  622: 	ct_cmdp_write_1(chp, CMDP_DMER);
  623: 
  624: 	/* vendor unique hook */
  625: 	if (bs->sc_hw->hw_dma_stop)
  626: 		(*bs->sc_hw->hw_dma_stop) (ct);
  627: 
  628: 	/* flush cpu cache */
  629: 	(*bs->sc_dmasync_after) (ct);
  630: }
  631: 
  632: /**********************************************
  633:  * VENDOR UNIQUE DMA FUNCS
  634:  **********************************************/
  635: static int bshw_dma_init_sc98 (struct ct_softc *);
  636: static void bshw_dma_start_sc98 (struct ct_softc *);
  637: static void bshw_dma_stop_sc98 (struct ct_softc *);
  638: static int bshw_dma_init_texa (struct ct_softc *);
  639: static void bshw_dma_start_elecom (struct ct_softc *);
  640: static void bshw_dma_stop_elecom (struct ct_softc *);
  641: 
  642: static int
  643: bshw_dma_init_texa(ct)
  644: 	struct ct_softc *ct;
  645: {
  646: 	struct ct_bus_access_handle *chp = &ct->sc_ch;
  647: 	u_int8_t regval;
  648: 
  649: 	if ((regval = ct_cr_read_1(chp, 0x37)) & 0x08)
  650: 		return 0;
  651: 
  652: 	ct_cr_write_1(chp, 0x37, regval | 0x08);
  653: 	regval = ct_cr_read_1(chp, 0x3f);
  654: 	ct_cr_write_1(chp, 0x3f, regval | 0x08);
  655: 	return 1;
  656: }
  657: 
  658: static int
  659: bshw_dma_init_sc98(ct)
  660: 	struct ct_softc *ct;
  661: {
  662: 	struct ct_bus_access_handle *chp = &ct->sc_ch;
  663: 
  664: 	if (ct_cr_read_1(chp, 0x37) & 0x08)
  665: 		return 0;
  666: 
  667: 	/* If your card is SC98 with bios ver 1.01 or 1.02 under no PCI */
  668: 	ct_cr_write_1(chp, 0x37, 0x1a);
  669: 	ct_cr_write_1(chp, 0x3f, 0x1a);
  670: #if	0
  671: 	/* only valid for IO */
  672: 	ct_cr_write_1(chp, 0x40, 0xf4);
  673: 	ct_cr_write_1(chp, 0x41, 0x9);
  674: 	ct_cr_write_1(chp, 0x43, 0xff);
  675: 	ct_cr_write_1(chp, 0x46, 0x4e);
  676: 
  677: 	ct_cr_write_1(chp, 0x48, 0xf4);
  678: 	ct_cr_write_1(chp, 0x49, 0x9);
  679: 	ct_cr_write_1(chp, 0x4b, 0xff);
  680: 	ct_cr_write_1(chp, 0x4e, 0x4e);
  681: #endif
  682: 	return 1;
  683: }
  684: 
  685: static void
  686: bshw_dma_start_sc98(ct)
  687: 	struct ct_softc *ct;
  688: {
  689: 	struct ct_bus_access_handle *chp = &ct->sc_ch;
  690: 
  691: 	ct_cr_write_1(chp, 0x73, 0x32);
  692: 	ct_cr_write_1(chp, 0x74, 0x23);
  693: }
  694: 
  695: static void
  696: bshw_dma_stop_sc98(ct)
  697: 	struct ct_softc *ct;
  698: {
  699: 	struct ct_bus_access_handle *chp = &ct->sc_ch;
  700: 
  701: 	ct_cr_write_1(chp, 0x73, 0x43);
  702: 	ct_cr_write_1(chp, 0x74, 0x34);
  703: }
  704: 
  705: static void
  706: bshw_dma_start_elecom(ct)
  707: 	struct ct_softc *ct;
  708: {
  709: 	struct ct_bus_access_handle *chp = &ct->sc_ch;
  710: 	u_int8_t tmp = ct_cr_read_1(chp, 0x4c);
  711: 
  712: 	ct_cr_write_1(chp, 0x32, tmp & 0xdf);
  713: }
  714: 
  715: static void
  716: bshw_dma_stop_elecom(ct)
  717: 	struct ct_softc *ct;
  718: {
  719: 	struct ct_bus_access_handle *chp = &ct->sc_ch;
  720: 	u_int8_t tmp = ct_cr_read_1(chp, 0x4c);
  721: 
  722: 	ct_cr_write_1(chp, 0x32, tmp | 0x20);
  723: }
  724: 
  725: static struct bshw bshw_generic = {
  726: 	BSHW_SYNC_RELOAD,
  727: 
  728: 	0,
  729: 
  730: 	NULL,
  731: 	NULL,
  732: 	NULL,
  733: };
  734: 
  735: static struct bshw bshw_sc98 = {
  736: 	BSHW_DOUBLE_DMACHAN,
  737: 
  738: 	0x60,
  739: 
  740: 	bshw_dma_init_sc98,
  741: 	bshw_dma_start_sc98,
  742: 	bshw_dma_stop_sc98,
  743: };
  744: 
  745: static struct bshw bshw_texa = {
  746: 	BSHW_DOUBLE_DMACHAN,
  747: 
  748: 	0x60,
  749: 
  750: 	bshw_dma_init_texa,
  751: 	NULL,
  752: 	NULL,
  753: };
  754: 
  755: static struct bshw bshw_elecom = {
  756: 	0,
  757: 
  758: 	0x38,
  759: 
  760: 	NULL,
  761: 	bshw_dma_start_elecom,
  762: 	bshw_dma_stop_elecom,
  763: };
  764: 
  765: static struct bshw bshw_lc_smit = {
  766: 	BSHW_SMFIFO | BSHW_DOUBLE_DMACHAN,
  767: 
  768: 	0x60,
  769: 
  770: 	NULL,
  771: 	NULL,
  772: 	NULL,
  773: };
  774: 
  775: static struct bshw bshw_lha20X = {
  776: 	BSHW_DOUBLE_DMACHAN,
  777: 
  778: 	0x60,
  779: 
  780: 	NULL,
  781: 	NULL,
  782: 	NULL,
  783: };
  784: 
  785: /* hw tabs */
  786: static dvcfg_hw_t bshw_hwsel_array[] = {
  787: /* 0x00 */	&bshw_generic,
  788: /* 0x01 */	&bshw_sc98,
  789: /* 0x02 */	&bshw_texa,
  790: /* 0x03 */	&bshw_elecom,
  791: /* 0x04 */	&bshw_lc_smit,
  792: /* 0x05 */	&bshw_lha20X,
  793: };
  794: 
  795: struct dvcfg_hwsel bshw_hwsel = {
  796: 	DVCFG_HWSEL_SZ(bshw_hwsel_array),
  797: 	bshw_hwsel_array
  798: };