The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/bs/bshw.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 6cc6c892c995b513e056bc63b7791404


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.