Annotation of lucent/sys/src/9/pc/dma.c, revision 1.1.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.