Annotation of lucent/sys/src/9/pc/dma.c, revision 1.1

1.1     ! root        1: #include       "u.h"
        !             2: #include       "../port/lib.h"
        !             3: #include       "mem.h"
        !             4: #include       "dat.h"
        !             5: #include       "fns.h"
        !             6: 
        !             7: /*
        !             8:  *  headland chip set for the safari.
        !             9:  */
        !            10: typedef struct DMAport DMAport;
        !            11: typedef struct DMA     DMA;
        !            12: typedef struct DMAxfer DMAxfer;
        !            13: 
        !            14: enum
        !            15: {
        !            16:        /*
        !            17:         *  the byte registers for DMA0 are all one byte apart
        !            18:         */
        !            19:        Dma0=           0x00,
        !            20:        Dma0status=     Dma0+0x8,       /* status port */
        !            21:        Dma0reset=      Dma0+0xD,       /* reset port */
        !            22: 
        !            23:        /*
        !            24:         *  the byte registers for DMA1 are all two bytes apart (why?)
        !            25:         */
        !            26:        Dma1=           0xC0,
        !            27:        Dma1status=     Dma1+2*0x8,     /* status port */
        !            28:        Dma1reset=      Dma1+2*0xD,     /* reset port */
        !            29: };
        !            30: 
        !            31: /*
        !            32:  *  state of a dma transfer
        !            33:  */
        !            34: struct DMAxfer
        !            35: {
        !            36:        Page    pg;             /* page used by dma */
        !            37:        void    *va;            /* virtual address destination/src */
        !            38:        long    len;            /* bytes to be transferred */
        !            39:        int     isread;
        !            40: };
        !            41: 
        !            42: /*
        !            43:  *  the dma controllers.  the first half of this structure specifies
        !            44:  *  the I/O ports used by the DMA controllers.
        !            45:  */
        !            46: struct DMAport
        !            47: {
        !            48:        uchar   addr[4];        /* current address (4 channels) */
        !            49:        uchar   count[4];       /* current count (4 channels) */
        !            50:        uchar   page[4];        /* page registers (4 channels) */
        !            51:        uchar   cmd;            /* command status register */
        !            52:        uchar   req;            /* request registers */
        !            53:        uchar   sbm;            /* single bit mask register */
        !            54:        uchar   mode;           /* mode register */
        !            55:        uchar   cbp;            /* clear byte pointer */
        !            56:        uchar   mc;             /* master clear */
        !            57:        uchar   cmask;          /* clear mask register */
        !            58:        uchar   wam;            /* write all mask register bit */
        !            59: };
        !            60: 
        !            61: struct DMA
        !            62: {
        !            63:        DMAport;
        !            64:        int     shift;
        !            65:        Lock;
        !            66:        DMAxfer x[4];
        !            67: };
        !            68: 
        !            69: DMA dma[2] = {
        !            70:        { 0x00, 0x02, 0x04, 0x06,
        !            71:          0x01, 0x03, 0x05, 0x07,
        !            72:          0x87, 0x83, 0x81, 0x82,
        !            73:          0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        !            74:         0 },
        !            75: 
        !            76:        { 0xc0, 0xc4, 0xc8, 0xcc,
        !            77:          0xc2, 0xc6, 0xca, 0xce,
        !            78:          0x8f, 0x8b, 0x89, 0x8a,
        !            79:          0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
        !            80:         1 },
        !            81: };
        !            82: 
        !            83: /*
        !            84:  *  DMA must be in the first 16 meg.  This gets called early by main() to
        !            85:  *  ensure that.
        !            86:  */
        !            87: void
        !            88: dmainit(void)
        !            89: {
        !            90:        int i, chan;
        !            91:        DMA *dp;
        !            92:        DMAxfer *xp;
        !            93: 
        !            94:        for(i = 0; i < 2; i++){
        !            95:                dp = &dma[i];
        !            96:                for(chan = 0; chan < 4; chan++){
        !            97:                        xp = &dp->x[chan];
        !            98:                        xp->pg.pa = (ulong)xspanalloc(BY2PG, BY2PG, 0);
        !            99:                        xp->pg.va = KZERO|xp->pg.pa;
        !           100:                        xp->len = 0;
        !           101:                        xp->isread = 0;
        !           102:                }
        !           103:        }
        !           104: }
        !           105: 
        !           106: /*
        !           107:  *  setup a dma transfer.  if the destination is not in kernel
        !           108:  *  memory, allocate a page for the transfer.
        !           109:  *
        !           110:  *  we assume BIOS has set up the command register before we
        !           111:  *  are booted.
        !           112:  *
        !           113:  *  return the updated transfer length (we can't transfer across 64k
        !           114:  *  boundaries)
        !           115:  */
        !           116: long
        !           117: dmasetup(int chan, void *va, long len, int isread)
        !           118: {
        !           119:        DMA *dp;
        !           120:        DMAxfer *xp;
        !           121:        ulong pa;
        !           122:        uchar mode;
        !           123: 
        !           124:        dp = &dma[(chan>>2)&1];
        !           125:        chan = chan & 3;
        !           126:        xp = &dp->x[chan];
        !           127: 
        !           128:        /*
        !           129:         *  if this isn't kernel memory or crossing 64k boundary or above 16 meg
        !           130:         *  use the allocated low memory page.
        !           131:         */
        !           132:        pa = PADDR(va);
        !           133:        if((((ulong)va)&0xF0000000) != KZERO
        !           134:        || (pa&0xFFFF0000) != ((pa+len)&0xFFFF0000)
        !           135:        || pa > 16*MB){
        !           136:                if(len > BY2PG)
        !           137:                        len = BY2PG;
        !           138:                if(!isread)
        !           139:                        memmove((void*)(xp->pg.va), va, len);
        !           140:                xp->va = va;
        !           141:                xp->len = len;
        !           142:                xp->isread = isread;
        !           143:                pa = xp->pg.pa;
        !           144:        } else
        !           145:                xp->len = 0;
        !           146: 
        !           147:        /*
        !           148:         * this setup must be atomic
        !           149:         */
        !           150:        ilock(dp);
        !           151:        mode = (isread ? 0x44 : 0x48) | chan;
        !           152:        outb(dp->mode, mode);           /* single mode dma (give CPU a chance at mem) */
        !           153:        outb(dp->page[chan], pa>>16);
        !           154:        outb(dp->cbp, 0);               /* set count & address to their first byte */
        !           155:        outb(dp->addr[chan], pa>>dp->shift);            /* set address */
        !           156:        outb(dp->addr[chan], pa>>(8+dp->shift));
        !           157:        outb(dp->count[chan], (len>>dp->shift)-1);              /* set count */
        !           158:        outb(dp->count[chan], ((len>>dp->shift)-1)>>8);
        !           159:        outb(dp->sbm, chan);            /* enable the channel */
        !           160:        iunlock(dp);
        !           161: 
        !           162:        return len;
        !           163: }
        !           164: 
        !           165: /*
        !           166:  *  this must be called after a dma has been completed.
        !           167:  *
        !           168:  *  if a page has been allocated for the dma,
        !           169:  *  copy the data into the actual destination
        !           170:  *  and free the page.
        !           171:  */
        !           172: void
        !           173: dmaend(int chan)
        !           174: {
        !           175:        DMA *dp;
        !           176:        DMAxfer *xp;
        !           177: 
        !           178:        dp = &dma[(chan>>2)&1];
        !           179:        chan = chan & 3;
        !           180: 
        !           181:        /*
        !           182:         *  disable the channel
        !           183:         */
        !           184:        ilock(dp);
        !           185:        outb(dp->sbm, 4|chan);
        !           186:        iunlock(dp);
        !           187: 
        !           188:        xp = &dp->x[chan];
        !           189:        if(xp->len == 0 || !xp->isread)
        !           190:                return;
        !           191: 
        !           192:        /*
        !           193:         *  copy out of temporary page
        !           194:         */
        !           195:        memmove(xp->va, (void*)(xp->pg.va), xp->len);
        !           196:        xp->len = 0;
        !           197: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.