Annotation of margi2/margi.c, revision 1.1

1.1     ! cvs         1: /* 
        !             2:     margi.c
        !             3: 
        !             4:     Copyright (C) Marcus Metzler for convergence integrated media.
        !             5: 
        !             6:     This program is free software; you can redistribute it and/or modify
        !             7:     it under the terms of the GNU General Public License as published by
        !             8:     the Free Software Foundation; either version 2 of the License, or
        !             9:     (at your option) any later version.
        !            10: 
        !            11:     This program is distributed in the hope that it will be useful,
        !            12:     but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14:     GNU General Public License for more details.
        !            15: 
        !            16:     You should have received a copy of the GNU General Public License
        !            17:     along with this program; if not, write to the Free Software
        !            18:     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            19: */
        !            20: 
        !            21: #include "margi.h"
        !            22: 
        !            23: #include <pcmcia/version.h>
        !            24: #include <pcmcia/cs_types.h>
        !            25: #include <pcmcia/cs.h>
        !            26: #include <pcmcia/cistpl.h>
        !            27: #include <pcmcia/cisreg.h>
        !            28: #include <pcmcia/bus_ops.h>
        !            29: #include <pcmcia/ds.h>
        !            30: 
        !            31: 
        !            32: 
        !            33: #include "l64014.h"
        !            34: #include "l64021.h"
        !            35: #include "i2c.h"
        !            36: #include "decoder.h"
        !            37: #include "dram.h"
        !            38: #include "video.h"
        !            39: #include "cvdv.h"
        !            40: 
        !            41: //#define USE_BH 1
        !            42: #ifdef USE_BH
        !            43: #define MARGI_BH 31
        !            44: // shouldn't be a number, but then MARGI_BH must be entered into interrupt.h
        !            45: #endif
        !            46: 
        !            47: MODULE_AUTHOR(AUTHOR);
        !            48: MODULE_DESCRIPTION(MEDDEVNAME " Driver V." DVERSION);
        !            49: 
        !            50: #ifdef PCMCIA_DEBUG
        !            51: static int pc_debug = PCMCIA_DEBUG;
        !            52: MODULE_PARM(pc_debug, "i");
        !            53: #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
        !            54: static char *version = "margi_cs.c 0.42 11/1/2000 (Marcus Metzler)";
        !            55: #else
        !            56: #define DEBUG(n, args...)
        !            57: #endif
        !            58: 
        !            59: #define MAX_DEV 4
        !            60: #define DEVICE_NR(minor)       ((minor)>>4)
        !            61: 
        !            62: /*====================================================================*/
        !            63: 
        !            64: /* Parameters that can be set with 'insmod' */
        !            65: 
        !            66: /* Release IO ports after configuration? */
        !            67: static int free_ports = 0;
        !            68: 
        !            69: /* The old way: bit map of interrupts to choose from */
        !            70: /* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
        !            71: static u_int irq_mask = 0xdeb8;
        !            72: /* Newer, simpler way of listing specific interrupts */
        !            73: static int irq_list[4] = { -1 };
        !            74: 
        !            75: MODULE_PARM(free_ports, "i");
        !            76: MODULE_PARM(irq_mask, "i");
        !            77: MODULE_PARM(irq_list, "1-4i");
        !            78: 
        !            79: extern unsigned int major_device_number;
        !            80: extern struct file_operations cvdv_fileops;
        !            81: 
        !            82: 
        !            83: typedef struct margi_info_t {
        !            84:        dev_link_t link;
        !            85:        dev_node_t node;
        !            86:        struct cvdv_cards card;
        !            87:        int stop;
        !            88: } margi_info_t;
        !            89: 
        !            90: 
        !            91: 
        !            92: /*
        !            93:    The event() function is this driver's Card Services event handler.
        !            94:    It will be called by Card Services when an appropriate card status
        !            95:    event is received.  The config() and release() entry points are
        !            96:    used to configure or release a socket, in response to card
        !            97:    insertion and ejection events.  They are invoked from the margi
        !            98:    event handler. 
        !            99: */
        !           100: 
        !           101: static void margi_config(dev_link_t * link);
        !           102: static void margi_release(u_long arg);
        !           103: static int margi_event(event_t event, int priority,
        !           104:                       event_callback_args_t * args);
        !           105: /*
        !           106:    The attach() and detach() entry points are used to create and destroy
        !           107:    "instances" of the driver, where each instance represents everything
        !           108:    needed to manage one actual PCMCIA card.
        !           109: */
        !           110: 
        !           111: static dev_link_t *margi_attach(void);
        !           112: static void margi_detach(dev_link_t *);
        !           113: static u_char read_lsi_status(struct cvdv_cards *card);
        !           114: 
        !           115: /*
        !           116:    You'll also need to prototype all the functions that will actually
        !           117:    be used to talk to your device.  See 'memory_cs' for a good example
        !           118:    of a fully self-sufficient driver; the other drivers rely more or
        !           119:    less on other parts of the kernel.
        !           120: */
        !           121: 
        !           122: /*
        !           123:    The dev_info variable is the "key" that is used to match up this
        !           124:    device driver with appropriate cards, through the card configuration
        !           125:    database.
        !           126: */
        !           127: 
        !           128: static dev_link_t *dev_table[MAX_DEV] = { NULL, /* ... */  };
        !           129: 
        !           130: static dev_info_t dev_info = "margi_cs";
        !           131: 
        !           132: /*
        !           133:    A linked list of "instances" of the margi device.  Each actual
        !           134:    PCMCIA card corresponds to one device instance, and is described
        !           135:    by one dev_link_t structure (defined in ds.h).
        !           136: 
        !           137:    You may not want to use a linked list for this -- for example, the
        !           138:    memory card driver uses an array of dev_link_t pointers, where minor
        !           139:    device numbers are used to derive the corresponding array index.
        !           140: */
        !           141: 
        !           142: static dev_link_t *dev_list = NULL;
        !           143: 
        !           144: /*
        !           145:    A dev_link_t structure has fields for most things that are needed
        !           146:    to keep track of a socket, but there will usually be some device
        !           147:    specific information that also needs to be kept track of.  The
        !           148:    'priv' pointer in a dev_link_t structure can be used to point to
        !           149:    a device-specific private data structure, like this.
        !           150: 
        !           151:    To simplify the data structure handling, we actually include the
        !           152:    dev_link_t structure in the device's private data structure.
        !           153: 
        !           154:    A driver needs to provide a dev_node_t structure for each device
        !           155:    on a card.  In some cases, there is only one device per card (for
        !           156:    example, ethernet cards, modems).  In other cases, there may be
        !           157:    many actual or logical devices (SCSI adapters, memory cards with
        !           158:    multiple partitions).  The dev_node_t structures need to be kept
        !           159:    in a linked list starting at the 'dev' field of a dev_link_t
        !           160:    structure.  We allocate them in the card's private data structure,
        !           161:    because they generally shouldn't be allocated dynamically.
        !           162: 
        !           163:    In this case, we also provide a flag to indicate if a device is
        !           164:    "stopped" due to a power management event, or card ejection.  The
        !           165:    device IO routines can use a flag like this to throttle IO to a
        !           166:    card that is not ready to accept it.
        !           167: 
        !           168:    The bus_operations pointer is used on platforms for which we need
        !           169:    to use special socket-specific versions of normal IO primitives
        !           170:    (inb, outb, readb, writeb, etc) for card IO.
        !           171: */
        !           172: 
        !           173: 
        !           174: void DACSetFrequency(struct cvdv_cards *card, int khz, int multiple) {
        !           175:        u8 b =  read_indexed_register(card, IIO_OSC_AUD);
        !           176: 
        !           177:        b &= 0xf8;
        !           178: 
        !           179:        switch (khz){
        !           180:        case 48:
        !           181:                b |= 0x00;
        !           182:                break;
        !           183:        case 44:
        !           184:                b |= 0x01;
        !           185:                break;
        !           186:        case 96:
        !           187:                b |= 0x02;
        !           188:                break;
        !           189:        default:
        !           190:                b |= 0x00;
        !           191:                break;
        !           192:        }
        !           193:        write_indexed_register(card, IIO_OSC_AUD, b);
        !           194: 
        !           195: }
        !           196: 
        !           197: int MargiFreeBuffers(struct cvdv_cards *card)
        !           198: {
        !           199:        printk(KERN_DEBUG LOGNAME ": -- MargiFreeBuffers\n");
        !           200:        
        !           201:        ring_destroy(&(card->rbuf));
        !           202:        card->use_ring = 0;
        !           203:        return 0;
        !           204: }
        !           205: 
        !           206: 
        !           207: int MargiSetBuffers(struct cvdv_cards *card, u32 size)
        !           208: {
        !           209:        MargiFreeBuffers(card);
        !           210:        printk(KERN_DEBUG LOGNAME ": -- MargiSetBuffers(%d)\n",
        !           211:               size);
        !           212: 
        !           213:        ring_init(&(card->rbuf),size);
        !           214:        card->use_ring = 1;
        !           215:        return 0;
        !           216: 
        !           217: }
        !           218: 
        !           219: int MargiFlush (struct cvdv_cards *card)
        !           220: {
        !           221:        int co = 0;
        !           222:        int i;
        !           223:        for (i=0;i<100;i++)
        !           224:                MargiPush(card, 32, FlushPacket);
        !           225:        while (ring_write_rest(&(card->rbuf))  && co<100) co++;
        !           226:        VideoSetBackground(card, 1, 0, 0, 0);   // black
        !           227: 
        !           228:        ring_flush(&(card->rbuf));
        !           229:        card->DMAABusy = 0;
        !           230: 
        !           231: 
        !           232:        DecoderStopChannel(card);
        !           233:        DecoderStreamReset(card);
        !           234:        DecoderSetupReset(card);
        !           235:        card->channelrun = 0;
        !           236: 
        !           237:        printk(KERN_DEBUG LOGNAME ": Margi Flush \n");
        !           238:        return 0;
        !           239: }
        !           240: 
        !           241: 
        !           242: 
        !           243: 
        !           244: void init_p2t(p2t_t *p)
        !           245: {
        !           246:        memset(p->pes,0,PBUFFER);
        !           247:        p->type = AUDIO;
        !           248:        p->pos = 0;
        !           249:        p->frags = 0;
        !           250: }
        !           251: 
        !           252: void clear_p2t(p2t_t *p)
        !           253: {
        !           254:        memset(p->pes,0,PBUFFER);
        !           255:        p->pos = 0;
        !           256:        p->frags = 0;
        !           257: }
        !           258: 
        !           259: 
        !           260: long int find_pes_header(u8 const *buf, long int length, int *frags)
        !           261: {
        !           262:        int c = 0;
        !           263:        int found = 0;
        !           264: 
        !           265:        *frags = 0;
        !           266: 
        !           267:        while (c < length-3 && !found) {
        !           268:                if (buf[c] == 0x00 && buf[c+1] == 0x00 && 
        !           269:                    buf[c+2] == 0x01) {
        !           270:                        switch ( buf[c+3] ) {
        !           271:                                
        !           272:                        case PROG_STREAM_MAP:
        !           273:                        case PRIVATE_STREAM2:
        !           274:                        case PROG_STREAM_DIR:
        !           275:                        case ECM_STREAM     :
        !           276:                        case EMM_STREAM     :
        !           277:                        case PADDING_STREAM :
        !           278:                        case DSM_CC_STREAM  :
        !           279:                        case ISO13522_STREAM:
        !           280:                        case PRIVATE_STREAM1:
        !           281:                        case AUDIO_STREAM_S ... AUDIO_STREAM_E:
        !           282:                        case VIDEO_STREAM_S ... VIDEO_STREAM_E:
        !           283:                                found = 1;
        !           284:                                break;
        !           285:                                
        !           286:                        default:
        !           287:                                c++;
        !           288:                                break;
        !           289:                        }       
        !           290:                } else c++;
        !           291:        }
        !           292:        if (c == length-3 && !found){
        !           293:                if (buf[length-1] == 0x00) *frags = 1;
        !           294:                if (buf[length-2] == 0x00 &&
        !           295:                    buf[length-1] == 0x00) *frags = 2;
        !           296:                if (buf[length-3] == 0x00 &&
        !           297:                    buf[length-2] == 0x00 &&
        !           298:                    buf[length-1] == 0x01) *frags = 3;
        !           299:                return -1;
        !           300:        }
        !           301: 
        !           302:        return c;
        !           303: }
        !           304: 
        !           305: void pes_out( u8 const *buf, long int length,p2t_t *p)
        !           306: {
        !           307:   
        !           308:        if ( length > 3 && 
        !           309:             buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x01 )
        !           310:                switch (buf[3]){
        !           311:                        case PROG_STREAM_MAP:
        !           312:                        case PRIVATE_STREAM2:
        !           313:                        case PROG_STREAM_DIR:
        !           314:                        case ECM_STREAM     :
        !           315:                        case EMM_STREAM     :
        !           316:                        case PADDING_STREAM :
        !           317:                        case DSM_CC_STREAM  :
        !           318:                        case ISO13522_STREAM:
        !           319:                        case PRIVATE_STREAM1:
        !           320:                        case AUDIO_STREAM_S ... AUDIO_STREAM_E:
        !           321:                                p->type = AUDIO;
        !           322:                                break;
        !           323:                        case VIDEO_STREAM_S ... VIDEO_STREAM_E:
        !           324:                                p->type = VIDEO;                
        !           325:                                break;
        !           326:                        default:
        !           327:                                break;
        !           328:                }                       
        !           329: 
        !           330:        
        !           331: }
        !           332: 
        !           333: void get_pes( u8 const *buf, long int length, p2t_t *p)
        !           334: {
        !           335:        int c,c2,l,add;
        !           336:        int check;
        !           337: 
        !           338:        c = 0;
        !           339:        c2 = 0;
        !           340:        if (p->frags){
        !           341:                check = 0;
        !           342:                switch(p->frags){
        !           343:                case 1:
        !           344:                        if ( buf[c] == 0x00 && buf[c+1] == 0x01 ){
        !           345:                                check = 1;
        !           346:                                c += 2;
        !           347:                        }
        !           348:                        break;
        !           349:                case 2:
        !           350:                        if ( buf[c] == 0x01 ){
        !           351:                                check = 1;
        !           352:                                c++;
        !           353:                        }
        !           354:                        break;
        !           355:                case 3:
        !           356:                        check = 1;
        !           357:                }
        !           358:                if(check){
        !           359:                        switch ( buf[c] ) {
        !           360:                                
        !           361:                        case PROG_STREAM_MAP:
        !           362:                        case PRIVATE_STREAM2:
        !           363:                        case PROG_STREAM_DIR:
        !           364:                        case ECM_STREAM     :
        !           365:                        case EMM_STREAM     :
        !           366:                        case PADDING_STREAM :
        !           367:                        case DSM_CC_STREAM  :
        !           368:                        case ISO13522_STREAM:
        !           369:                        case PRIVATE_STREAM1:
        !           370:                        case AUDIO_STREAM_S ... AUDIO_STREAM_E:
        !           371:                        case VIDEO_STREAM_S ... VIDEO_STREAM_E:
        !           372:                                p->pes[0] = 0x00;
        !           373:                                p->pes[1] = 0x00;
        !           374:                                p->pes[2] = 0x01;
        !           375:                                p->pes[3] = buf[c];
        !           376:                                p->pos=4;
        !           377:                                /*
        !           378:                                memcpy(p->pes+p->pos,buf+c,
        !           379:                                       PBUFFER-p->pos);
        !           380:                                c += PBUFFER-p->pos;
        !           381:                                p->pos = PBUFFER;
        !           382:                                */
        !           383:                                pes_out(p->pes,p->pos,p);
        !           384:                                clear_p2t(p);
        !           385:                                break;
        !           386:                                
        !           387:                        default:
        !           388:                                c=0;
        !           389:                                break;
        !           390:                        }
        !           391:                }
        !           392:                p->frags = 0;
        !           393:        }
        !           394:                
        !           395:        add = 0;
        !           396:        while (c < length){
        !           397:                c2 = find_pes_header(buf+c+add,length-c-add,&p->frags);
        !           398:                if (c2 >= 0) {
        !           399:                        c2 += c+add;
        !           400:                        if (c2 > c){
        !           401:                                pes_out(buf+c,c2-c,p);
        !           402:                                c = c2;
        !           403:                                clear_p2t(p);
        !           404:                                add = 0;
        !           405:                        } else add = 1;
        !           406:                } else {
        !           407:                        l = length-c;
        !           408:                        pes_out(buf+c,l,p);
        !           409:                        c = length;
        !           410:                }
        !           411:        }
        !           412: }
        !           413: 
        !           414: 
        !           415: 
        !           416: int MargiPush(struct cvdv_cards *card, int count, const char *data)
        !           417: {
        !           418: //     printk(KERN_DEBUG LOGNAME ": -- MargiPush(%d,0x%08lX)\n",count,(long)data);
        !           419:        if (!card->use_ring)
        !           420:                return 0;
        !           421: 
        !           422:        if (!card->channelrun){
        !           423:                DecoderStartChannel(card);
        !           424:        }
        !           425: 
        !           426:        card->DMAABusy = 1;
        !           427:        /*
        !           428:          while (ring_write_rest(&(card->rbuf)) < count && co < 100){
        !           429:        printk("buffer waiting to write\n");
        !           430:          co++;
        !           431: //       interruptible_sleep_on(&card->wqA);
        !           432: //       if (signal_pending(current))
        !           433: //         return 0;
        !           434:        }
        !           435:        */
        !           436:        count = ring_write(&(card->rbuf),data,count);
        !           437:        return count;
        !           438: }
        !           439: 
        !           440: int DecoderStartChannel(struct cvdv_cards *card)
        !           441: {
        !           442:        //DecoderSetByte(card,0x007,0x01);  // channel start
        !           443:        DecoderMaskByte(card, 0x007, 0xC3, 0xC3);       // channel start
        !           444:        //DecoderSetByte(card,0x005,0x01);  // invert channel clock on
        !           445:        //DecoderDelByte(card,0x005,0x02);  // channel request mode off
        !           446:        //DecoderDelByte(card,0x005,0x04);  // channel pause off
        !           447:        //DecoderDelByte(card,0x005,0x08);  // channel bypass enable off
        !           448: #ifdef BYPASS 
        !           449:        DecoderMaskByte(card,0x005,0x0F,0x08);
        !           450: #else
        !           451:        DecoderMaskByte(card,0x005,0x0F,0x01);
        !           452: #endif
        !           453:        card->channelrun = 1;
        !           454:        return 0;
        !           455: }
        !           456: 
        !           457: int DecoderStopChannel(struct cvdv_cards *card)
        !           458: {
        !           459:   //   DecoderDelByte(card,0x007,0x01);  // channel reset
        !           460:        DecoderMaskByte(card, 0x007, 0xC3, 0xC2);       // channel reset
        !           461:        DecoderSetByte(card, 0x005, 0x04);      // channel pause
        !           462:        card->channelrun = 0;
        !           463:        return 0;
        !           464: }
        !           465: 
        !           466: u32 DecoderGetAudioBufferSpace(struct cvdv_cards *card)
        !           467: {
        !           468: 
        !           469:        u32 MaxSize, Size;
        !           470: 
        !           471:        MaxSize = card->AudioESSize;
        !           472:        Size = DecoderGetAudioESLevel(card);
        !           473: 
        !           474:        if (Size>MaxSize)
        !           475:          return 0;
        !           476:        return (MaxSize - Size);
        !           477: 
        !           478: }
        !           479: 
        !           480: u32 DecoderGetVideoBufferSpace(struct cvdv_cards *card)
        !           481: {
        !           482: 
        !           483:        u32 MaxSize, Size;
        !           484: 
        !           485:        MaxSize = card->VideoESSize;
        !           486:        Size = DecoderGetVideoESLevel(card);
        !           487: 
        !           488:        if (Size>MaxSize)
        !           489:          return 0;
        !           490:        return (MaxSize - Size);
        !           491: 
        !           492: }
        !           493: 
        !           494: u32 DecoderGetBufferSpace(struct cvdv_cards *card)
        !           495: {
        !           496:        u32 audio,video;
        !           497:        
        !           498:        audio = DecoderGetAudioBufferSpace(card);
        !           499:        video = DecoderGetVideoBufferSpace(card);
        !           500: 
        !           501:                if (audio > 2048) audio -= 2048;
        !           502:                if (video > 16384) video -= 16384;
        !           503: 
        !           504:        if (audio < video) return audio;
        !           505:        return video;
        !           506: }
        !           507: 
        !           508: static int ringDMA (struct cvdv_cards *card){
        !           509:        
        !           510:        u32 size = 0;
        !           511:        u_char stat;
        !           512:        dev_link_t *link = &(((margi_info_t *) card->margi)->link);
        !           513:        u32 count=0;
        !           514:        u8 data;
        !           515:        
        !           516:        count = ring_read_rest(&(card->rbuf));
        !           517:        if (count < 4096) {
        !           518:                card->DMAABusy = 0;
        !           519:                wake_up_interruptible(&(card->wqA));
        !           520:                return 0;
        !           521:        } else  if ( card->stream.sh.valid &&
        !           522:                     card->setup.audioselect == audio_none)
        !           523:                DecoderStartDecode(card);
        !           524: 
        !           525: 
        !           526:        stat = read_lsi_status(card);
        !           527:        /*
        !           528:        printk(KERN_DEBUG LOGNAME 
        !           529:               ": -- stat: %d  readpos: %d writepos: %d \n",
        !           530:               stat,card->rbuf.read_pos,card->rbuf.write_pos);
        !           531:        */
        !           532:        if (stat & LSI_ARQ) {
        !           533:                stat = read_lsi_status(card);
        !           534:        }
        !           535: 
        !           536:        if (stat & LSI_READY){
        !           537:                data = read_indexed_register(card, IIO_LSI_CONTROL);
        !           538:                data |= RR;
        !           539:                write_indexed_register(card, IIO_LSI_CONTROL, data);
        !           540:                return 0;
        !           541:        }
        !           542: 
        !           543:        if ((stat & LSI_ARQ) == 0) {
        !           544:                size = DecoderGetBufferSpace(card);
        !           545:                if (count > size) count = size & 0xfffffffc;
        !           546:                if (count>=2048) count &=0xfffff800;
        !           547:                count &=0xfffffffc;
        !           548:                
        !           549:                /*
        !           550:                printk(KERN_DEBUG LOGNAME 
        !           551:                       ": -- stat: %d  length: %d size: %d\n",
        !           552:                       stat,count,size);
        !           553:                */
        !           554:                if (count) {
        !           555:                        ring_read_direct(&(card->rbuf),
        !           556:                                         link->io.BasePort1+DIO_LSI_STATUS, 
        !           557:                                         count);
        !           558:                    }
        !           559:        } else {
        !           560:                count = 0;
        !           561:                //card->DMAABusy = 0;
        !           562:        }
        !           563: 
        !           564:        return count;
        !           565: }
        !           566: 
        !           567: 
        !           568: u_char read_indexed_register(struct cvdv_cards * card, int addr)
        !           569: {
        !           570:        dev_link_t *link = &(((margi_info_t *) card->margi)->link);
        !           571: 
        !           572:        outb(addr, link->io.BasePort1 + DIO_CONTROL_INDEX);
        !           573:        return (inb(link->io.BasePort1 + DIO_CONTROL_DATA));
        !           574: }
        !           575: 
        !           576: 
        !           577: void write_indexed_register(struct cvdv_cards *card, int addr, u_char data)
        !           578: {
        !           579:        dev_link_t *link = &(((margi_info_t *) card->margi)->link);
        !           580: 
        !           581:        outb(addr, link->io.BasePort1 + DIO_CONTROL_INDEX);
        !           582:        outb(data, link->io.BasePort1 + DIO_CONTROL_DATA);
        !           583: }
        !           584: 
        !           585: void WriteByte(struct cvdv_cards *card, int addr, u_char data)
        !           586: {
        !           587:        dev_link_t *link = &(((margi_info_t *) card->margi)->link);
        !           588: 
        !           589:        outb((u_char) (addr & 255),
        !           590:             link->io.BasePort1 + DIO_LSI_INDEX_LOW);
        !           591:        outb(((addr & 256) ? 1 : 0),
        !           592:             link->io.BasePort1 + DIO_LSI_INDEX_HIGH);
        !           593:        outb(data, link->io.BasePort1 + DIO_LSI_DATA);
        !           594: }
        !           595: 
        !           596: u_char ReadByte(struct cvdv_cards *card, int addr)
        !           597: {
        !           598:        dev_link_t *link = &(((margi_info_t *) card->margi)->link);
        !           599: 
        !           600:        outb((u_char) (addr & 255),
        !           601:             link->io.BasePort1 + DIO_LSI_INDEX_LOW);
        !           602:        outb(((addr & 256) ? 1 : 0),
        !           603:             link->io.BasePort1 + DIO_LSI_INDEX_HIGH);
        !           604:        return inb(link->io.BasePort1 + DIO_LSI_DATA);
        !           605: }
        !           606: 
        !           607: void MaskByte(struct cvdv_cards *card, int addr, u_char mask, u_char bits)
        !           608: {
        !           609:        WriteByte(card, addr, (ReadByte(card, addr) & ~(mask)) | (bits));
        !           610: }
        !           611: 
        !           612: 
        !           613: 
        !           614: #define MAXWRITE 49000
        !           615: #define MAX_COUNT 10
        !           616: 
        !           617: #ifdef USE_BH
        !           618: struct cvdv_cards *bh_card;
        !           619: 
        !           620: static void do_margi_bh(void)
        !           621: {
        !           622:        struct cvdv_cards *card = bh_card;
        !           623: #else
        !           624: 
        !           625: static void do_margi(struct cvdv_cards *card)
        !           626: {
        !           627: 
        !           628: #endif
        !           629:        int countA, countB;
        !           630:        int try;
        !           631: 
        !           632:        countA = 0;
        !           633:        countB = 0;
        !           634: 
        !           635:        card->currentType = 0;
        !           636:        for ( try = 0; try < MAX_COUNT ;try++)
        !           637:                if (countA < MAXWRITE){
        !           638:                        int count = 0;
        !           639:                        count = ringDMA(card);
        !           640:                        countA += count;
        !           641:                        if (!count) 
        !           642:                                try=MAX_COUNT;
        !           643:                } else break;
        !           644: 
        !           645: 
        !           646: }
        !           647: 
        !           648: void L64014Intr(int irq, void *dev_id, struct pt_regs *regs)
        !           649: {
        !           650:        margi_info_t *margi = dev_id;
        !           651:        struct cvdv_cards *card = &(margi->card);
        !           652:        u_char dio_index, lsi_index_low, lsi_index_high;
        !           653:        u8 control,mask,stat;
        !           654:        int try;
        !           655: 
        !           656:        //save registers
        !           657:        dio_index = inb(margi->link.io.BasePort1 + DIO_CONTROL_INDEX);
        !           658:        lsi_index_low = inb(margi->link.io.BasePort1 + DIO_LSI_INDEX_LOW);
        !           659:        lsi_index_high =
        !           660:            inb(margi->link.io.BasePort1 + DIO_LSI_INDEX_HIGH);
        !           661: 
        !           662:        control= read_indexed_register(card, IIO_IRQ_CONTROL);
        !           663:        if (control & IRQ_EN){
        !           664:                mask = 0;
        !           665:                if ( control & DEC_EN ) mask |= DEC_INT;
        !           666:                if ( control & VSYNC_EN ) mask |= VSYNC_INT;
        !           667:                stat = read_indexed_register(card, IIO_IRQ_STATUS);
        !           668:                try = 0;
        !           669:                while ( (try++ < 100) && (stat & mask) ){                     
        !           670:                        
        !           671:                        if (stat & DEC_INT) {
        !           672:                                write_indexed_register(card,IIO_IRQ_CONTROL,
        !           673:                                                       control & (~DEC_EN));
        !           674:                                write_indexed_register(card,IIO_IRQ_CONTROL,
        !           675:                                                       control);
        !           676:                                
        !           677:                                if(card->use_ring){
        !           678:                                        L64021Intr(card);
        !           679:                                }
        !           680:                        }
        !           681:                        if (stat & VSYNC_INT) {
        !           682:                                
        !           683:                                write_indexed_register(card,IIO_IRQ_CONTROL,
        !           684:                                                       control & (~VSYNC_EN));
        !           685:                                write_indexed_register(card,IIO_IRQ_CONTROL,
        !           686:                                                       control);
        !           687:                                if(card->use_ring){
        !           688:                                        L64021Intr(card);
        !           689:                                }
        !           690:                                if (card->DMAABusy){
        !           691: 
        !           692: #ifdef USE_BH
        !           693:                                        bh_card = card;
        !           694:                                        mark_bh(MARGI_BH);
        !           695: #else 
        !           696:                                        do_margi(card);
        !           697: #endif
        !           698:                }
        !           699:                        }
        !           700: 
        !           701:                        stat = read_indexed_register(card, IIO_IRQ_STATUS);
        !           702:                }
        !           703:        }
        !           704: 
        !           705:        //load registers
        !           706:        outb(dio_index, margi->link.io.BasePort1 + DIO_CONTROL_INDEX);
        !           707:        outb(lsi_index_low, margi->link.io.BasePort1 + DIO_LSI_INDEX_LOW);
        !           708:        outb(lsi_index_high,margi->link.io.BasePort1 + DIO_LSI_INDEX_HIGH);
        !           709: }
        !           710: 
        !           711: int L64014RemoveIntr(struct cvdv_cards *card)
        !           712: {
        !           713:        printk(KERN_DEBUG LOGNAME ": -- L64014RemoveIntr\n");
        !           714:        // Disable the IRQ's
        !           715:        write_indexed_register(card, IIO_IRQ_CONTROL, 0x00);
        !           716:        if (!card->IntInstalled)
        !           717:                return 1;
        !           718:        L64021RemoveIntr(card);
        !           719:        return 0;
        !           720: }
        !           721: 
        !           722: void l64020Reset(struct cvdv_cards *card){
        !           723:        u8 data;
        !           724:        
        !           725:        
        !           726:        data = read_indexed_register(card, IIO_LSI_CONTROL);
        !           727:        data &= ~(RR | DR);
        !           728:        write_indexed_register(card, IIO_LSI_CONTROL, data);
        !           729:        mdelay(100);
        !           730:        data = read_indexed_register(card, IIO_LSI_CONTROL);
        !           731:        data |= DR;
        !           732:        write_indexed_register(card, IIO_LSI_CONTROL, data);
        !           733: 
        !           734:        data = read_indexed_register(card,IIO_GPIO_PINS);
        !           735:        data &= ~0x01;
        !           736:        write_indexed_register(card,IIO_GPIO_PINS,data);
        !           737:        data |= 0x01;
        !           738:        write_indexed_register(card,IIO_GPIO_PINS,data);
        !           739:        
        !           740:        //write_indexed_register(card, IIO_LSI_CONTROL, DR);
        !           741: }
        !           742: 
        !           743: int L64014Init(struct cvdv_cards *card)
        !           744: {
        !           745:        u16 testram[16];
        !           746:        int i, err;
        !           747: 
        !           748:        printk(KERN_DEBUG LOGNAME ": -- L64014Init\n");
        !           749:        card->videomode = VIDEO_MODE;
        !           750: 
        !           751:        /* Reset 64020 */
        !           752:        write_indexed_register(card, IIO_GPIO_CONTROL, 0x01);
        !           753:        l64020Reset(card);
        !           754:        /* init GPIO */
        !           755:        write_indexed_register(card, IIO_GPIO_CONTROL, 0x01);
        !           756:        write_indexed_register(card, IIO_GPIO_PINS, 0xff);
        !           757: 
        !           758:        /* Set to PAL */
        !           759:        write_indexed_register(card, IIO_VIDEO_CONTROL0, 0);
        !           760:        write_indexed_register(card, IIO_VIDEO_CONTROL1, VMS_PAL);
        !           761: 
        !           762:        /* Set Audio freq */
        !           763:        write_indexed_register(card, IIO_OSC_AUD, 0x12);
        !           764: 
        !           765:        write_indexed_register(card, CSS_COMMAND, 0x01);
        !           766: 
        !           767: 
        !           768:        printk("CSID: %02x\n", I2CRead(card, 0, 0x3d));
        !           769:        card->i2c_addr = I2CRead(card, 0, 0x0f);
        !           770:        printk("I2CADDR: %02x\n", card->i2c_addr);
        !           771: 
        !           772:        I2CWrite(card, card->i2c_addr, CS_CONTROL0, 0x4a);
        !           773:        I2CWrite(card, card->i2c_addr, CS_CONTROL1, 0x04);
        !           774:        I2CWrite(card, card->i2c_addr, CS_SC_AMP, 0x15);
        !           775:        I2CWrite(card, card->i2c_addr, CS_SC_SYNTH0, 0x96);
        !           776:        I2CWrite(card, card->i2c_addr, CS_SC_SYNTH1, 0x15);
        !           777:        I2CWrite(card, card->i2c_addr, CS_SC_SYNTH2, 0x13);
        !           778:        I2CWrite(card, card->i2c_addr, CS_SC_SYNTH3, 0x54);
        !           779: 
        !           780:        I2CWrite(card, card->i2c_addr, CS_DAC, 0x87);
        !           781:        I2CWrite(card, card->i2c_addr, CS_BKG_COL, 0x03);
        !           782: 
        !           783:        printk("Decoder Status: %d\n", read_lsi_status(card));
        !           784:        printk("lsi stat %d\n", DecoderReadByte(card, 0x005));
        !           785: 
        !           786:        L64021Init(card);
        !           787: 
        !           788:        // Find out how much DRAM we have
        !           789:        card->DRAMSize = 0x00200000;    // maximum size
        !           790:        do {
        !           791:                printk(KERN_DEBUG LOGNAME
        !           792:                       ": Probing DRAM Size: 0x%08X (%d kByte) ... ",
        !           793:                       card->DRAMSize, card->DRAMSize / 512);
        !           794:                for (i = 0; i < 8; i++)
        !           795:                        testram[i] = rnd(0x100) | (rnd(0x100) << 8);
        !           796:                if (DRAMWriteWord(card, 0, 4, &testram[0], 0))
        !           797:                        printk(KERN_DEBUG LOGNAME ": DRAM Write error.\n");
        !           798:                if (DRAMWriteWord
        !           799:                    (card, card->DRAMSize - 4, 4, &testram[4],
        !           800:                     0)) printk(KERN_DEBUG LOGNAME
        !           801:                                ": DRAM Write error.\n");
        !           802:                if (DRAMReadWord(card, 0, 4, &testram[8], 0))
        !           803:                        printk(KERN_DEBUG LOGNAME ": DRAM Read error.\n");
        !           804:                if (DRAMReadWord
        !           805:                    (card, card->DRAMSize - 4, 4, &testram[12],
        !           806:                     0)) printk(KERN_DEBUG LOGNAME ": DRAM Read error.\n");
        !           807:                err = 0;
        !           808:                for (i = 0; (!err) && (i < 8); i++)
        !           809:                        if (testram[i] != testram[i + 8])
        !           810:                                err = i + 1;
        !           811:                if (err) printk(" failed\n");
        !           812:                else printk(" ok\n");
        !           813:                /*
        !           814:                if (err)
        !           815:                        printk(KERN_DEBUG LOGNAME
        !           816:                               ": DRAM compare error at cell %d: 0x%04X %04X %04X %04X->0x%04X %04X %04X %04X / 0x%04X %04X %04X %04X->0x%04X %04X %04X %04X\n",
        !           817:                               err, testram[0], testram[1], testram[2],
        !           818:                               testram[3], testram[8], testram[9],
        !           819:                               testram[10], testram[11], testram[4],
        !           820:                               testram[5], testram[6], testram[7],
        !           821:                               testram[12], testram[13], testram[14],
        !           822:                               testram[15]);
        !           823:                */
        !           824:                if (err)
        !           825:                        card->DRAMSize >>= 1;
        !           826:        } while (err && (card->DRAMSize >= 0x00100000));
        !           827:        printk(KERN_INFO LOGNAME ": DRAM Size: 0x%08X (%d kByte)\n",
        !           828:               card->DRAMSize, card->DRAMSize / 512);
        !           829:        if (card->DRAMSize < 0x00100000) {      // minimum size
        !           830:                printk(KERN_INFO LOGNAME
        !           831:                       ": DRAM ERROR: Not enough memory on card!\n");
        !           832:                return 1;
        !           833:        }
        !           834:        return 0;
        !           835: }
        !           836: 
        !           837: 
        !           838: void CardDeInit(struct cvdv_cards *card)
        !           839: {
        !           840:        CloseCard(card);
        !           841:        MargiFlush(card);
        !           842:        MargiFreeBuffers(card);
        !           843:        L64014RemoveIntr(card);
        !           844: }
        !           845: 
        !           846: 
        !           847: static u_char read_lsi_status(struct cvdv_cards *card)
        !           848: {
        !           849:        margi_info_t *margi = (margi_info_t *) card->margi;
        !           850:        return (inb(margi->link.io.BasePort1 + DIO_LSI_STATUS) & 15);
        !           851: 
        !           852: }
        !           853: 
        !           854: /*====================================================================*/
        !           855: 
        !           856: static void cs_error(client_handle_t handle, int func, int ret)
        !           857: {
        !           858:        error_info_t err = { func, ret };
        !           859:        CardServices(ReportError, handle, &err);
        !           860: }
        !           861: 
        !           862: /*======================================================================
        !           863: 
        !           864:     margi_attach() creates an "instance" of the driver, allocating
        !           865:     local data structures for one device.  The device is registered
        !           866:     with Card Services.
        !           867: 
        !           868:     The dev_link structure is initialized, but we don't actually
        !           869:     configure the card at this point -- we wait until we receive a
        !           870:     card insertion event.
        !           871:     
        !           872: ======================================================================*/
        !           873: 
        !           874: static dev_link_t *margi_attach(void)
        !           875: {
        !           876:        margi_info_t *local;
        !           877:        dev_link_t *link;
        !           878:        client_reg_t client_reg;
        !           879:        int ret, i;
        !           880: 
        !           881:        DEBUG(0, "margi_attach()\n");
        !           882: 
        !           883:        for (i = 0; i < MAX_DEV; i++)
        !           884:                if (dev_table[i] == NULL)
        !           885:                        break;
        !           886:        if (i == MAX_DEV) {
        !           887:                printk(KERN_NOTICE "margi_cs: no devices available\n");
        !           888:                return NULL;
        !           889:        }
        !           890: 
        !           891:        /* Allocate space for private device-specific data */
        !           892:        local = kmalloc(sizeof(margi_info_t), GFP_KERNEL);
        !           893:        if (!local)
        !           894:                return NULL;
        !           895:        memset(local, 0, sizeof(margi_info_t));
        !           896:        link = &local->link;
        !           897:        link->priv = local;
        !           898:        local->card.margi = (void *) local;
        !           899:        dev_table[i] = link;
        !           900: 
        !           901:        /* Initialize the dev_link_t structure */
        !           902:        link->release.function = &margi_release;
        !           903:        link->release.data = (u_long) link;
        !           904: 
        !           905:        /* Interrupt setup */
        !           906:        link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
        !           907:        link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
        !           908:        if (irq_list[0] == -1)
        !           909:                link->irq.IRQInfo2 = irq_mask;
        !           910:        else
        !           911:                for (i = 0; i < 4; i++)
        !           912:                        link->irq.IRQInfo2 |= 1 << irq_list[i];
        !           913:        link->irq.Handler = NULL;
        !           914: 
        !           915:        /*
        !           916:           General socket configuration defaults can go here.  In this
        !           917:           client, we assume very little, and rely on the CIS for almost
        !           918:           everything.  In most clients, many details (i.e., number, sizes,
        !           919:           and attributes of IO windows) are fixed by the nature of the
        !           920:           device, and can be hard-wired here.
        !           921:         */
        !           922:        link->conf.Attributes = 0;
        !           923:        link->conf.Vcc = 50;
        !           924:        link->conf.IntType = INT_MEMORY_AND_IO;
        !           925: 
        !           926:        /* Register with Card Services */
        !           927:        link->next = dev_list;
        !           928:        dev_list = link;
        !           929:        client_reg.dev_info = &dev_info;
        !           930:        client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
        !           931:        client_reg.EventMask =
        !           932:            CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
        !           933:            CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
        !           934:            CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
        !           935:        client_reg.event_handler = &margi_event;
        !           936:        client_reg.Version = 0x0210;
        !           937:        client_reg.event_callback_args.client_data = link;
        !           938:        ret = CardServices(RegisterClient, &link->handle, &client_reg);
        !           939:        if (ret != CS_SUCCESS) {
        !           940:                cs_error(link->handle, RegisterClient, ret);
        !           941:                margi_detach(link);
        !           942:                return NULL;
        !           943:        }
        !           944: 
        !           945:        return link;
        !           946: }                              /* margi_attach */
        !           947: 
        !           948: /*======================================================================
        !           949: 
        !           950:     This deletes a driver "instance".  The device is de-registered
        !           951:     with Card Services.  If it has been released, all local data
        !           952:     structures are freed.  Otherwise, the structures will be freed
        !           953:     when the device is released.
        !           954: 
        !           955: ======================================================================*/
        !           956: 
        !           957: static void margi_detach(dev_link_t * link)
        !           958: {
        !           959:        dev_link_t **linkp;
        !           960: 
        !           961:        int nd;
        !           962: 
        !           963:        DEBUG(0, "margi_detach(0x%p)\n", link);
        !           964: 
        !           965:        for (nd = 0; nd < MAX_DEV; nd++)
        !           966:                if (dev_table[nd] == link)
        !           967:                        break;
        !           968:        if (nd == MAX_DEV)
        !           969:                return;
        !           970: 
        !           971:        /* Locate device structure */
        !           972:        for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
        !           973:                if (*linkp == link)
        !           974:                        break;
        !           975:        if (*linkp == NULL)
        !           976:                return;
        !           977: 
        !           978:        /*
        !           979:           If the device is currently configured and active, we won't
        !           980:           actually delete it yet.  Instead, it is marked so that when
        !           981:           the release() function is called, that will trigger a proper
        !           982:           detach().
        !           983:         */
        !           984:        if (link->state & DEV_CONFIG) {
        !           985: #ifdef PCMCIA_DEBUG
        !           986:                printk(KERN_DEBUG "margi_cs: detach postponed, '%s' "
        !           987:                       "still locked\n", link->dev->dev_name);
        !           988: #endif
        !           989:                link->state |= DEV_STALE_LINK;
        !           990:                return;
        !           991:        }
        !           992: 
        !           993:        /* Break the link with Card Services */
        !           994:        if (link->handle)
        !           995:                CardServices(DeregisterClient, link->handle);
        !           996: 
        !           997:        /* Unlink device structure, and free it */
        !           998:        *linkp = link->next;
        !           999:        /* This points to the parent struct cvdv_cards struct */
        !          1000:        dev_table[nd] = NULL;
        !          1001: 
        !          1002:        kfree(link->priv);
        !          1003: 
        !          1004: }                              /* margi_detach */
        !          1005: 
        !          1006: /*======================================================================
        !          1007: 
        !          1008:     margi_config() is scheduled to run after a CARD_INSERTION event
        !          1009:     is received, to configure the PCMCIA socket, and to make the
        !          1010:     device available to the system.
        !          1011:     
        !          1012: ======================================================================*/
        !          1013: 
        !          1014: #define CS_CHECK(fn, args...) \
        !          1015: while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed
        !          1016: 
        !          1017: #define CFG_CHECK(fn, args...) \
        !          1018: if (CardServices(fn, args) != 0) goto next_entry
        !          1019: 
        !          1020: static void margi_config(dev_link_t * link)
        !          1021: {
        !          1022:        client_handle_t handle = link->handle;
        !          1023:        margi_info_t *dev = link->priv;
        !          1024:        struct cvdv_cards *card = &(dev->card);
        !          1025:        tuple_t tuple;
        !          1026:        cisparse_t parse;
        !          1027:        int last_fn, last_ret, i;
        !          1028:        u_char buf[64];
        !          1029:        config_info_t conf;
        !          1030:        win_req_t req;
        !          1031:        memreq_t map;
        !          1032:        int minor = 0;
        !          1033: 
        !          1034:        DEBUG(0, "margi_config(0x%p)\n", link);
        !          1035: 
        !          1036:        /*
        !          1037:           This reads the card's CONFIG tuple to find its configuration
        !          1038:           registers.
        !          1039:         */
        !          1040:        tuple.DesiredTuple = CISTPL_CONFIG;
        !          1041:        tuple.Attributes = 0;
        !          1042:        tuple.TupleData = buf;
        !          1043:        tuple.TupleDataMax = sizeof(buf);
        !          1044:        tuple.TupleOffset = 0;
        !          1045:        CS_CHECK(GetFirstTuple, handle, &tuple);
        !          1046:        CS_CHECK(GetTupleData, handle, &tuple);
        !          1047:        CS_CHECK(ParseTuple, handle, &tuple, &parse);
        !          1048:        link->conf.ConfigBase = parse.config.base;
        !          1049:        link->conf.Present = parse.config.rmask[0];
        !          1050: 
        !          1051:        /* Configure card */
        !          1052:        link->state |= DEV_CONFIG;
        !          1053: 
        !          1054:        /* Look up the current Vcc */
        !          1055:        CS_CHECK(GetConfigurationInfo, handle, &conf);
        !          1056:        link->conf.Vcc = conf.Vcc;
        !          1057: 
        !          1058:        /*
        !          1059:           In this loop, we scan the CIS for configuration table entries,
        !          1060:           each of which describes a valid card configuration, including
        !          1061:           voltage, IO window, memory window, and interrupt settings.
        !          1062: 
        !          1063:           We make no assumptions about the card to be configured: we use
        !          1064:           just the information available in the CIS.  In an ideal world,
        !          1065:           this would work for any PCMCIA card, but it requires a complete
        !          1066:           and accurate CIS.  In practice, a driver usually "knows" most of
        !          1067:           these things without consulting the CIS, and most client drivers
        !          1068:           will only use the CIS to fill in implementation-defined details.
        !          1069:         */
        !          1070:        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
        !          1071:        CS_CHECK(GetFirstTuple, handle, &tuple);
        !          1072:        while (1) {
        !          1073:                cistpl_cftable_entry_t dflt = { 0 };
        !          1074:                cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
        !          1075:                CFG_CHECK(GetTupleData, handle, &tuple);
        !          1076:                CFG_CHECK(ParseTuple, handle, &tuple, &parse);
        !          1077: 
        !          1078:                if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
        !          1079:                        dflt = *cfg;
        !          1080:                if (cfg->index == 0)
        !          1081:                        goto next_entry;
        !          1082:                link->conf.ConfigIndex = cfg->index;
        !          1083: 
        !          1084:                /* Does this card need audio output? */
        !          1085:                if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
        !          1086:                        link->conf.Attributes |= CONF_ENABLE_SPKR;
        !          1087:                        link->conf.Status = CCSR_AUDIO_ENA;
        !          1088:                }
        !          1089: 
        !          1090:                /* Use power settings for Vcc and Vpp if present */
        !          1091:                /*  Note that the CIS values need to be rescaled */
        !          1092:                if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
        !          1093:                        if (conf.Vcc !=
        !          1094:                            cfg->vcc.param[CISTPL_POWER_VNOM] /
        !          1095:                            10000) goto next_entry;
        !          1096:                } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
        !          1097:                        if (conf.Vcc !=
        !          1098:                            dflt.vcc.param[CISTPL_POWER_VNOM] /
        !          1099:                            10000) goto next_entry;
        !          1100:                }
        !          1101: 
        !          1102:                if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
        !          1103:                        link->conf.Vpp1 = link->conf.Vpp2 =
        !          1104:                            cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
        !          1105:                else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
        !          1106:                        link->conf.Vpp1 = link->conf.Vpp2 =
        !          1107:                            dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
        !          1108: 
        !          1109:                /* Do we need to allocate an interrupt? */
        !          1110:                //      if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
        !          1111:                //link->conf.Attributes |= CONF_ENABLE_IRQ;
        !          1112:                /*
        !          1113:                   Allocate an interrupt line.  Note that this does not assign a
        !          1114:                   handler to the interrupt, unless the 'Handler' member of the
        !          1115:                   irq structure is initialized.
        !          1116:                 */
        !          1117: 
        !          1118:                link->irq.Attributes =
        !          1119:                  IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
        !          1120:                link->irq.Handler = &L64014Intr;
        !          1121:                link->irq.Instance = link;
        !          1122:                link->conf.Attributes |= CONF_ENABLE_IRQ;
        !          1123: 
        !          1124: #ifdef USE_BH
        !          1125:                init_bh(MARGI_BH, do_margi_bh);
        !          1126: #endif
        !          1127:                if (link->conf.Attributes & CONF_ENABLE_IRQ)
        !          1128:                        CS_CHECK(RequestIRQ, link->handle, &link->irq);
        !          1129: 
        !          1130:                /* IO window settings */
        !          1131:                link->io.NumPorts1 = link->io.NumPorts2 = 0;
        !          1132:                if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
        !          1133:                        cistpl_io_t *io =
        !          1134:                            (cfg->io.nwin) ? &cfg->io : &dflt.io;
        !          1135:                        link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
        !          1136:                        if (!(io->flags & CISTPL_IO_8BIT))
        !          1137:                                link->io.Attributes1 =
        !          1138:                                    IO_DATA_PATH_WIDTH_16;
        !          1139:                        if (!(io->flags & CISTPL_IO_16BIT))
        !          1140:                                link->io.Attributes1 =
        !          1141:                                    IO_DATA_PATH_WIDTH_8;
        !          1142:                        link->io.IOAddrLines =
        !          1143:                            io->flags & CISTPL_IO_LINES_MASK;
        !          1144:                        link->io.BasePort1 = io->win[0].base;
        !          1145:                        link->io.NumPorts1 = io->win[0].len;
        !          1146:                        if (io->nwin > 1) {
        !          1147:                                link->io.Attributes2 =
        !          1148:                                    link->io.Attributes1;
        !          1149:                                link->io.BasePort2 = io->win[1].base;
        !          1150:                                link->io.NumPorts2 = io->win[1].len;
        !          1151:                        }
        !          1152:                }
        !          1153: 
        !          1154:                /* This reserves IO space but doesn't actually enable it */
        !          1155:                CFG_CHECK(RequestIO, link->handle, &link->io);
        !          1156: 
        !          1157:                /*
        !          1158:                   Now set up a common memory window, if needed.  There is room
        !          1159:                   in the dev_link_t structure for one memory window handle,
        !          1160:                   but if the base addresses need to be saved, or if multiple
        !          1161:                   windows are needed, the info should go in the private data
        !          1162:                   structure for this device.
        !          1163: 
        !          1164:                   Note that the memory window base is a physical address, and
        !          1165:                   needs to be mapped to virtual space with ioremap() before it
        !          1166:                   is used.
        !          1167:                 */
        !          1168:                if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
        !          1169:                        cistpl_mem_t *mem =
        !          1170:                            (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
        !          1171:                        req.Attributes =
        !          1172:                            WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM;
        !          1173:                        req.Attributes |= WIN_ENABLE;
        !          1174:                        req.Base = mem->win[0].host_addr;
        !          1175:                        req.Size = mem->win[0].len;
        !          1176:                        req.AccessSpeed = 0;
        !          1177:                        link->win = (window_handle_t) link->handle;
        !          1178:                        CFG_CHECK(RequestWindow, &link->win, &req);
        !          1179:                        map.Page = 0;
        !          1180:                        map.CardOffset = mem->win[0].card_addr;
        !          1181:                        CFG_CHECK(MapMemPage, link->win, &map);
        !          1182:                }
        !          1183:                /* If we got this far, we're cool! */
        !          1184:                break;
        !          1185:                
        !          1186:        next_entry:
        !          1187:                CS_CHECK(GetNextTuple, handle, &tuple);
        !          1188:        }
        !          1189: 
        !          1190:        /*
        !          1191:           This actually configures the PCMCIA socket -- setting up
        !          1192:           the I/O windows and the interrupt mapping, and putting the
        !          1193:           card and host interface into "Memory and IO" mode.
        !          1194:         */
        !          1195:        CS_CHECK(RequestConfiguration, link->handle, &link->conf);
        !          1196: 
        !          1197:        /*
        !          1198:           We can release the IO port allocations here, if some other
        !          1199:           driver for the card is going to loaded, and will expect the
        !          1200:           ports to be available.
        !          1201:         */
        !          1202:        if (free_ports) {
        !          1203:                if (link->io.BasePort1)
        !          1204:                        release_region(link->io.BasePort1,
        !          1205:                                       link->io.NumPorts1);
        !          1206:                if (link->io.BasePort2)
        !          1207:                        release_region(link->io.BasePort2,
        !          1208:                                       link->io.NumPorts2);
        !          1209:        }
        !          1210: 
        !          1211:        /*
        !          1212:           At this point, the dev_node_t structure(s) need to be
        !          1213:           initialized and arranged in a linked list at link->dev.
        !          1214:         */
        !          1215: 
        !          1216:        first_card = card;
        !          1217:        minor=0;
        !          1218:        card->next = NULL;
        !          1219:        card_init(card, minor);
        !          1220:        card->tqueue_decoder.routine =
        !          1221:                (void *) (void *) L64021Intr;
        !          1222:        if ((i = register_chrdev(CVDV_MAJOR, CVDV_PROCNAME, &cvdv_fileops))
        !          1223:            >= 0) {
        !          1224:                major_device_number = ((i) ? i : CVDV_MAJOR);
        !          1225:                printk(KERN_INFO LOGNAME
        !          1226:                       ": Char-device with major number %d installed\n",
        !          1227:                       major_device_number);
        !          1228:        } else {
        !          1229:                printk(KERN_ERR LOGNAME
        !          1230:                       ": ERROR: Failed to install Char-device %d, error %d\n",
        !          1231:                       CVDV_MAJOR, i);
        !          1232:        }
        !          1233:        sprintf(dev->node.dev_name, "margi");
        !          1234:        dev->node.major = major_device_number;
        !          1235:        dev->node.minor = minor;
        !          1236:        link->dev = &dev->node;
        !          1237: 
        !          1238:        /* Finally, report what we've done */
        !          1239:        printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
        !          1240:               dev->node.dev_name, link->conf.ConfigIndex,
        !          1241:               link->conf.Vcc / 10, link->conf.Vcc % 10);
        !          1242:        if (link->conf.Vpp1)
        !          1243:                printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
        !          1244:                       link->conf.Vpp1 % 10);
        !          1245:        if (link->conf.Attributes & CONF_ENABLE_IRQ)
        !          1246:                printk(", irq %d", link->irq.AssignedIRQ);
        !          1247:        if (link->io.NumPorts1)
        !          1248:                printk(", io 0x%04x-0x%04x", link->io.BasePort1,
        !          1249:                       link->io.BasePort1 + link->io.NumPorts1 - 1);
        !          1250:        if (link->io.NumPorts2)
        !          1251:                printk(" & 0x%04x-0x%04x", link->io.BasePort2,
        !          1252:                       link->io.BasePort2 + link->io.NumPorts2 - 1);
        !          1253:        if (link->win)
        !          1254:                printk(", mem 0x%06lx-0x%06lx", req.Base,
        !          1255:                       req.Base + req.Size - 1);
        !          1256:        printk("\n");
        !          1257: 
        !          1258:        link->state &= ~DEV_CONFIG_PENDING;
        !          1259:        if (0xdd == read_indexed_register(card, IIO_ID)) {
        !          1260:                printk("L64014 Version %d in mode %d detected\n",
        !          1261:                       (read_indexed_register(card, IIO_MODE) & 248) >> 3,
        !          1262:                       read_indexed_register(card, IIO_MODE) & 7);
        !          1263:                write_indexed_register(card, IIO_GPIO_CONTROL, 0x07);
        !          1264: 
        !          1265:                L64014Init(card);
        !          1266: 
        !          1267:                // default: color bars
        !          1268:                VideoSetBackground(card, 1, 0, 0, 0);   // black
        !          1269:                SetVideoSystem(card);
        !          1270:                minorlist[minor] = card;        // fast access for the char driver
        !          1271: 
        !          1272: 
        !          1273:                /*enable L64014 IRQ */
        !          1274:                write_indexed_register(card, IIO_IRQ_CONTROL,
        !          1275:                                       IRQ_POL | IRQ_EN | VSYNC_EN);
        !          1276: //             write_indexed_register(card, IIO_IRQ_CONTROL, 0x24);
        !          1277:        }
        !          1278:        return;
        !          1279: 
        !          1280:       cs_failed:
        !          1281:        cs_error(link->handle, last_fn, last_ret);
        !          1282:        margi_release((u_long) link);
        !          1283: 
        !          1284: }                              /* margi_config */
        !          1285: 
        !          1286: /*======================================================================
        !          1287: 
        !          1288:     After a card is removed, margi_release() will unregister the
        !          1289:     device, and release the PCMCIA configuration.  If the device is
        !          1290:     still open, this will be postponed until it is closed.
        !          1291:     
        !          1292: ======================================================================*/
        !          1293: 
        !          1294: static void margi_release(u_long arg)
        !          1295: {
        !          1296:        dev_link_t *link = (dev_link_t *) arg;
        !          1297:        margi_info_t *dev = link->priv;
        !          1298:        struct cvdv_cards *card = &(dev->card);
        !          1299: 
        !          1300:        DEBUG(0, "margi_release(0x%p)\n", link);
        !          1301:        /*
        !          1302:           If the device is currently in use, we won't release until it
        !          1303:           is actually closed, because until then, we can't be sure that
        !          1304:           no one will try to access the device or its data structures.
        !          1305:         */
        !          1306:        if (link->open) {
        !          1307:                DEBUG(1, "margi_cs: release postponed, '%s' still open\n",
        !          1308:                      link->dev->dev_name);
        !          1309:                link->state |= DEV_STALE_CONFIG;
        !          1310:                return;
        !          1311:        }
        !          1312: 
        !          1313:        /* Unlink the device chain */
        !          1314:        link->dev = NULL;
        !          1315: 
        !          1316:        /*
        !          1317:           In a normal driver, additional code may be needed to release
        !          1318:           other kernel data structures associated with this device. 
        !          1319:         */
        !          1320: 
        !          1321:        printk(KERN_INFO LOGNAME ": Unloading device driver\n");
        !          1322:        if (major_device_number)
        !          1323:                unregister_chrdev(major_device_number, CVDV_PROCNAME);
        !          1324:        CardDeInit(card);
        !          1325: 
        !          1326: #ifdef USE_BH
        !          1327:        remove_bh(MARGI_BH);
        !          1328: #endif
        !          1329:        mdelay(100);
        !          1330:        /* Don't bother checking to see if these succeed or not */
        !          1331:        if (link->win)
        !          1332:          CardServices(ReleaseWindow, link->win);
        !          1333:        CardServices(ReleaseConfiguration, link->handle);
        !          1334:        if (link->io.NumPorts1)
        !          1335:          CardServices(ReleaseIO, link->handle, &link->io);
        !          1336:        if (link->irq.AssignedIRQ)
        !          1337:          CardServices(ReleaseIRQ, link->handle, &link->irq);
        !          1338:        link->state &= ~DEV_CONFIG;
        !          1339: 
        !          1340:        if (link->state & DEV_STALE_LINK)
        !          1341:                margi_detach(link);
        !          1342: 
        !          1343: }                              /* margi_release */
        !          1344: 
        !          1345: /*======================================================================
        !          1346: 
        !          1347:     The card status event handler.  Mostly, this schedules other
        !          1348:     stuff to run after an event is received.
        !          1349: 
        !          1350:     When a CARD_REMOVAL event is received, we immediately set a
        !          1351:     private flag to block future accesses to this device.  All the
        !          1352:     functions that actually access the device should check this flag
        !          1353:     to make sure the card is still present.
        !          1354:     
        !          1355: ======================================================================*/
        !          1356: 
        !          1357: static int margi_event(event_t event, int priority,
        !          1358:                       event_callback_args_t * args)
        !          1359: {
        !          1360:        dev_link_t *link = args->client_data;
        !          1361:        margi_info_t *dev = link->priv;
        !          1362: 
        !          1363:        DEBUG(1, "margi_event(0x%06x)\n", event);
        !          1364: 
        !          1365:        switch (event) {
        !          1366:        case CS_EVENT_CARD_REMOVAL:
        !          1367:                link->state &= ~DEV_PRESENT;
        !          1368:                if (link->state & DEV_CONFIG) {
        !          1369:                        ((margi_info_t *) link->priv)->stop = 1;
        !          1370:                        link->release.expires = jiffies + HZ / 20;
        !          1371:                        add_timer(&link->release);
        !          1372:                }
        !          1373:                break;
        !          1374:        case CS_EVENT_CARD_INSERTION:
        !          1375:                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        !          1376:                dev->card.bus = args->bus;
        !          1377:                margi_config(link);
        !          1378:                break;
        !          1379:        case CS_EVENT_PM_SUSPEND:
        !          1380:                link->state |= DEV_SUSPEND;
        !          1381:                /* Fall through... */
        !          1382:        case CS_EVENT_RESET_PHYSICAL:
        !          1383:                /* Mark the device as stopped, to block IO until later */
        !          1384:                dev->stop = 1;
        !          1385:                if (link->state & DEV_CONFIG)
        !          1386:                        CardServices(ReleaseConfiguration, link->handle);
        !          1387:                break;
        !          1388:        case CS_EVENT_PM_RESUME:
        !          1389:                link->state &= ~DEV_SUSPEND;
        !          1390:                /* Fall through... */
        !          1391:        case CS_EVENT_CARD_RESET:
        !          1392:                if (link->state & DEV_CONFIG)
        !          1393:                        CardServices(RequestConfiguration, link->handle,
        !          1394:                                     &link->conf);
        !          1395:                dev->stop = 0;
        !          1396:                /*
        !          1397:                   In a normal driver, additional code may go here to restore
        !          1398:                   the device state and restart IO. 
        !          1399:                 */
        !          1400:                break;
        !          1401:        }
        !          1402:        return 0;
        !          1403: }                              /* margi_event */
        !          1404: 
        !          1405: /*====================================================================*/
        !          1406: 
        !          1407: static int __init init_margi_cs(void)
        !          1408: {
        !          1409:        servinfo_t serv;
        !          1410:        DEBUG(0, "%s\n", version);
        !          1411:        CardServices(GetCardServicesInfo, &serv);
        !          1412:        if (serv.Revision != CS_RELEASE_CODE) {
        !          1413:                printk(KERN_NOTICE "margi_cs: Card Services release "
        !          1414:                       "does not match!\n");
        !          1415:                return -1;
        !          1416:        }
        !          1417:        register_pccard_driver(&dev_info, &margi_attach, &margi_detach);
        !          1418:        return 0;
        !          1419: }
        !          1420: 
        !          1421: static void __exit exit_margi_cs(void)
        !          1422: {
        !          1423:        DEBUG(0, "margi_cs: unloading\n");
        !          1424:        unregister_pccard_driver(&dev_info);
        !          1425:        while (dev_list != NULL) {
        !          1426:                if (dev_list->state & DEV_CONFIG)
        !          1427:                        margi_release((u_long) dev_list);
        !          1428:                margi_detach(dev_list);
        !          1429:        }
        !          1430: }
        !          1431: 
        !          1432: module_init(init_margi_cs);
        !          1433: module_exit(exit_margi_cs);

LinuxTV legacy CVS <linuxtv.org/cvs>