File:  [DragonFly] / src / sys / dev / disk / i386 / bs / Attic / bshw.c
Revision 1.5: download - view: text, annotated - select for diffs
Fri Feb 13 01:04:14 2004 UTC (10 years, 5 months ago) by joerg
Branches: MAIN
CVS tags: HEAD, DragonFly_Stable, DragonFly_Snap29Sep2004, DragonFly_Snap13Sep2004, DragonFly_RELEASE_1_2_Slip, DragonFly_RELEASE_1_2, DragonFly_1_0_REL, DragonFly_1_0_RC1, DragonFly_1_0A_REL
Add __DragonFly__

    1: /*	$NecBSD: bshw.c,v 1.1 1997/07/18 09:19:03 kmatsuda Exp $	*/
    2: /*	$NetBSD$	*/
    3: /*	$DragonFly: src/sys/dev/disk/i386/bs/bshw.c,v 1.5 2004/02/13 01:04:14 joerg Exp $	*/
    4: /*
    5:  * [NetBSD for NEC PC98 series]
    6:  *  Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
    7:  *  All rights reserved.
    8:  * 
    9:  *  Redistribution and use in source and binary forms, with or without
   10:  *  modification, are permitted provided that the following conditions
   11:  *  are met:
   12:  *  1. Redistributions of source code must retain the above copyright
   13:  *     notice, this list of conditions and the following disclaimer.
   14:  *  2. Redistributions in binary form must reproduce the above copyright
   15:  *     notice, this list of conditions and the following disclaimer in the
   16:  *     documentation and/or other materials provided with the distribution.
   17:  *  3. The name of the author may not be used to endorse or promote products
   18:  *     derived from this software without specific prior written permission.
   19:  * 
   20:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   22:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   23:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   24:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   25:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   26:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   28:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   29:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30:  * POSSIBILITY OF SUCH DAMAGE.
   31:  */
   32: /*
   33:  * Copyright (c) 1994, 1995, 1996 Naofumi HONDA.  All rights reserved.
   34:  *
   35:  * $FreeBSD: src/sys/i386/isa/bs/bshw.c,v 1.7.2.1 2001/07/26 02:32:18 nyan Exp $
   36:  * $DragonFly: src/sys/dev/disk/i386/bs/bshw.c,v 1.5 2004/02/13 01:04:14 joerg Exp $
   37:  */
   38: 
   39: #ifdef	__NetBSD__
   40: #include <dev/isa/isadmareg.h>
   41: #include <i386/Cbus/dev/bs/bsif.h>
   42: #include <i386/Cbus/dev/bs/bshw.lst>
   43: #endif
   44: #if defined(__DragonFly__) || defined(__FreeBSD__)
   45: #include "opt_pc98.h"
   46: #include <i386/isa/ic/i8237.h>
   47: #include "bsif.h"
   48: #include "bshw.lst"
   49: #include <machine/clock.h>
   50: #include <sys/cons.h>
   51: #endif
   52: 
   53: static struct bs_softc *gbsc;
   54: 
   55: /**************************************************
   56:  * DECLARATION
   57:  **************************************************/
   58: static void bshw_force_bsmode (struct bs_softc *);
   59: 
   60: /**************************************************
   61:  * STATIC VAL
   62:  **************************************************/
   63: static int irq_tbl[] = { 3, 5, 6, 9, 12, 13 };
   64: 
   65: /**************************************************
   66:  * SCSI CMD BRANCH
   67:  **************************************************/
   68: #define	RS	(BSSAT | BSSMIT | BSLINK | BSREAD)
   69: #define	WS	(BSSAT | BSSMIT | BSLINK)
   70: #define	EOK	(BSERROROK)
   71: 
   72: u_int8_t bshw_cmd[256] = {
   73: /*   0  1   2   3   4   5   6   7   8   9   A   B   C   E   D   F */
   74: /*0*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,RS ,0  ,WS ,0  ,0  ,0  ,0  ,0  ,
   75: /*1*/0  ,0  ,EOK,0  ,0  ,0  ,0  ,0  ,0  ,0  ,EOK,0  ,0  ,0  ,0  ,0  ,
   76: /*2*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,RS ,0  ,WS ,0  ,0  ,0  ,0  ,0  ,
   77: /*3*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   78: /*4*/0  ,0  ,EOK,EOK,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   79: /*5*/0  ,0  ,0  ,0  ,EOK,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   80: /*6*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   81: /*7*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   82: /*8*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   83: /*9*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   84: /*A*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   85: /*B*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   86: /*C*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   87: /*D*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   88: /*E*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   89: /*F*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,
   90: };
   91: 
   92: #undef	RS
   93: #undef	WS
   94: #undef	EOK
   95: 
   96: /**********************************************
   97:  * init
   98:  **********************************************/
   99: static void
  100: bshw_force_bsmode(bsc)
  101: 	struct bs_softc *bsc;
  102: {
  103: 
  104: 	if (bsc->sc_flags & BSBSMODE)
  105: 		return;
  106: 	bsc->sc_flags |= BSBSMODE;
  107: 
  108: 	/*
  109: 	 * If you have memory over 16M, some stupid boards always force to
  110: 	 * use the io polling mode. Check such a case and change mode into
  111: 	 * bus master DMA. However this depends heavily on the board's
  112: 	 * specifications!
  113: 	 */
  114: 
  115: 	if (bsc->sc_hw->dma_init && ((*bsc->sc_hw->dma_init)(bsc)))
  116: 		printf("%s change mode using external DMA (%x)\n",
  117: 		    bsc->sc_dvname, (u_int)read_wd33c93(bsc, 0x37));
  118: }
  119: 
  120: #define	RESET_DEFAULT	2000
  121: 
  122: int
  123: bshw_chip_reset(bsc)
  124: 	struct bs_softc *bsc;
  125: {
  126: 	int ct;
  127: 	u_int8_t aux;
  128: 
  129: 	bshw_lock(bsc);
  130: 
  131: 	bshw_abort_cmd(bsc);
  132: 	delay(10000);
  133: 
  134: 	bshw_get_auxstat(bsc);
  135: 	bshw_get_busstat(bsc);
  136: 
  137: 	write_wd33c93(bsc, wd3s_oid, IDR_EHP | bsc->sc_cspeed | bsc->sc_hostid);
  138: 	write_wd33c93(bsc, wd3s_cmd, WD3S_RESET);
  139: 
  140: 	for (ct = RESET_DEFAULT; ct > 0; ct--)
  141: 	{
  142: 		aux = bshw_get_auxstat(bsc);
  143: 		if (aux != 0xff && (aux & STR_INT))
  144: 		{
  145: 			if (bshw_get_busstat(bsc) == 0)
  146: 				break;
  147: 
  148: 			write_wd33c93(bsc, wd3s_cmd, WD3S_RESET);
  149: 		}
  150: 		delay(1);
  151: 	}
  152: 
  153: 	if (ct == 0)
  154: 	{
  155: 		bshw_unlock(bsc);
  156: 		return ENXIO;
  157: 	}
  158: 
  159: 	bshw_force_bsmode(bsc);
  160: 
  161: 	write_wd33c93(bsc, wd3s_tout, BSHW_SEL_TIMEOUT);
  162: 	write_wd33c93(bsc, wd3s_sid, SIDR_RESEL);
  163: 	bsc->sc_flags |= BSDMATRANSFER;
  164: 	write_wd33c93(bsc, wd3s_ctrl, CR_DEFAULT);
  165: 	write_wd33c93(bsc, wd3s_synch, 0);
  166: 
  167: 	bshw_get_auxstat(bsc);
  168: 	bsc->sc_busstat = bshw_get_busstat(bsc);
  169: 	bshw_unlock(bsc);
  170: 
  171: 	return 0;
  172: }
  173: 
  174: /* scsi bus hard reset */
  175: #define	TWIDDLEWAIT	10000
  176: static int tw_pos;
  177: static char tw_chars[] = "|/-\\";
  178: 
  179: /* this is some jokes */
  180: static void
  181: twiddle_wait(void)
  182: {
  183: 
  184: 	cnputc('\b');
  185: 	cnputc(tw_chars[tw_pos++]);
  186: 	tw_pos %= (sizeof(tw_chars) - 1);
  187: 	delay(TWIDDLEWAIT);
  188: }
  189: 
  190: static void bshw_set_vsp (struct bs_softc *, u_int, u_int8_t);
  191: 
  192: static void
  193: bshw_set_vsp(bsc, chan, spva)
  194: 	struct bs_softc *bsc;
  195: 	u_int chan;
  196: 	u_int8_t spva;
  197: {
  198: 	struct bshw *hw = bsc->sc_hw;
  199: 
  200: 	if (hw->sregaddr == 0)
  201: 		return;
  202: 
  203: 	write_wd33c93(bsc, hw->sregaddr + chan, spva);
  204: 	if (hw->hw_flags & BSHW_DOUBLE_DMACHAN)
  205: 		write_wd33c93(bsc, hw->sregaddr + chan + 8, spva);
  206: }
  207: 
  208: void
  209: bshw_bus_reset(bsc)
  210: 	struct bs_softc *bsc;
  211: {
  212: 	struct targ_info *ti;
  213: 	int i, lpc;
  214: 
  215: 	if (bsc->sc_RSTdelay == 0)
  216: 		bsc->sc_RSTdelay = 6 * 1000 * 1000;
  217: 	else
  218: 	{
  219: 		/* XXX:
  220: 		 * second time reset will be requested by hardware failuer.
  221: 		 */
  222: 		bsc->sc_RSTdelay = 12 * 1000 * 1000;
  223: 	}
  224: 
  225: 	bshw_lock(bsc);
  226: 	write_wd33c93(bsc, wd3s_mbank, (bsc->sc_membank | MBR_RST) & ~MBR_IEN);
  227: 	delay(500000);
  228: 	write_wd33c93(bsc, wd3s_mbank, (bsc->sc_membank) & ~MBR_IEN);
  229: 	bshw_unlock(bsc);
  230: 
  231: 	for (lpc = 0; lpc < 2; lpc ++)
  232: 	{
  233: 		cnputc(' ');
  234: 		for (i = 0; i <= bsc->sc_RSTdelay / TWIDDLEWAIT; i++)
  235: 			twiddle_wait();
  236: 		cnputc('\b');
  237: 
  238: 		(void) read_wd33c93(bsc, wd3s_auxc);
  239: 
  240: 		delay(10000);
  241: 
  242: 		if ((read_wd33c93(bsc, wd3s_auxc) & AUXCR_RRST) == 0)
  243: 			break;
  244: 
  245: 		printf("\nreset state still continue, wait ...");
  246: 	}
  247: 
  248: 	for (i = 0; i < NTARGETS; i++)
  249: 	{
  250: 		if ((ti = bsc->sc_ti[i]) != NULL)
  251: 		{
  252: 			ti->ti_sync = 0;
  253: 			bshw_set_vsp(bsc, i, 0);
  254: 		}
  255: 	}
  256: }
  257: 
  258: /* probe */
  259: int
  260: bshw_board_probe(bsc, drq, irq)
  261: 	struct bs_softc *bsc;
  262: 	u_int *drq;
  263: 	u_int *irq;
  264: {
  265: 
  266: 	gbsc = bsc;
  267: #ifdef	SHOW_PORT
  268: 	bshw_print_port(bsc);
  269: #endif	/* SHOW_PORT */
  270: 
  271: 	bsc->sc_hostid = (read_wd33c93(bsc, wd3s_auxc) & AUXCR_HIDM);
  272: 
  273: 	if ((*irq) == IRQUNK)
  274: 		*irq = irq_tbl[(read_wd33c93(bsc, wd3s_auxc) >> 3) & 7];
  275: 
  276: 	if ((*drq) == DRQUNK)
  277: 		*drq = BUS_IOR(cmd_port) & 3;
  278: 
  279: 	bsc->sc_dmachan = *drq;
  280: 	bsc->sc_irq = (*irq);
  281: 
  282: 	bsc->sc_membank = read_wd33c93(bsc, wd3s_mbank);
  283: 	bsc->sc_membank &= ~MBR_RST;
  284: 	bsc->sc_membank |= MBR_IEN;
  285: 
  286: 	bsc->sc_cspeed = (read_wd33c93(bsc, wd3s_oid) & (~IDR_IDM));
  287: 	switch (BSC_CHIP_CLOCK(bsc->sc_cfgflags))
  288: 	{
  289: 	case 0:
  290: 		break;
  291: 
  292: 	case 1:
  293: 		bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_16_20);
  294: 		break;
  295: 
  296: 	case 2:
  297: 		bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_16_20);
  298: 		bsc->sc_cspeed |= IDR_FS_12_15;
  299: 		break;
  300: 
  301: 	case 3:
  302: 		bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_16_20);
  303: 		bsc->sc_cspeed |= IDR_FS_16_20;
  304: 		break;
  305: 	}
  306: 
  307: 	/* XXX: host id fixed(7) */
  308: 	bsc->sc_hostid = 7;
  309: 
  310: 	if (bshw_chip_reset(bsc))
  311: 		return ENXIO;
  312: 
  313: 	return 0;
  314: }
  315: 
  316: /*
  317:  * XXX:
  318:  * Assume the board clock rate must be 20Mhz (always satisfied, maybe)!
  319:  * Only 10M/s 6.6M/s 5.0M/s 3.3M/s for synchronus transfer speed set.
  320:  */
  321: #define	ILLEGAL_SYNCH
  322: #ifdef	ILLEGAL_SYNCH
  323: /*  A  10    6.6   5.0   4.0   3.3   2.8   2.5   2.0  M/s */
  324: /*  X  100   150   200   250   300   350   400   500  ns  */
  325: static u_int bshw_scsi_period[] =
  326:    {0, 25,   37,   50,   62,   75,   87,   100,  125};
  327: static u_int8_t bshw_chip_pval[] =
  328:    {0, 0xa0, 0xb0, 0x20, 0xd0, 0x30, 0xf0, 0x40, 0x50};
  329: #else	/* !ILLEGAL_SYNCH */
  330: /*  A  10    6.6   5.0   3.3   2.5 M/s */
  331: /*  X  100   150   200   300   400 ns  */
  332: static u_int bshw_scsi_period[] =
  333:    {0, 25,   37,   50,   75,   100};
  334: static u_int8_t bshw_chip_pval[] =
  335:    {0, 0xa0, 0xb0, 0x20, 0x30, 0x40};
  336: #endif	/* !ILLEGAL_SYNCH */
  337: 
  338: void
  339: bshw_adj_syncdata(sdp)
  340: 	struct syncdata *sdp;
  341: {
  342: 	int i;
  343: 
  344: 	if (sdp->offset == 0 || sdp->period < 25 || sdp->period > 100)
  345: 		sdp->offset = sdp->period = 0;
  346: 	else
  347: 	{
  348: 		for (i = 0; sdp->period > bshw_scsi_period[i] + 2; i ++)
  349: 			;
  350: 		sdp->period = bshw_scsi_period[i];
  351: 	}
  352: }
  353: 
  354: void
  355: bshw_set_synchronous(bsc, ti)
  356: 	struct bs_softc *bsc;
  357: 	struct targ_info *ti;
  358: {
  359: 	struct syncdata sd;
  360: 	int i;
  361: 
  362: 	sd = ti->ti_syncnow;
  363: 	bshw_adj_syncdata(&sd);
  364: 	for (i = 0; sd.period != bshw_scsi_period[i]; i++)
  365: 		;
  366: 
  367: 	ti->ti_sync = ((sd.offset & 0x0f) | bshw_chip_pval[i]);
  368: 	bshw_set_vsp(bsc, ti->ti_id, ti->ti_sync);
  369: 
  370: 	if (bsc->sc_nexus == ti)
  371: 		bshw_set_sync_reg(bsc, ti->ti_sync);
  372: }
  373: 
  374: /* ctrl reg */
  375: void
  376: bshw_setup_ctrl_reg(bsc, flags)
  377: 	struct bs_softc *bsc;
  378: 	u_int flags;
  379: {
  380: 	u_int8_t regval;
  381: 
  382: 	regval = (flags & BS_SCSI_NOPARITY) ? CR_DEFAULT : CR_DEFAULT_HP;
  383: 	if (bsc->sc_flags & BSDMATRANSFER)
  384: 		regval |= CR_DMA;
  385: 	write_wd33c93(bsc, wd3s_ctrl, regval);
  386: }
  387: 
  388: /* sat command */
  389: void
  390: bshw_issue_satcmd(bsc, cb, link)
  391: 	struct bs_softc *bsc;
  392: 	struct bsccb *cb;
  393: 	int link;
  394: {
  395: 	int i;
  396: 
  397: 	BUS_IOW(addr_port, wd3s_cdb);
  398: 	for (i = 0; i < cb->cmdlen - 1; i++)
  399: 		BUS_IOW(ctrl_port, cb->cmd[i]);
  400: 	BUS_IOW(ctrl_port, cb->cmd[i] | (link ? 1 : 0));
  401: }
  402: 
  403: /* lock */
  404: void
  405: bshw_lock(bsc)
  406: 	struct bs_softc *bsc;
  407: {
  408: 
  409: 	bsc->sc_hwlock++;
  410: 	write_wd33c93(bsc, wd3s_mbank, bsc->sc_membank & (~MBR_IEN));
  411: }
  412: 
  413: void
  414: bshw_unlock(bsc)
  415: 	struct bs_softc *bsc;
  416: {
  417: 
  418: 	if ((--bsc->sc_hwlock) <= 0)
  419: 		write_wd33c93(bsc, wd3s_mbank, bsc->sc_membank);
  420: }
  421: 
  422: /**********************************************
  423:  * DMA OPERATIONS
  424:  **********************************************/
  425: #ifdef	__NetBSD__
  426: #include <i386/Cbus/dev/bs/bshw_dma.c>
  427: #include <i386/Cbus/dev/bs/bshw_pdma.c>
  428: #endif
  429: #if defined(__DragonFly__) || defined(__FreeBSD__)
  430: #include "bshw_dma.c"
  431: #include "bshw_pdma.c"
  432: #endif
  433: 
  434: /**********************************************
  435:  * DEBUG
  436:  **********************************************/
  437: /* misc */
  438: void
  439: bshw_print_port(bsc)
  440: 	struct bs_softc * bsc;
  441: {
  442: 	int i, j;
  443: 	int port = 0x0;
  444: 
  445: 	if (bsc == NULL)
  446: 		bsc = gbsc;
  447: 
  448: 	printf("\n");
  449: 	for (j = 0; j <= 0x70; j += 0x10)
  450: 	{
  451: 		printf("port %x: ", port);
  452: 		for (i = 0; i < 0x10; i++)
  453: 			printf("%x ", (u_int) read_wd33c93(bsc, port++));
  454: 		printf("\n");
  455: 	}
  456: }