Main Page Data Structures File List Data Fields Globals Related Pages

# amd186.cpp

Go to the documentation of this file.

    00001 /*  amd186.cpp
    00002     Low-level AMD186ED functions
    00003
    00004     18.06.2001: tk, assembly implementations for all PIO functions.
    00005     12.04.2000: tk, initial implementation.
    00006
    00007     Copyright (c)2000 by Thomas Kindler, thomas.kindler@gmx.de
    00008
    00009     This program is free software; you can redistribute it and/or
    00010     modify it under the terms of the GNU General Public License as
    00011     published by the Free Software Foundation; either version 2 of
    00012     the License, or (at your option) any later version. Read the
    00013     full License at http://www.gnu.org/copyleft for more details.
    00014 */
    00015
    00016 // include files -----
    00017 //
    00018 #include <iostream>
    00019 #include <dos.h>
    00020 #include <stdio.h>
    00021 #include "clib/hwapi.h"
    00022 #include "amd186.h"
    00023
    00024
    00032 void REP_INSB( int port, void *dest, int numBytes )
    00033 {
    00034   asm  {
    00035     pushf
    00036     push cx
    00037     push dx
    00038     push di
    00039     push es
    00040     cld
    00041
    00042     mov  cx, numBytes
    00043     mov  dx, port
    00044     les  di, dword ptr [dest]
    00045     rep  insb
    00046
    00047     pop  es
    00048     pop  di
    00049     pop  dx
    00050     pop  cx
    00051     popf
    00052   }
    00053 }
    00054
    00055
    00063 void REP_INSW( int port, void *dest, int numWords )
    00064 {
    00065   asm  {
    00066     pushf
    00067     push cx
    00068     push dx
    00069     push di
    00070     push es
    00071     cld
    00072
    00073     mov  cx, numWords
    00074     mov  dx, port
    00075     les  di, dword ptr[dest]
    00076     rep  insw
    00077
    00078     pop  es
    00079     pop  di
    00080     pop  dx
    00081     pop  cx
    00082     popf
    00083   }
    00084 }
    00085
    00086
    00094 void REP_OUTSB( int port, void *src, int numBytes )
    00095 {
    00096   asm  {
    00097     pushf
    00098     push cx
    00099     push dx
    00100     push di
    00101     push ds
    00102     cld
    00103
    00104     mov  cx, numBytes
    00105     mov  dx, port
    00106     lds  si, dword ptr [src]
    00107     rep  outsb
    00108
    00109     pop  ds
    00110     pop  di
    00111     pop  dx
    00112     pop  cx
    00113     popf
    00114   }
    00115 }
    00116
    00117
    00125 void REP_OUTSW( int port, void *src, int numWords )
    00126 {
    00127   asm  {
    00128     pushf
    00129     push cx
    00130     push dx
    00131     push di
    00132     push ds
    00133     cld
    00134
    00135     mov  cx, numWords
    00136     mov  dx, port
    00137     lds  si, dword ptr [src]
    00138     rep  outsw
    00139
    00140     pop  ds
    00141     pop  di
    00142     pop  dx
    00143     pop  cx
    00144     popf
    00145   }
    00146 }
    00147
    00148
    00159 void usleep(unsigned us)
    00160 {
    00161   asm {
    00162       push  cx
    00163       mov   cx, us
    00164     l1:
    00165       nop
    00166       nop
    00167       loop  l1
    00168       pop   cx
    00169   }
    00170 }
    00171
    00172
    00182 void AMD_TestPios()
    00183 {
    00184   for (int i=0; i<=13; i++) {
    00185     pfe_enable_pio(1<<i, PIO_O0);
    00186     unsigned long a = AMD_GetPioDir();
    00187     if (i == 13)
    00188       pfe_enable_pio(1<<i, PIO_IPD);
    00189     else
    00190       pfe_enable_pio(1<<i, PIO_IPU);
    00191     unsigned long b = AMD_GetPioDir();
    00192
    00193     int j;
    00194     for (j=0; j<32; j++)
    00195       if ((a^b) & (1<<j)) break;
    00196
    00197     printf( "%d -> %d, 0x%08lxL\n", i, j, a^b);
    00198   }
    00199 }
    00200
    00201
    00212 void AMD_SetPioData(unsigned long mask, unsigned long data)
    00213 {
    00214   asm {
    00215     push  ax
    00216     push  bx
    00217     push  cx
    00218     push  dx
    00219
    00220     mov   dx, PCB_PDATA0
    00221     mov   bx, word ptr data
    00222     mov   cx, word ptr mask
    00223     and   bx, cx
    00224     not   cx
    00225     in    ax, dx
    00226     and   ax, cx
    00227     or    ax, bx
    00228     out   dx, ax
    00229
    00230     mov   dx, PCB_PDATA1
    00231     mov   bx, word ptr data+2
    00232     mov   cx, word ptr mask+2
    00233     and   bx, cx
    00234     not   cx
    00235     in    ax, dx
    00236     and   ax, cx
    00237     or    ax, bx
    00238     out   dx, ax
    00239
    00240     pop   dx
    00241     pop   cx
    00242     pop   bx
    00243     pop   ax
    00244   }
    00245 }
    00246
    00247
    00258 void AMD_SetPioDir(unsigned long mask, unsigned long dir)
    00259 {
    00260   asm {
    00261     push  ax
    00262     push  bx
    00263     push  cx
    00264     push  dx
    00265
    00266     mov   dx, PCB_PDIR0
    00267     mov   bx, word ptr dir
    00268     mov   cx, word ptr mask
    00269     and   bx, cx
    00270     not   cx
    00271     in    ax, dx
    00272     and   ax, cx
    00273     or    ax, bx
    00274     out   dx, ax
    00275
    00276     mov   dx, PCB_PDIR1
    00277     mov   bx, word ptr dir+2
    00278     mov   cx, word ptr mask+2
    00279     and   bx, cx
    00280     not   cx
    00281     in    ax, dx
    00282     and   ax, cx
    00283     or    ax, bx
    00284     out   dx, ax
    00285
    00286     pop   dx
    00287     pop   cx
    00288     pop   bx
    00289     pop   ax
    00290   }
    00291 }
    00292
    00293
    00304 void AMD_SetPioMode(unsigned long mask, unsigned long mode)
    00305 {
    00306   asm {
    00307     push  ax
    00308     push  bx
    00309     push  cx
    00310     push  dx
    00311
    00312     mov   dx, PCB_PIOMODE0
    00313     mov   bx, word ptr mode
    00314     mov   cx, word ptr mask
    00315     and   bx, cx
    00316     not   cx
    00317     in    ax, dx
    00318     and   ax, cx
    00319     or    ax, bx
    00320     out   dx, ax
    00321
    00322     mov   dx, PCB_PIOMODE1
    00323     mov   bx, word ptr mode+2
    00324     mov   cx, word ptr mask+2
    00325     and   bx, cx
    00326     not   cx
    00327     in    ax, dx
    00328     and   ax, cx
    00329     or    ax, bx
    00330     out   dx, ax
    00331
    00332     pop   dx
    00333     pop   cx
    00334     pop   bx
    00335     pop   ax
    00336   }
    00337 }
    00338
    00339
    00350 void AMD_SetPcsWaitStates(int waitstates)
    00351 {
    00352   const int pacsBits[] = {
    00353      0,  1,  2,  3,  8,  8,  9,  9,
    00354     10, 10, 11, 11, 11, 11, 11, 11
    00355   };
    00356
    00357   if (waitstates > 15)  waitstates = 15;
    00358   if (waitstates <  0)  waitstates =  0;
    00359
    00360   outpw(PCB_PACS, (inpw(PCB_PACS) & 0xfff4) | pacsBits[waitstates]);
    00361 }
    00362
    00363
    00372 void  AMD_StartDma(int channel, DmaInfo *dma)
    00373 {
    00374   unsigned long src, dst;
    00375   if (dma->control & DCON_SMIO)
    00376     src = FP_SEG(dma->srcMem)*16L + FP_OFF(dma->srcMem);
    00377   else
    00378     src = dma->srcPort;
    00379
    00380   if (dma->control & DCON_DMIO)
    00381     dst = FP_SEG(dma->dstMem)*16L + FP_OFF(dma->dstMem);
    00382   else
    00383     dst = dma->dstPort;
    00384
    00385   // stop previous transfer first
    00386   //
    00387   outpw(channel ? PCB_D1CON  : PCB_D0CON,  DCON_STOP);
    00388
    00389   outpw(channel ? PCB_D1SRCL : PCB_D0SRCL, (unsigned)src);
    00390   outpw(channel ? PCB_D1SRCH : PCB_D0SRCH, (unsigned)(src>>16));
    00391   outpw(channel ? PCB_D1DSTL : PCB_D0DSTL, (unsigned)dst);
    00392   outpw(channel ? PCB_D1DSTH : PCB_D0DSTH, (unsigned)(dst>>16));
    00393   outpw(channel ? PCB_D1TC   : PCB_D0TC,   dma->length);
    00394   outpw(channel ? PCB_D1CON  : PCB_D0CON,  dma->control | DCON_START);
    00395 }
    00396
    00397
    00403 void AMD_StopDma(int channel)
    00404 {
    00405   unsigned control;
    00406
    00407   control = inpw(channel ? PCB_D1CON : PCB_D0CON);
    00408   control = (control & ~DCON_START) | DCON_STOP;
    00409   outpw(channel ? PCB_D1CON : PCB_D0CON,  control);
    00410 }
    00411
    00412
    00424 void AMD_GetDmaInfo(int channel, DmaInfo *dma)
    00425 {
    00426   // Stop DMA channel first..
    00427   //
    00428   dma->control = inpw(channel ? PCB_D1CON : PCB_D0CON);
    00429   outpw(channel ? PCB_D1CON : PCB_D0CON,
    00430         (dma->control & ~DCON_START) | DCON_STOP);
    00431
    00432   unsigned  sh, sl, dh, dl;
    00433   sh = inpw(channel ? PCB_D1SRCH : PCB_D0SRCH);
    00434   sl = inpw(channel ? PCB_D1SRCL : PCB_D0SRCL);
    00435   dh = inpw(channel ? PCB_D1SRCH : PCB_D0SRCH);
    00436   dl = inpw(channel ? PCB_D1DSTL : PCB_D0DSTL);
    00437   dma->length  = inpw(channel ? PCB_D1TC  : PCB_D0TC);
    00438
    00439   if (dma->control & DCON_SMIO)
    00440     dma->srcMem = MK_FP(sh << 12, sl);
    00441   else
    00442     dma->srcPort = sl;
    00443
    00444   if (dma->control & DCON_DMIO)
    00445     dma->dstMem = MK_FP(dh << 12, dl);
    00446   else
    00447     dma->dstPort = dl;
    00448
    00449   // Restart DMA channel
    00450   //
    00451   if (dma->control & DCON_ST)
    00452     outpw(channel ? PCB_D1CON : PCB_D0CON, dma->control | DCON_START);
    00453 }
    00454
    00455
    00456 /*
    00457  * Enable/Disable DMA request pin.
    00458  * This function switches the DRQ pin between normal
    00459  * operation and PIO input with pullup.
    00460  *
    00461  * \param channel DMA channel, either 0 or 1
    00462  * \param onoff   enable/disable DRQ
    00463  */
    00464 void AMD_EnableDrq(int channel, int onoff)
    00465 {
    00466   int pio = channel ? 13 : 12;
    00467   if (onoff) {
    00468     // mode 0, dir 0 - normal operation
    00469     AMD_SetPioMode(1<<pio, 0);
    00470     AMD_SetPioDir (1<<pio, 0);
    00471   } else {
    00472     // mode 0, dir 1 - input with pullup
    00473     AMD_SetPioDir (1<<pio, 1<<pio);
    00474     AMD_SetPioMode(1<<pio, 0);
    00475   }
    00476 }
    00477