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>