linux/drivers/isdn/act2000/act2000_isa.c
<<
>>
Prefs
   1/* $Id: act2000_isa.c,v 1.11.6.3 2001/09/23 22:24:32 kai Exp $
   2 *
   3 * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
   4 *
   5 * Author       Fritz Elfert
   6 * Copyright    by Fritz Elfert      <fritz@isdn4linux.de>
   7 * 
   8 * This software may be used and distributed according to the terms
   9 * of the GNU General Public License, incorporated herein by reference.
  10 *
  11 * Thanks to Friedemann Baitinger and IBM Germany
  12 *
  13 */
  14
  15#include "act2000.h"
  16#include "act2000_isa.h"
  17#include "capi.h"
  18
  19/*
  20 * Reset Controller, then try to read the Card's signature.
  21 + Return:
  22 *   1 = Signature found.
  23 *   0 = Signature not found.
  24 */
  25static int
  26act2000_isa_reset(unsigned short portbase)
  27{
  28        unsigned char reg;
  29        int i;
  30        int found;
  31        int serial = 0;
  32
  33        found = 0;
  34        if ((reg = inb(portbase + ISA_COR)) != 0xff) {
  35                outb(reg | ISA_COR_RESET, portbase + ISA_COR);
  36                mdelay(10);
  37                outb(reg, portbase + ISA_COR);
  38                mdelay(10);
  39
  40                for (i = 0; i < 16; i++) {
  41                        if (inb(portbase + ISA_ISR) & ISA_ISR_SERIAL)
  42                                serial |= 0x10000;
  43                        serial >>= 1;
  44                }
  45                if (serial == ISA_SER_ID)
  46                        found++;
  47        }
  48        return found;
  49}
  50
  51int
  52act2000_isa_detect(unsigned short portbase)
  53{
  54        int ret = 0;
  55
  56        if (request_region(portbase, ACT2000_PORTLEN, "act2000isa")) {
  57                ret = act2000_isa_reset(portbase);
  58                release_region(portbase, ISA_REGION);
  59        }
  60        return ret;
  61}
  62
  63static irqreturn_t
  64act2000_isa_interrupt(int dummy, void *dev_id)
  65{
  66        act2000_card *card = dev_id;
  67        u_char istatus;
  68
  69        istatus = (inb(ISA_PORT_ISR) & 0x07);
  70        if (istatus & ISA_ISR_OUT) {
  71                /* RX fifo has data */
  72                istatus &= ISA_ISR_OUT_MASK;
  73                outb(0, ISA_PORT_SIS);
  74                act2000_isa_receive(card);
  75                outb(ISA_SIS_INT, ISA_PORT_SIS);
  76        }
  77        if (istatus & ISA_ISR_ERR) {
  78                /* Error Interrupt */
  79                istatus &= ISA_ISR_ERR_MASK;
  80                printk(KERN_WARNING "act2000: errIRQ\n");
  81        }
  82        if (istatus)
  83                printk(KERN_DEBUG "act2000: ?IRQ %d %02x\n", card->irq, istatus);
  84        return IRQ_HANDLED;
  85}
  86
  87static void
  88act2000_isa_select_irq(act2000_card * card)
  89{
  90        unsigned char reg;
  91
  92        reg = (inb(ISA_PORT_COR) & ~ISA_COR_IRQOFF) | ISA_COR_PERR;
  93        switch (card->irq) {
  94                case 3:
  95                        reg = ISA_COR_IRQ03;
  96                        break;
  97                case 5:
  98                        reg = ISA_COR_IRQ05;
  99                        break;
 100                case 7:
 101                        reg = ISA_COR_IRQ07;
 102                        break;
 103                case 10:
 104                        reg = ISA_COR_IRQ10;
 105                        break;
 106                case 11:
 107                        reg = ISA_COR_IRQ11;
 108                        break;
 109                case 12:
 110                        reg = ISA_COR_IRQ12;
 111                        break;
 112                case 15:
 113                        reg = ISA_COR_IRQ15;
 114                        break;
 115        }
 116        outb(reg, ISA_PORT_COR);
 117}
 118
 119static void
 120act2000_isa_enable_irq(act2000_card * card)
 121{
 122        act2000_isa_select_irq(card);
 123        /* Enable READ irq */
 124        outb(ISA_SIS_INT, ISA_PORT_SIS);
 125}
 126
 127/*
 128 * Install interrupt handler, enable irq on card.
 129 * If irq is -1, choose next free irq, else irq is given explicitly.
 130 */
 131int
 132act2000_isa_config_irq(act2000_card * card, short irq)
 133{
 134        int old_irq;
 135
 136        if (card->flags & ACT2000_FLAGS_IVALID) {
 137                free_irq(card->irq, card);
 138        }
 139        card->flags &= ~ACT2000_FLAGS_IVALID;
 140        outb(ISA_COR_IRQOFF, ISA_PORT_COR);
 141        if (!irq)
 142                return 0;
 143
 144        old_irq = card->irq;
 145        card->irq = irq;
 146        if (request_irq(irq, &act2000_isa_interrupt, 0, card->regname, card)) {
 147                card->irq = old_irq;
 148                card->flags |= ACT2000_FLAGS_IVALID;
 149                printk(KERN_WARNING
 150                       "act2000: Could not request irq %d\n",irq);
 151                return -EBUSY;
 152        } else {
 153                act2000_isa_select_irq(card);
 154                /* Disable READ and WRITE irq */
 155                outb(0, ISA_PORT_SIS);
 156                outb(0, ISA_PORT_SOS);
 157        }
 158        return 0;
 159}
 160
 161int
 162act2000_isa_config_port(act2000_card * card, unsigned short portbase)
 163{
 164        if (card->flags & ACT2000_FLAGS_PVALID) {
 165                release_region(card->port, ISA_REGION);
 166                card->flags &= ~ACT2000_FLAGS_PVALID;
 167        }
 168        if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL)
 169                return -EBUSY;
 170        else {
 171                card->port = portbase;
 172                card->flags |= ACT2000_FLAGS_PVALID;
 173                return 0;
 174        }
 175}
 176
 177/*
 178 * Release ressources, used by an adaptor.
 179 */
 180void
 181act2000_isa_release(act2000_card * card)
 182{
 183        unsigned long flags;
 184
 185        spin_lock_irqsave(&card->lock, flags);
 186        if (card->flags & ACT2000_FLAGS_IVALID)
 187                free_irq(card->irq, card);
 188
 189        card->flags &= ~ACT2000_FLAGS_IVALID;
 190        if (card->flags & ACT2000_FLAGS_PVALID)
 191                release_region(card->port, ISA_REGION);
 192        card->flags &= ~ACT2000_FLAGS_PVALID;
 193        spin_unlock_irqrestore(&card->lock, flags);
 194}
 195
 196static int
 197act2000_isa_writeb(act2000_card * card, u_char data)
 198{
 199        u_char timeout = 40;
 200
 201        while (timeout) {
 202                if (inb(ISA_PORT_SOS) & ISA_SOS_READY) {
 203                        outb(data, ISA_PORT_SDO);
 204                        return 0;
 205                } else {
 206                        timeout--;
 207                        udelay(10);
 208                }
 209        }
 210        return 1;
 211}
 212
 213static int
 214act2000_isa_readb(act2000_card * card, u_char * data)
 215{
 216        u_char timeout = 40;
 217
 218        while (timeout) {
 219                if (inb(ISA_PORT_SIS) & ISA_SIS_READY) {
 220                        *data = inb(ISA_PORT_SDI);
 221                        return 0;
 222                } else {
 223                        timeout--;
 224                        udelay(10);
 225                }
 226        }
 227        return 1;
 228}
 229
 230void
 231act2000_isa_receive(act2000_card *card)
 232{
 233        u_char c;
 234
 235        if (test_and_set_bit(ACT2000_LOCK_RX, (void *) &card->ilock) != 0)
 236                return;
 237        while (!act2000_isa_readb(card, &c)) {
 238                if (card->idat.isa.rcvidx < 8) {
 239                        card->idat.isa.rcvhdr[card->idat.isa.rcvidx++] = c;
 240                        if (card->idat.isa.rcvidx == 8) {
 241                                int valid = actcapi_chkhdr(card, (actcapi_msghdr *)&card->idat.isa.rcvhdr);
 242
 243                                if (valid) {
 244                                        card->idat.isa.rcvlen = ((actcapi_msghdr *)&card->idat.isa.rcvhdr)->len;
 245                                        card->idat.isa.rcvskb = dev_alloc_skb(card->idat.isa.rcvlen);
 246                                        if (card->idat.isa.rcvskb == NULL) {
 247                                                card->idat.isa.rcvignore = 1;
 248                                                printk(KERN_WARNING
 249                                                       "act2000_isa_receive: no memory\n");
 250                                                test_and_clear_bit(ACT2000_LOCK_RX, (void *) &card->ilock);
 251                                                return;
 252                                        }
 253                                        memcpy(skb_put(card->idat.isa.rcvskb, 8), card->idat.isa.rcvhdr, 8);
 254                                        card->idat.isa.rcvptr = skb_put(card->idat.isa.rcvskb, card->idat.isa.rcvlen - 8);
 255                                } else {
 256                                        card->idat.isa.rcvidx = 0;
 257                                        printk(KERN_WARNING
 258                                               "act2000_isa_receive: Invalid CAPI msg\n");
 259                                        {
 260                                                int i; __u8 *p; __u8 *c; __u8 tmp[30];
 261                                                for (i = 0, p = (__u8 *)&card->idat.isa.rcvhdr, c = tmp; i < 8; i++)
 262                                                        c += sprintf(c, "%02x ", *(p++));
 263                                                printk(KERN_WARNING "act2000_isa_receive: %s\n", tmp);
 264                                        }
 265                                }
 266                        }
 267                } else {
 268                        if (!card->idat.isa.rcvignore)
 269                                *card->idat.isa.rcvptr++ = c;
 270                        if (++card->idat.isa.rcvidx >= card->idat.isa.rcvlen) {
 271                                if (!card->idat.isa.rcvignore) {
 272                                        skb_queue_tail(&card->rcvq, card->idat.isa.rcvskb);
 273                                        act2000_schedule_rx(card);
 274                                }
 275                                card->idat.isa.rcvidx = 0;
 276                                card->idat.isa.rcvlen = 8;
 277                                card->idat.isa.rcvignore = 0;
 278                                card->idat.isa.rcvskb = NULL;
 279                                card->idat.isa.rcvptr = card->idat.isa.rcvhdr;
 280                        }
 281                }
 282        }
 283        if (!(card->flags & ACT2000_FLAGS_IVALID)) {
 284                /* In polling mode, schedule myself */
 285                if ((card->idat.isa.rcvidx) &&
 286                    (card->idat.isa.rcvignore ||
 287                     (card->idat.isa.rcvidx < card->idat.isa.rcvlen)class="sref">isa.rcvl4en" class="sref">rcvl4en" class="sref"sref">rcvl4en" class="sre>idat.rcvignore">ISA_REG"dr="string76.>rcvlef">rcvdr="string76.>9g76.>rcvlef">r=isa" class="sref">isa.2190        if (test_and_clear_bit(ACT2000_LOCK_RX, (void *) &card->ilock);
219121922193     2194act2000_cardact2000_card * card)
21952196flags;
2197sprintk_bufa* skb_queu
rcvl4enlass="line" name="L198">2198act2000_msghdract20r9glass="line" name="L199">2199        3200
3201        whilea href="+code=test_and_set_bit" class="sref">test_and_set_bit(ACT2000_LOCK_RXcard->ilock) != 0)
3202                if (3203              (!3204                     ef="+code=skb_quock_irqsave" class="sref">spin_lock_irqsave(&card->lock, flags);
3205                } els(card->spin_lbuf) {
3206                        card->spin_lbuf) {
 href="+code=skb_put" de_tailss="sref">skb_queuede_tail&card->rcvq3207                        card->act2000kdrcard->spin_lbuf) {
data = 3208                }
act20ract2000_msghdrcard->spin_lbuf) {
data = 3209act20rrcvhda>;
cardcard3210act20rrcvhda>;
cardcard3211/* In poSa>( )ra  messagespan>
3212card->lockact20ract20r ed__rs="sref">act20r        }
 213s31                                     act20ract20r ed__rs="sref">act20r        }
 213<31                             }
 213{31                             f="drivers/isdn/act2000/act2000_isa.c#L275" id=3L206" 3lass="line" name="L216"> 213 31                     f="drivers/isdn/act2000/act2000_isa.c#L275" id=3L206" 3lass="line" name="L217"> 213
31             spin_unlock_irqrestore(&card->lock, flags);
 213 31             if (card->spin_lbuf) {
 213 3              if (/* In poSa>No m&am aef= to a
 223 3                      *test_and_clear_bit(ACT2000_LOCK_RXcard->ilock) != 0)
 223 3                      return 0;
 223 3              } else {
="drivers/isdn/act2000/act2000_isa.c#L194" id=3Lisdn7="L2s="line" name="L223"> 223 3                      "+code=skb_queuss="sref">skb_queu
card->spin_lbuf) {
 223 3                      "+code=i" cl="sale 3s/isdn/al*  223 3              }
skb_queu
len;
 223 32                     act2000_isa_writeb(card, (skb_queu
data)
 223 32                     /* In poSa>Fifo is full, but m&am aef= to a
 223}32             }
test_and_clear_bit(ACT2000_LOCK_RXcard->ilock) != 0)
 223
32                             /* In poSa>(myself */
 233v33                                     at.act2000_schedule_rx(card);
 233<33                                     ;
 233{33                             
="drivers/isdn/act2000/act2000_isa.c#L194" id=3L233" cla3s="line" name="L233"> 233 33                     ((skb_queu
 233
33                      233 33             }
 233 3              return;
"+code=skb_qract20ract2000_msghdrcard->act2000kdr 233 33                     href="+code=card"ract20rrcvhda>;
cardcard 233 3              if (act20rrcvhda>;
cardcard 233 3                      /* In poSa 243 3      "ss="comment">/* In po                 243 3      "ss="comment">/* In po                 243
3a href"ss="comment">/* In po                 243 3                              "+code=p" classss="sref">skb_queu
data)
card->act2000kdr 243 3                              "ss="comment">/* In poSa>Ra>(&ama>)ra  messagespan>
 243 3                              "+code=memcpy" cs="sref">act20ract20r ed__rs="sref">act20r        }
card->lock 243 3                              "+code=timeout"/a>(il" class="sref">skb_queue_tail(&card->act2000kdrskb_queu
 243 3                      
 243 3                              +code=rcvles/a> ev_kfreeass="sref">dev_alloc_skkfreeass=href="+code=card" clss="sref">skb_queu
 243 3                      "+code=card" class="sref">card->spin_lbuf) {
NULL;
 253 3              f="drivers/isdn/act2000/act2000_isa.c#L226" id=3L251" cla3s="line" name="L251"> 253 35a href="drivers/isdn/act2000/act2000_isa.c#L212" id=3L252" cla3s="line" name="L252"> 253 35 href="drivers/isdn/act2000/act2000_isa.c#L243" id=3L253" cla3s="line" name="L253"> 253 3      "ss="comment">/* In poSa 253 3      "ss="comment">/* In po * Get firmwaamaID, check href'ISDN' ong ature.a  href="drivers/isdn/act2000/act2000_isa.c#L285" id=3L255" cla3s="line" name="L255"> 253 3      "ss="comment">/* In po *
 253 3      statichref="drivers/isdn/act2000/act2000_isa.c#L285" 3d="L247" cla3s="line" name="L257"> 253 3      "+code=act2000_isa_readbsengets="sref">validact2000_card * card)
 253 3      f="drivers/isdn/act2000/act2000_isa.c#L284" 3d="L259" cla3s="line" name="L259"> 253 35 href="drivers/isdn/act2000/act2000_isa.c#L230" id=3L260" cla3s="line" name="L260"> 263 36     if (valid        }
valid 263 3              s/a>        }
u_char p; u_char valid 263 3              ref="+code=i" cl="scoun="sref">test_andcoun=ahre href="drivers/isdn/act2000/act2000_isa.c#L278" id=3L263" cla3s="line" name="L263"> 263 3      ="drivers/isdn/act2000/act2000_isa.c#L278" id=3L254" cla3s="line" name="L264"> 263 3               263 3                      ref="+code=card" claoun="sref">test_andcoun=ahre ref= 51ef="drivers/isdn/act2000/act2000_isa.c#L236" 3d="L266" cla3s="line" name="L266"> 263 3                      }
test_andEPROTO    f="drivers/isdn/act2000/act2000_isa.c#L279" id=3L247" cla3s="line" name="L267"> 263 3              } else {href"+code=act2000_isa_readbsenlass="sref">act2000_isa_readb(card, &p;  263 3                      if (!( 263 3                      "+code=card" claoun="sref">test_andcoun=ahre++f="drivers/isdn/act2000/act2000_isa.c#L274" id=3L270" cla3s="line" name="L270"> 273 37             f="drivers/isdn/act2000/act2000_isa.c#L226" id=3L271" cla3s="line" name="L271"> 273 37     whilea href="+code=test_andaoun="sref">test_andcoun=ahre rlref=20ref="drivers/isdn/act2000/act2000_isa.c#L284" 3d="L272" cla3s="line" name="L272"> 273 3                      "+code=p" class=lass="sref">printk(KERN_WARNING "act2000_isa_rec:>No Firmwaam-ID!);
 273 3                      ;
test_andETIME    f="drivers/isdn/act2000/act2000_isa.c#L279" id=3L274" cla3s="line" name="L274"> 273 3              f="drivers/isdn/act2000/act2000_isa.c#L226" id=3L265" cla3s="line" name="L275"> 273 3              ="+code=p" class="sref">p; "act#39;\0t#39;;
 273 3              "+code=ACT2000_as="sref">validrcvlen"act#39;\0t#39;;
 273 3              ref="+code=test_and&qucs="sref">tmp)&qucs=href="+code=KERN_WARas="sref">validilock000mp;"act2000_ISDN&pan>);
 273 3                      "+code=p" class=lass="sref">printk(KERN_WARNING "act2000_isa_rec:>Wrref=Firmwaam-ID!);
 273 3                      ;
test_andEPROTO    f="drivers/isdn/act2000/act2000_isa.c#L279" id=3L280" cla3s="line" name="L280"> 283 38             f="drivers/isdn/act2000/act2000_isa.c#L226" id=3L281" cla3s="line" name="L281"> 283 38     whilea href=="+code=p" class="sref">p++));
u_charvalidrcvlen"act#39;\nt#39;;
isa. 283 38                     ="+code=p" class="sref">p; "act#39;\0t#39;;
 283 3      if (!(printk(test_andNING"INFOan class="string">"act2000_isa_rec:>Firmwaam-ID\n", validrcvlen 283 3              ref="+code=card" class="sref">card->flags & ACT2000_FLAGS_IVALID)) {
 283 3              if ((printk(KERN_WARNING"act2000_Enabe, scInterrupts ...);
 283 3                  (act2000_isa_readbcard, & 283 3              f="drivers/isdn/act2000/act2000_isa.c#L226" id=3L258" cla3lass="sref">rcvl4en" cla3s="sr3f"sref">rcvl4e;
9g763>rcvlef">r=isa" class="s3ef">i3a.f="drivers/isdn/act2000/act2000_isa.c#L226" id=3L190" cla3s="line" name="L190">2193 39 href="drivers/isdn/act2000/act2000_isa.c#L201" 3d="L281" cla3s="line" name="L191">2193/* In poSa2193/* In po * Download microd" chrefo , &a, check Firmwaam ong ature.a  href="drivers/isdn/act2000/act2000_isa.c#L285" id=3L193" 2la3s="line" name="L193">2193 39     "ss="comment">/* In po *
21932193act2000_isa_readbact2000_card * card)
dde="sref">spin_lbucarddde=    is/a>        }
<__user"sref">spin_lbu__usera href="+code=card" cla="sref">act2000_cb href="drivers/isdn/act2000/act2000_isa.c#L182" 2d=3L196" 2la3s="line" name="L196">21932193act2000_aength    f="drivers/isdn/act2000/act2000_isa.c#L279" id=3rcvl4enla3s="line" name="L198">21939gla3s="line" name="L199">2193 3      c;
3204
40             href="+code=flags" ctimeos="sref">skb_put2194 40             s/a>        }
u_char act2000_a href="drivers/isdn/act2000/act2000_isa.c#L184" 2d"4L202" 3la4s="line" name="L202">3204 4              s/a>        }
u_char         }
<__user"sref">spin_lbu__usera href"+code=p" class="sref">p; 2194 40     if (!(u_char spin_lbu) {
3204 4              "+code=tmp" clacarddde="sref">spin_lbucarddde=    is/a>        }
ilock2194 4      ="drivers/isdn/act2000/act2000_isa.c#L194" id=4L604" 3la4s="line" name="L196">2194 4              href="+code=card" clisa_readb(se="sref">skb_put(se=href="+code=card" class="sref">card, &skb_put3204 4                      ;
test_andENXIO
2194 40     if (test_andmsleep_interruptibeehref=500ef="drivers/isdn/act2000/act2000_isa.c#L259" id=4L206" 3la4s="line" name="L199">3204spin_lbuaopy_from_userhref=href="+code=card" clabass="sref">ilockact2000_cb hre, onzeof="+code=test_andabass="sref">ilockisa.3214test_andEFAULT
3214        }
act2000_aength     hr"+code=skb_q clabass="sref">ilockact2000_aength    f="drivers/isdn/act2000/act2000_isa.c#L279" id=4L212" 3la4s="line" name="L212">3214        }
<="sref">p++));
ilockspin_lbua*  214s41     if (!(ilockACT2000_VERIFY_REA=mp;p; act2000_aength    ref">isa. 214<41                     ;
test_andEFAULT
 214{41             "+code=p" class=s="sref">spin_lbu) {
spin_lbukmalasshref=1024a "+code=p" classGFP_NINGE="sref">NULLGFP_NINGE=mp; 214 41             href="+code=card" cl=s="sref">spin_lbu) {
isa. 214
41             test_andENOMEM
 214 41     if (skb_put 214 4              a href="+code=timeout"aength"sref">act2000_aength    ref="drivers/isdn/act2000/act2000_isa.c#L284" 3d=4L220" cla4s="line" name="L220"> 224 4                      "+code=i" cl="sale 3s/isdn/al* act2000_aength     ref= 1024) ? 1024 :="+code=i" cl="saength"sref">act2000_aength    f="drivers/isdn/act2000/act2000_isa.c#L279" id=4L221" cla4s="line" name="L221"> 224 4                      "+code=i" cl="s="sref">c;
 224 4              } else {"+code=p" class="sref">act2000_a hreef="+code=skb_put"=s="sref">spin_lbu) {
 224 4                      ref="+code=test_andaopy_from_user"sref">spin_lbuaopy_from_userhref="+code=skb_put"=s="sref">spin_lbu) {
p;  224 4                      } else {"+code=p" classkfree"sref">spin_lbukfreehref="+code=skb_put"=s="sref">spin_lbu) {
 224 4              }
test_andEFAULT
 224 42                     f="drivers/isdn/act2000/act2000_isa.c#L226" id=4L227" cla4s="line" name="L227"> 224 42                     a href="+code=timeout"="sref">c;
 224}42             }
act2000_isa_writeb(card, (act2000_a hre hreef="drivers/isdn/act2000/act2000_isa.c#L284" 3d=4L219" cla4s="line" name="L229"> 224
42                             printk(KERN_WARNING  234v43                                     a href="ss="string">"act2000_isa_rec:>loader timed os=span>);
 234<43                                     a href="ss="string">"act2000_ aen="d c="d, act2000_aength    f="+code=card" cla"sref">c;
 234{43                             spin_lbukfreehref="+code=skb_put"=s="sref">spin_lbu) {
 234 43                     test_andETIME    f="drivers/isdn/act2000/act2000_isa.c#L279" id=4L214" cla4s="line" name="L234"> 234
43                      234 43             }
c;
 234 4              return;
f="drivers/isdn/act2000/act2000_isa.c#L226" id=4L227" cla4s="line" name="L237"> 234 43                     "+code=__u8"pi_aength"sref">act2000_aength     -f="+code=skb_put"ale 3s/isdn/al*  234 4              if (        }
<="sref">p++));
 234 43. 244 44     if (spin_lbukfreehref="+code=skb_put"=s="sref">spin_lbu) {
 244 44             s/a>        }
test_andmsleep_interruptibeehref=500ef="drivers/isdn/act2000/act2000_isa.c#L259" id=4L232" cla4s="line" name="L242"> 244
44             ;
validcard, & 244 4      "+cod3l        while ( 244 4      
The original LXR softwaam by the cod3lhttp://sourceforge.net/projects/lxr">LXR >/* unity f=this experi In al ion by cod3lmailto:lxr@me=ux.no* http://www.redpill-me=pro.no* Redpill Le=pro AS f=provider of Le=ux >/nsult, scr_b operations services since 1995.