home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / tahoe / vba / vba.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  9.6 KB  |  340 lines

  1. /*
  2.  * Copyright (c) 1987, 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)vba.c    7.6 (Berkeley) 12/16/90
  34.  */
  35.  
  36. /*
  37.  * Tahoe VERSAbus adapator support routines.
  38.  */
  39.  
  40. #include "sys/param.h"
  41. #include "sys/buf.h"
  42. #include "sys/cmap.h"
  43. #include "sys/conf.h"
  44. #include "dk.h"
  45. #include "sys/map.h"
  46. #include "sys/systm.h"
  47. #include "sys/user.h"
  48. #include "sys/vmparam.h"
  49. #include "sys/vmmac.h"
  50. #include "sys/proc.h"
  51. #include "sys/syslog.h"
  52. #include "sys/malloc.h"
  53.  
  54. #include "../include/mtpr.h"
  55. #include "../include/pte.h"
  56.  
  57. #include "../vba/vbavar.h"
  58.  
  59. /*
  60.  * Allocate private page map and intermediate buffer
  61.  * for a VERSAbus device, large enough for maximum transfer size.
  62.  * Intermediate buffer 
  63.  * Make intermediate buffer uncacheable.
  64.  */
  65. vbainit(vb, xsize, flags)
  66.     register struct vb_buf *vb;
  67.     int xsize, flags;
  68. {
  69.     register struct pte *pte;
  70.     register n;
  71.  
  72.     vb->vb_flags = flags;
  73.     if (vbmapalloc((int)btoc(xsize) + 1, &vb->vb_map, &vb->vb_utl) == 0) {
  74.         printf("vbmap exhausted\n");
  75.         return (0);
  76.     }
  77.     n = roundup(xsize, NBPG);
  78.     vb->vb_bufsize = n;
  79.     if (vb->vb_rawbuf == 0)
  80.         vb->vb_rawbuf = (caddr_t)malloc((u_long)n, M_DEVBUF, M_NOWAIT);
  81.     if (vb->vb_rawbuf == 0) {
  82.         printf("no memory for device buffer\n");
  83.         return (0);
  84.     }
  85.     if ((int)vb->vb_rawbuf & PGOFSET)
  86.         panic("vbinit pgoff");
  87.     vb->vb_physbuf = (u_long)kvtophys(vb->vb_rawbuf);
  88.     if (flags & VB_20BIT)
  89.         vb->vb_maxphys = btoc(VB_MAXADDR20);
  90.     else if (flags & VB_24BIT)
  91.         vb->vb_maxphys = btoc(VB_MAXADDR24);
  92.     else
  93.         vb->vb_maxphys = btoc(VB_MAXADDR32);
  94.     if (btoc(vb->vb_physbuf + n) > vb->vb_maxphys)
  95.         panic("vbinit physbuf");
  96.     
  97.     /*
  98.      * Make raw buffer pages uncacheable.
  99.      */
  100.     pte = kvtopte(vb->vb_rawbuf);
  101.     for (n = btoc(n); n--; pte++)
  102.         pte->pg_nc = 1;
  103.     mtpr(TBIA, 0);
  104.     return (1);
  105. }
  106.  
  107. /*
  108.  * Due to unknown hardware or software errors, some sites have problems
  109.  * with strange crashes or corruption of text images when DMA is attempted
  110.  * to kernel addresses spanning a page boundary, or to user addresses
  111.  * (even if the buffer is physically contiguous).  To avoid this behavior,
  112.  * the following toggles inhibit such transfers when set.
  113.  *    vba_copyk: copy transfers to kernel address that span a page boundary
  114.  *    vba_copyu: copy transfers to user addresses
  115.  */
  116. #ifndef VBA_TRICKY
  117. int vba_copyk = 1;
  118. int vba_copyu = 1;
  119. #else
  120. int vba_copyk = 0;
  121. int vba_copyu = 0;
  122. #endif
  123.  
  124. /*
  125.  * Check a transfer to see whether it can be done directly
  126.  * to the destination buffer, or whether it must be copied.
  127.  * On Tahoe, the lack of a bus I/O map forces data to be copied
  128.  * to a physically-contiguous buffer whenever one of the following is true:
  129.  *    1) The data length is not a multiple of sector size.
  130.  *       (The swapping code does this, unfortunately.)
  131.  *    2) The buffer is not physically contiguous and the controller
  132.  *       does not support scatter-gather operations.
  133.  *    3) The physical address for I/O is higher than addressible
  134.  *       by the device.
  135.  * This routine is called by the start routine.
  136.  * If copying is necessary, the intermediate buffer is mapped;
  137.  * if the operation is a write, the data is copied into the buffer.
  138.  * It returns the physical address of the first byte for DMA, to
  139.  * be presented to the controller.
  140.  */
  141. u_long
  142. vbasetup(bp, vb, sectsize)
  143.     register struct buf *bp;
  144.     register struct vb_buf *vb;
  145.     int sectsize;
  146. {
  147.     register struct pte *spte, *dpte;
  148.     register int p, i;
  149.     int npf, o, v;
  150.  
  151.     o = (int)bp->b_un.b_addr & PGOFSET;
  152.     npf = btoc(bp->b_bcount + o);
  153.     vb->vb_iskernel = (((int)bp->b_un.b_addr & KERNBASE) == KERNBASE);
  154.     if (vb->vb_iskernel) {
  155.         spte = kvtopte(bp->b_un.b_addr);
  156. if (vba_copyk && (o != 0 || npf > 1)) goto copy;
  157.     } else {
  158.         spte = vtopte((bp->b_flags&B_DIRTY) ? &proc[2] : bp->b_proc,
  159.             btop(bp->b_un.b_addr));
  160. if (vba_copyu) goto copy;
  161.     }
  162.     if (bp->b_bcount % sectsize != 0 || (o & (sizeof(long) - 1)) != 0)
  163.         goto copy;
  164.     else if ((vb->vb_flags & VB_SCATTER) == 0 ||
  165.         vb->vb_maxphys != btoc(VB_MAXADDR32)) {
  166.         dpte = spte;
  167.         p = (dpte++)->pg_pfnum;
  168.         for (i = npf; --i > 0; dpte++) {
  169.             if ((v = dpte->pg_pfnum) != p + CLSIZE &&
  170.                 (vb->vb_flags & VB_SCATTER) == 0)
  171.                 goto copy;
  172.             if (p >= vb->vb_maxphys)
  173.                 goto copy;
  174.             p = v;
  175.         }
  176.         if (p >= vb->vb_maxphys)
  177.             goto copy;
  178.     }
  179.     vb->vb_copy = 0;
  180.     if (vb->vb_iskernel)
  181.         vbastat.k_raw++;
  182.     else
  183.         vbastat.u_raw++;
  184.     return ((spte->pg_pfnum << PGSHIFT) + o);
  185.  
  186. copy:
  187.     vb->vb_copy = 1;
  188.     if (bp->b_bcount > vb->vb_bufsize)
  189.         panic("vba xfer too large");
  190.     if (vb->vb_iskernel) {
  191.         if ((bp->b_flags & B_READ) == 0)
  192.             bcopy(bp->b_un.b_addr, vb->vb_rawbuf,
  193.                 (unsigned)bp->b_bcount);
  194.         vbastat.k_copy++;
  195.     } else  {
  196.         dpte = vb->vb_map;
  197.         for (i = npf, p = (int)vb->vb_utl; i--; p += NBPG) {
  198.             *(int *)dpte++ = (spte++)->pg_pfnum |
  199.                 PG_V | PG_KW | PG_N;
  200.             mtpr(TBIS, p);
  201.         }
  202.         if ((bp->b_flags & B_READ) == 0)
  203.             bcopy(vb->vb_utl + o, vb->vb_rawbuf,
  204.                 (unsigned)bp->b_bcount);
  205.         vbastat.u_copy++;
  206.     }
  207.     return (vb->vb_physbuf);
  208. }
  209.  
  210. /*
  211.  * Called by the driver's interrupt routine, after DMA is completed.
  212.  * If the operation was a read, copy data to final buffer if necessary
  213.  * or invalidate data cache for cacheable direct buffers.
  214.  * Similar to the vbastart routine, but in the reverse direction.
  215.  */
  216. vbadone(bp, vb)
  217.     register struct buf *bp;
  218.     register struct vb_buf *vb;
  219. {
  220.     register npf;
  221.     register caddr_t v;
  222.     int o;
  223.  
  224.     if (bp->b_flags & B_READ) {
  225.         o = (int)bp->b_un.b_addr & PGOFSET;
  226.         if (vb->vb_copy) {
  227.             if (vb->vb_iskernel)
  228.                 bcopy(vb->vb_rawbuf, bp->b_un.b_addr,
  229.                     (unsigned)(bp->b_bcount - bp->b_resid));
  230.             else {
  231.                 bcopy(vb->vb_rawbuf, vb->vb_utl + o,
  232.                     (unsigned)(bp->b_bcount - bp->b_resid));
  233.                 dkeyinval(bp->b_proc);
  234.             }
  235.         } else {
  236.             if (vb->vb_iskernel) {
  237.                 npf = btoc(bp->b_bcount + o);
  238.                 for (v = bp->b_un.b_addr; npf--; v += NBPG)
  239.                     mtpr(P1DC, (int)v);
  240.             } else
  241.                 dkeyinval(bp->b_proc);
  242.         }
  243.     }
  244. }
  245.  
  246. /*
  247.  * Set up a scatter-gather operation for SMD/E controller.
  248.  * This code belongs half-way between {hd,vd}.c and this file.
  249.  */
  250.  
  251. #include "dk.h"
  252. #if NVD > 0
  253. #include "vdreg.h"
  254.  
  255. vd_sgsetup(bp, vb, sg)
  256.     register struct buf *bp;
  257.     struct vb_buf *vb;
  258.     struct trsg *sg;
  259. {
  260.     register struct pte *spte;
  261.     register struct addr_chain *adr;
  262.     register int i;
  263.     int o;
  264.  
  265.     vb->vb_iskernel = (((int)bp->b_un.b_addr & KERNBASE) == KERNBASE);
  266.     vb->vb_copy = 0;
  267.     if (vb->vb_iskernel) {
  268.         spte = kvtopte(bp->b_un.b_addr);
  269.         vbastat.k_sg++;
  270.     } else {
  271.         spte = vtopte((bp->b_flags&B_DIRTY) ? &proc[2] : bp->b_proc,
  272.             btop(bp->b_un.b_addr));
  273.         vbastat.u_sg++;
  274.     }
  275.  
  276.     o = (int)bp->b_un.b_addr & PGOFSET;
  277.     i = min(NBPG - o, bp->b_bcount);
  278.     sg->start_addr.wcount = i >> 1;
  279.     sg->start_addr.memadr = ((spte++)->pg_pfnum << PGSHIFT) + o;
  280.     i = bp->b_bcount - i;
  281.     if (i > VDMAXPAGES * NBPG)
  282.         panic("vba xfer too large");
  283.     i = i >> 1;
  284.     for (adr = sg->addr_chain; i > 0; adr++, i -= NBPG / 2) {
  285.         adr->nxt_addr = (spte++)->pg_pfnum << PGSHIFT;
  286.         adr->nxt_len = imin(i, NBPG / 2);
  287.     }
  288.     adr->nxt_addr = 0;
  289.     adr++->nxt_len = 0;
  290.     return ((adr - sg->addr_chain) * sizeof(*adr) / sizeof(long));
  291. }
  292. #endif
  293.  
  294. #include "hd.h"
  295. #if NHD > 0
  296. #include "hdreg.h"
  297.  
  298. hd_sgsetup(bp, vb, sg)
  299.     register struct buf *bp;
  300.     struct vb_buf *vb;
  301.     struct chain *sg;
  302. {
  303.     register struct pte *spte;
  304.     register struct addr_chain *adr;
  305.     register int i, cnt;
  306.     int o;
  307.  
  308.     if (bp->b_bcount > HDC_MAXBC ||
  309.         bp->b_bcount % sizeof(long) - 1 ||
  310.         (u_int)bp->b_un.b_addr % sizeof(long) - 1)
  311.         return(0);
  312.  
  313.     vb->vb_iskernel = (((int)bp->b_un.b_addr & KERNBASE) == KERNBASE);
  314.     vb->vb_copy = 0;
  315.     if (vb->vb_iskernel) {
  316.         spte = kvtopte(bp->b_un.b_addr);
  317.         vbastat.k_sg++;
  318.     } else {
  319.         spte = vtopte((bp->b_flags&B_DIRTY) ? &proc[2] : bp->b_proc,
  320.             btop(bp->b_un.b_addr));
  321.         vbastat.u_sg++;
  322.     }
  323.  
  324.     o = (int)bp->b_un.b_addr & PGOFSET;
  325.     i = min(NBPG - o, bp->b_bcount);
  326.     sg->wcount = i >> 2;
  327.     sg->memadr = ((spte++)->pg_pfnum << PGSHIFT) + o;
  328.     cnt = 0;
  329.     for (i = (bp->b_bcount - i) >> 2; i > 0; i -= NBPG / sizeof(long)) {
  330.         if (++cnt == HDC_MAXCHAIN)
  331.             return(0);
  332.         sg->wcount |= LWC_DATA_CHAIN;
  333.         ++sg;
  334.         sg->wcount = imin(i, NBPG / sizeof(long));
  335.         sg->memadr = (spte++)->pg_pfnum << PGSHIFT;
  336.     }
  337.     return(1);
  338. }
  339. #endif
  340.