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

Cache object: c7774b4ceb4b394d6132ed77eaf94239


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