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

Cache object: 46222b7d94ab6cc419fb063c471ff647


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