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

Cache object: ce422967e80c73ee2ff0ae827bc4669f


[ 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.