File:  [DragonFly] / src / sys / dev / disk / i386 / bs / Attic / bshw_dma.c
Revision 1.3: download - view: text, annotated - select for diffs
Wed Aug 27 10:35:16 2003 UTC (11 years, 1 month ago) by rob
Branches: MAIN
CVS tags: HEAD
remove __P() from this directory

    1: /* $FreeBSD: src/sys/i386/isa/bs/bshw_dma.c,v 1.6.6.1 2000/10/21 07:44:26 nyan Exp $ */
    2: /* $DragonFly: src/sys/dev/disk/i386/bs/bshw_dma.c,v 1.3 2003/08/27 10:35:16 rob Exp $ */
    3: /*	$NecBSD: bshw_dma.c,v 1.3 1997/07/26 06:03:16 honda Exp $	*/
    4: /*	$NetBSD$	*/
    5: /*
    6:  * [NetBSD for NEC PC98 series]
    7:  *  Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
    8:  *  All rights reserved.
    9:  * 
   10:  *  Redistribution and use in source and binary forms, with or without
   11:  *  modification, are permitted provided that the following conditions
   12:  *  are met:
   13:  *  1. Redistributions of source code must retain the above copyright
   14:  *     notice, this list of conditions and the following disclaimer.
   15:  *  2. Redistributions in binary form must reproduce the above copyright
   16:  *     notice, this list of conditions and the following disclaimer in the
   17:  *     documentation and/or other materials provided with the distribution.
   18:  *  3. The name of the author may not be used to endorse or promote products
   19:  *     derived from this software without specific prior written permission.
   20:  * 
   21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   23:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   24:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   25:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   26:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   27:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   29:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   30:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   31:  * POSSIBILITY OF SUCH DAMAGE.
   32:  */
   33: /*
   34:  * Copyright (c) 1994, 1995, 1996 Naofumi HONDA.  All rights reserved.
   35:  */
   36: 
   37: /*********************************************************
   38:  * static declare.
   39:  *********************************************************/
   40: static void bshw_dmastart (struct bs_softc *);
   41: static void bshw_dmadone (struct bs_softc *);
   42: 
   43: /**********************************************
   44:  * UPPER INTERFACE FUNCS (all funcs exported)
   45:  **********************************************/
   46: void
   47: bshw_dmaabort(bsc, ti)
   48: 	struct bs_softc *bsc;
   49: 	struct targ_info *ti;
   50: {
   51: 
   52: 	bshw_dmadone(bsc);
   53: 	bsc->sc_p.seglen = 0;
   54: 	bshw_set_count(bsc, 0);
   55: 
   56: 	if (ti == NULL)
   57: 	{
   58: 		int i;
   59: 		struct targ_info *tmpti;
   60: 
   61: 		for (i = 0; i < NTARGETS; i++)
   62: 			if ((tmpti = bsc->sc_ti[i]) != NULL)
   63: 				tmpti->ti_scsp.seglen = 0;
   64: 	}
   65: 	else
   66: 		ti->ti_scsp.seglen = 0;
   67: }
   68: 
   69: /* DMA TRANSFER */
   70: void
   71: bs_dma_xfer(ti, direction)
   72: 	struct targ_info *ti;
   73: 	u_int direction;
   74: {
   75: 	vm_offset_t va, endva, phys, nphys;
   76: 	struct bs_softc *bsc = ti->ti_bsc;
   77: 	struct sc_p *sp = &bsc->sc_p;
   78: 
   79: 	bsc->sc_dmadir = direction;
   80: 	bshw_set_dma_trans(bsc, ti->ti_cfgflags);
   81: 
   82: 	if (sp->seglen == 0)
   83: 	{
   84: 		phys = vtophys((vm_offset_t) sp->data);
   85: 		if (phys >= RAM_END)
   86: 		{
   87: 			/* setup segaddr */
   88: 			sp->segaddr = ti->bounce_phys;
   89: 			/* setup seglen */
   90: 			sp->seglen = sp->datalen;
   91: 			if (sp->seglen > ti->bounce_size)
   92: 				sp->seglen = ti->bounce_size;
   93: 			/* setup bufp */
   94: 			sp->bufp = ti->bounce_addr;
   95: 			if (bsc->sc_dmadir != BSHW_READ)
   96: 				bcopy(sp->data, sp->bufp, sp->seglen);
   97: #ifdef	BS_STATICS
   98: 			bs_bounce_used[ti->ti_id]++;
   99: #endif	/* BS_STATICS */
  100: 		}
  101: 		else
  102: 		{
  103: 			/* setup segaddr */
  104: 			sp->segaddr = (u_int8_t *) phys;
  105: 			/* setup seglen */
  106: 			endva = (vm_offset_t)round_page((unsigned long)(sp->data + sp->datalen));
  107: 			for (va = (vm_offset_t) sp->data; ; phys = nphys)
  108: 			{
  109: 				if ((va += BSHW_NBPG) >= endva)
  110: 				{
  111: 					sp->seglen = sp->datalen;
  112: 					break;
  113: 				}
  114: 
  115: 				nphys = vtophys(va);
  116: 				if (phys + BSHW_NBPG != nphys || nphys >= RAM_END)
  117: 				{
  118: 					sp->seglen =
  119: 					    (u_int8_t *) trunc_page(va) - sp->data;
  120: 					break;
  121: 				}
  122: 			}
  123: 			/* setup bufp */
  124: 			sp->bufp = NULL;
  125: 		}
  126: 	}
  127: 
  128: 	bshw_dmastart(bsc);
  129: 	bshw_set_count(bsc, sp->seglen);
  130: }
  131: 
  132: void
  133: bs_dma_xfer_end(ti)
  134: 	struct targ_info *ti;
  135: {
  136: 	struct bs_softc *bsc = ti->ti_bsc;
  137: 	struct sc_p *sp = &bsc->sc_p;
  138: 	u_int count, transbytes;
  139: 
  140: 	bshw_dmadone(bsc);
  141: 	if (ti->ti_phase == DATAPHASE)
  142: 	{
  143: 		count = bshw_get_count(bsc);
  144: 		if (count < (u_int) sp->seglen)
  145: 		{
  146: 			transbytes = sp->seglen - count;
  147: 			if (sp->bufp)
  148: 			{
  149: 				if (bsc->sc_dmadir == BSHW_READ)
  150: 					bcopy(sp->bufp, sp->data, transbytes);
  151: 				sp->bufp += transbytes;
  152: 			}
  153: 			sp->seglen = count;
  154: 			sp->segaddr += transbytes;
  155: 			sp->data += transbytes;
  156: 			sp->datalen -= transbytes;
  157: 			return;
  158: 		}
  159: 		else if (count == (u_int) sp->seglen)
  160: 		{
  161: 			return;
  162: 		}
  163: 
  164: 		bs_printf(ti, "xfer_end", "strange count");
  165: 		printf("port data %x seglen %x\n", count, sp->seglen);
  166: 	}
  167: 	else
  168: 		bs_printf(ti, "xfer_end", "extra dma interrupt");
  169: 
  170: 	ti->ti_error |= BSDMAABNORMAL;
  171: 	sp->seglen = ti->ti_scsp.seglen = 0;	/* XXX */
  172: }
  173: 
  174: /**********************************************
  175:  * GENERIC DMA FUNCS
  176:  **********************************************/
  177: static u_int8_t dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 };
  178: 
  179: /* common dma settings */
  180: #undef	DMA1_SMSK
  181: #define DMA1_SMSK	(0x15)
  182: #undef	DMA1_MODE
  183: #define DMA1_MODE	(0x17)
  184: #undef	DMA1_FFC
  185: #define DMA1_FFC	(0x19)
  186: #undef	DMA37SM_SET
  187: #define DMA37SM_SET	0x04
  188: #undef	DMA1_CHN
  189: #define DMA1_CHN(c)	(0x01 + ((c) << 2))
  190: 
  191: static void
  192: bshw_dmastart(bsc)
  193: 	struct bs_softc *bsc;
  194: {
  195: 	int chan = bsc->sc_dmachan;
  196: 	int waport;
  197: 	u_int8_t *phys = bsc->sc_p.segaddr;
  198: 	u_int nbytes = bsc->sc_p.seglen;
  199: 
  200: 	/*
  201: 	 * Program one of DMA channels 0..3. These are
  202: 	 * byte mode channels.
  203: 	 */
  204: 	/* set dma channel mode, and reset address ff */
  205: #ifdef __FreeBSD__
  206: 	if (need_pre_dma_flush)
  207: 		wbinvd();
  208: #else	/* NetBSD/pc98 */
  209: 	if (bsc->sc_dmadir & BSHW_READ)
  210: 		cpu_cf_preRead(curcpu);
  211: 	else
  212: 		cpu_cf_preWrite(curcpu);
  213: #endif
  214: 
  215: 	if (bsc->sc_dmadir & BSHW_READ)
  216: 		outb(DMA1_MODE, DMA37MD_SINGLE | DMA37MD_WRITE | chan);
  217: 	else
  218: 		outb(DMA1_MODE, DMA37MD_SINGLE | DMA37MD_READ | chan);
  219: 	outb(DMA1_FFC, 0);
  220: 
  221: 	/* send start address */
  222: 	waport = DMA1_CHN(chan);
  223: 	outb(waport, (u_int) phys);
  224: 	outb(waport, ((u_int) phys) >> 8);
  225: 	outb(dmapageport[chan], ((u_int) phys) >> 16);
  226: 
  227: 	/* send count */
  228: 	outb(waport + 2, --nbytes);
  229: 	outb(waport + 2, nbytes >> 8);
  230: 
  231: 	/* vendor unique hook */
  232: 	if (bsc->sc_hw->dma_start)
  233: 		(*bsc->sc_hw->dma_start)(bsc);
  234: 
  235: 	outb(DMA1_SMSK, chan);
  236: 	BUS_IOW(cmd_port, CMDP_DMES);
  237: 
  238: 	bsc->sc_flags |= BSDMASTART;
  239: }
  240: 
  241: static void
  242: bshw_dmadone(bsc)
  243: 	struct bs_softc *bsc;
  244: {
  245: 
  246: 	outb(DMA1_SMSK, (bsc->sc_dmachan | DMA37SM_SET));
  247: 	BUS_IOW(cmd_port, CMDP_DMER);
  248: 
  249: 	/* vendor unique hook */
  250: 	if (bsc->sc_hw->dma_stop)
  251: 		(*bsc->sc_hw->dma_stop)(bsc);
  252: 
  253: #ifdef __FreeBSD__
  254: 	if (need_post_dma_flush)
  255: 		invd();
  256: #else
  257: 	if (bsc->sc_dmadir & BSHW_READ)
  258: 		cpu_cf_postRead(curcpu);
  259: 	else
  260: 		cpu_cf_postWrite(curcpu);
  261: #endif
  262: 
  263: 	bsc->sc_flags &= (~BSDMASTART);
  264: }
  265: 
  266: /**********************************************
  267:  * VENDOR UNIQUE DMA FUNCS
  268:  **********************************************/
  269: static int
  270: bshw_dma_init_texa(bsc)
  271: 	struct bs_softc *bsc;
  272: {
  273: 	u_int8_t regval;
  274: 
  275: 	if ((regval = read_wd33c93(bsc, 0x37)) & 0x08)
  276: 		return 0;
  277: 
  278: 	write_wd33c93(bsc, 0x37, regval | 0x08);
  279: 	regval = read_wd33c93(bsc, 0x3f);
  280: 	write_wd33c93(bsc, 0x3f, regval | 0x08);
  281: 	return 1;
  282: }
  283: 
  284: static int
  285: bshw_dma_init_sc98(bsc)
  286: 	struct bs_softc *bsc;
  287: {
  288: 
  289: 	if (read_wd33c93(bsc, 0x37) & 0x08)
  290: 		return 0;
  291: 
  292: 	/* If your card is SC98 with bios ver 1.01 or 1.02 under no PCI */
  293: 	write_wd33c93(bsc, 0x37, 0x1a);
  294: 	write_wd33c93(bsc, 0x3f, 0x1a);
  295: #if	0
  296: 	/* only valid for IO */
  297: 	write_wd33c93(bsc, 0x40, 0xf4);
  298: 	write_wd33c93(bsc, 0x41, 0x9);
  299: 	write_wd33c93(bsc, 0x43, 0xff);
  300: 	write_wd33c93(bsc, 0x46, 0x4e);
  301: 
  302: 	write_wd33c93(bsc, 0x48, 0xf4);
  303: 	write_wd33c93(bsc, 0x49, 0x9);
  304: 	write_wd33c93(bsc, 0x4b, 0xff);
  305: 	write_wd33c93(bsc, 0x4e, 0x4e);
  306: #endif
  307: 	return 1;
  308: }
  309: 
  310: static void
  311: bshw_dma_start_sc98(bsc)
  312: 	struct bs_softc *bsc;
  313: {
  314: 
  315: 	write_wd33c93(bsc, 0x73, 0x32);
  316: 	write_wd33c93(bsc, 0x74, 0x23);
  317: }
  318: 
  319: static void
  320: bshw_dma_stop_sc98(bsc)
  321: 	struct bs_softc *bsc;
  322: {
  323: 
  324: 	write_wd33c93(bsc, 0x73, 0x43);
  325: 	write_wd33c93(bsc, 0x74, 0x34);
  326: }
  327: 
  328: static void
  329: bshw_dma_start_elecom(bsc)
  330: 	struct bs_softc *bsc;
  331: {
  332: 	u_int8_t tmp = read_wd33c93(bsc, 0x4c);
  333: 
  334: 	write_wd33c93(bsc, 0x32, tmp & 0xdf);
  335: }
  336: 
  337: static void
  338: bshw_dma_stop_elecom(bsc)
  339: 	struct bs_softc *bsc;
  340: {
  341: 	u_int8_t tmp = read_wd33c93(bsc, 0x4c);
  342: 
  343: 	write_wd33c93(bsc, 0x32, tmp | 0x20);
  344: }