cregit-Linux how code gets into the kernel

Release 4.11 drivers/pnp/isapnp/core.c

/*
 *  ISA Plug & Play support
 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
 *
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Changelog:
 *  2000-01-01  Added quirks handling for buggy hardware
 *              Peter Denison <peterd@pnd-pc.demon.co.uk>
 *  2000-06-14  Added isapnp_probe_devs() and isapnp_activate_dev()
 *              Christoph Hellwig <hch@infradead.org>
 *  2001-06-03  Added release_region calls to correspond with
 *              request_region calls when a failure occurs.  Also
 *              added KERN_* constants to printk() calls.
 *  2001-11-07  Added isapnp_{,un}register_driver calls along the lines
 *              of the pci driver interface
 *              Kai Germaschewski <kai.germaschewski@gmx.de>
 *  2002-06-06  Made the use of dma channel 0 configurable
 *              Gerald Teschl <gerald.teschl@univie.ac.at>
 *  2002-10-06  Ported to PnP Layer - Adam Belay <ambx1@neo.rr.com>
 *  2003-08-11  Resource Management Updates - Adam Belay <ambx1@neo.rr.com>
 */

#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/isapnp.h>
#include <linux/mutex.h>
#include <asm/io.h>

#include "../base.h"

#if 0
#define ISAPNP_REGION_OK
#endif


int isapnp_disable;		
/* Disable ISA PnP */

static int isapnp_rdp;		
/* Read Data Port */

static int isapnp_reset = 1;	
/* reset all PnP cards (deactivate) */

static int isapnp_verbose = 1;	
/* verbose mode */

module_param(isapnp_disable, int, 0);
MODULE_PARM_DESC(isapnp_disable, "ISA Plug & Play disable");
module_param(isapnp_rdp, int, 0);
MODULE_PARM_DESC(isapnp_rdp, "ISA Plug & Play read data port");
module_param(isapnp_reset, int, 0);
MODULE_PARM_DESC(isapnp_reset, "ISA Plug & Play reset all cards");
module_param(isapnp_verbose, int, 0);
MODULE_PARM_DESC(isapnp_verbose, "ISA Plug & Play verbose mode");


#define _PIDXR		0x279

#define _PNPWRP		0xa79

/* short tags */

#define _STAG_PNPVERNO		0x01

#define _STAG_LOGDEVID		0x02

#define _STAG_COMPATDEVID	0x03

#define _STAG_IRQ		0x04

#define _STAG_DMA		0x05

#define _STAG_STARTDEP		0x06

#define _STAG_ENDDEP		0x07

#define _STAG_IOPORT		0x08

#define _STAG_FIXEDIO		0x09

#define _STAG_VENDOR		0x0e

#define _STAG_END		0x0f
/* long tags */

#define _LTAG_MEMRANGE		0x81

#define _LTAG_ANSISTR		0x82

#define _LTAG_UNICODESTR	0x83

#define _LTAG_VENDOR		0x84

#define _LTAG_MEM32RANGE	0x85

#define _LTAG_FIXEDMEM32RANGE	0x86

/* Logical device control and configuration registers */


#define ISAPNP_CFG_ACTIVATE	0x30	
/* byte */

#define ISAPNP_CFG_MEM		0x40	
/* 4 * dword */

#define ISAPNP_CFG_PORT		0x60	
/* 8 * word */

#define ISAPNP_CFG_IRQ		0x70	
/* 2 * word */

#define ISAPNP_CFG_DMA		0x74	
/* 2 * byte */

/*
 * Sizes of ISAPNP logical device configuration register sets.
 * See PNP-ISA-v1.0a.pdf, Appendix A.
 */

#define ISAPNP_MAX_MEM		4

#define ISAPNP_MAX_PORT		8

#define ISAPNP_MAX_IRQ		2

#define ISAPNP_MAX_DMA		2


static unsigned char isapnp_checksum_value;
static DEFINE_MUTEX(isapnp_cfg_mutex);

static int isapnp_csn_count;

/* some prototypes */


static inline void write_data(unsigned char x) { outb(x, _PNPWRP); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay1372.22%150.00%
Linus Torvalds (pre-git)527.78%150.00%
Total18100.00%2100.00%


static inline void write_address(unsigned char x) { outb(x, _PIDXR); udelay(20); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay1669.57%125.00%
Linus Torvalds (pre-git)730.43%375.00%
Total23100.00%4100.00%


static inline unsigned char read_data(void) { unsigned char val = inb(isapnp_rdp); return val; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay1881.82%133.33%
Linus Torvalds (pre-git)29.09%133.33%
Robert Love29.09%133.33%
Total22100.00%3100.00%


unsigned char isapnp_read_byte(unsigned char idx) { write_address(idx); return read_data(); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay1578.95%133.33%
Linus Torvalds (pre-git)315.79%133.33%
Robert Love15.26%133.33%
Total19100.00%3100.00%


static unsigned short isapnp_read_word(unsigned char idx) { unsigned short val; val = isapnp_read_byte(idx); val = (val << 8) + isapnp_read_byte(idx + 1); return val; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay3280.00%125.00%
Linus Torvalds (pre-git)512.50%125.00%
Al Viro25.00%125.00%
Adrian Bunk12.50%125.00%
Total40100.00%4100.00%


void isapnp_write_byte(unsigned char idx, unsigned char val) { write_address(idx); write_data(val); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay2086.96%150.00%
Linus Torvalds (pre-git)313.04%150.00%
Total23100.00%2100.00%


static void isapnp_write_word(unsigned char idx, unsigned short val) { isapnp_write_byte(idx, val >> 8); isapnp_write_byte(idx + 1, val); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay2165.62%133.33%
Linus Torvalds (pre-git)1031.25%133.33%
Adrian Bunk13.12%133.33%
Total32100.00%3100.00%


static void isapnp_key(void) { unsigned char code = 0x6a, msb; int i; mdelay(1); write_address(0x00); write_address(0x00); write_address(code); for (i = 1; i < 32; i++) { msb = ((code & 0x01) ^ ((code & 0x02) >> 1)) << 7; code = (code >> 1) | msb; write_address(code); } }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay7784.62%150.00%
Linus Torvalds (pre-git)1415.38%150.00%
Total91100.00%2100.00%

/* place all pnp cards in wait-for-key state */
static void isapnp_wait(void) { isapnp_write_byte(0x02, 0x02); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)853.33%150.00%
Adam Belay746.67%150.00%
Total15100.00%2100.00%


static void isapnp_wake(unsigned char csn) { isapnp_write_byte(0x03, csn); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay1164.71%133.33%
Linus Torvalds (pre-git)529.41%133.33%
Adrian Bunk15.88%133.33%
Total17100.00%3100.00%


static void isapnp_device(unsigned char logdev) { isapnp_write_byte(0x07, logdev); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay847.06%133.33%
Linus Torvalds (pre-git)847.06%133.33%
Adrian Bunk15.88%133.33%
Total17100.00%3100.00%


static void isapnp_activate(unsigned char logdev) { isapnp_device(logdev); isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 1); udelay(250); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay1659.26%133.33%
Linus Torvalds (pre-git)1037.04%133.33%
Adrian Bunk13.70%133.33%
Total27100.00%3100.00%


static void isapnp_deactivate(unsigned char logdev) { isapnp_device(logdev); isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 0); udelay(500); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay1659.26%133.33%
Linus Torvalds (pre-git)1037.04%133.33%
Adrian Bunk13.70%133.33%
Total27100.00%3100.00%


static void __init isapnp_peek(unsigned char *data, int bytes) { int i, j; unsigned char d = 0; for (i = 1; i <= bytes; i++) { for (j = 0; j < 20; j++) { d = isapnp_read_byte(0x05); if (d & 1) break; udelay(100); } if (!(d & 1)) { if (data != NULL) *data++ = 0xff; continue; } d = isapnp_read_byte(0x04); /* PRESDI */ isapnp_checksum_value += d; if (data != NULL) *data++ = d; } }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay8367.48%150.00%
Linus Torvalds (pre-git)4032.52%150.00%
Total123100.00%2100.00%

#define RDP_STEP 32 /* minimum is 4 */
static int isapnp_next_rdp(void) { int rdp = isapnp_rdp; static int old_rdp = 0; if (old_rdp) { release_region(old_rdp, 1); old_rdp = 0; } while (rdp <= 0x3ff) { /* * We cannot use NE2000 probe spaces for ISAPnP or we * will lock up machines. */ if ((rdp < 0x280 || rdp > 0x380) && request_region(rdp, 1, "ISAPnP")) { isapnp_rdp = rdp; old_rdp = rdp; return 0; } rdp += RDP_STEP; } return -1; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay4147.13%120.00%
Alan Cox3034.48%120.00%
Linus Torvalds (pre-git)1517.24%240.00%
Björn Helgaas11.15%120.00%
Total87100.00%5100.00%

/* Set read port address */
static inline void isapnp_set_rdp(void) { isapnp_write_byte(0x00, isapnp_rdp >> 2); udelay(100); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay1565.22%150.00%
Linus Torvalds (pre-git)834.78%150.00%
Total23100.00%2100.00%

/* * Perform an isolation. The port selection code now tries to avoid * "dangerous to read" ports. */
static int __init isapnp_isolate_rdp_select(void) { isapnp_wait(); isapnp_key(); /* Control: reset CSN and conditionally everything else too */ isapnp_write_byte(0x02, isapnp_reset ? 0x05 : 0x04); mdelay(2); isapnp_wait(); isapnp_key(); isapnp_wake(0x00); if (isapnp_next_rdp() < 0) { isapnp_wait(); return -1; } isapnp_set_rdp(); udelay(1000); write_address(0x01); udelay(1000); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay5265.00%133.33%
Linus Torvalds (pre-git)2835.00%266.67%
Total80100.00%3100.00%

/* * Isolate (assign uniqued CSN) to all ISA PnP devices. */
static int __init isapnp_isolate(void) { unsigned char checksum = 0x6a; unsigned char chksum = 0x00; unsigned char bit = 0x00; int data; int csn = 0; int i; int iteration = 1; isapnp_rdp = 0x213; if (isapnp_isolate_rdp_select() < 0) return -1; while (1) { for (i = 1; i <= 64; i++) { data = read_data() << 8; udelay(250); data = data | read_data(); udelay(250); if (data == 0x55aa) bit = 0x01; checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1); bit = 0x00; } for (i = 65; i <= 72; i++) { data = read_data() << 8; udelay(250); data = data | read_data(); udelay(250); if (data == 0x55aa) chksum |= (1 << (i - 65)); } if (checksum != 0x00 && checksum == chksum) { csn++; isapnp_write_byte(0x06, csn); udelay(250); iteration++; isapnp_wake(0x00); isapnp_set_rdp(); udelay(1000); write_address(0x01); udelay(1000); goto __next; } if (iteration == 1) { isapnp_rdp += RDP_STEP; if (isapnp_isolate_rdp_select() < 0) return -1; } else if (iteration > 1) { break; } __next: if (csn == 255) break; checksum = 0x6a; chksum = 0x00; bit = 0x00; } isapnp_wait(); isapnp_csn_count = csn; return csn; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay25378.09%266.67%
Linus Torvalds (pre-git)7121.91%133.33%
Total324100.00%3100.00%

/* * Read one tag from stream. */
static int __init isapnp_read_tag(unsigned char *type, unsigned short *size) { unsigned char tag, tmp[2]; isapnp_peek(&tag, 1); if (tag == 0) /* invalid tag */ return -1; if (tag & 0x80) { /* large item */ *type = tag; isapnp_peek(tmp, 2); *size = (tmp[1] << 8) | tmp[0]; } else { *type = (tag >> 3) & 0x0f; *size = tag & 0x07; } if (*type == 0xff && *size == 0xffff) /* probably invalid data */ return -1; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay10987.90%150.00%
Linus Torvalds (pre-git)1512.10%150.00%
Total124100.00%2100.00%

/* * Skip specified number of bytes from stream. */
static void __init isapnp_skip_bytes(int count) { isapnp_peek(NULL, count); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay1270.59%150.00%
Linus Torvalds (pre-git)529.41%150.00%
Total17100.00%2100.00%

/* * Parse logical device tag. */
static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card, int size, int number) { unsigned char tmp[6]; struct pnp_dev *dev; u32 eisa_id; char id[8]; isapnp_peek(tmp, size); eisa_id = tmp[0] | tmp[1] << 8 | tmp[2] << 16 | tmp[3] << 24; pnp_eisa_id_to_string(eisa_id, id); dev = pnp_alloc_dev(&isapnp_protocol, number, id); if (!dev) return NULL; dev->card = card; dev->capabilities |= PNP_CONFIGURABLE; dev->capabilities |= PNP_READ; dev->capabilities |= PNP_WRITE; dev->capabilities |= PNP_DISABLE; pnp_init_resources(dev); return dev; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay6143.26%337.50%
Björn Helgaas4834.04%337.50%
Jaroslav Kysela2215.60%112.50%
Linus Torvalds (pre-git)107.09%112.50%
Total141100.00%8100.00%

/* * Add IRQ resource to resources list. */
static void __init isapnp_parse_irq_resource(struct pnp_dev *dev, unsigned int option_flags, int size) { unsigned char tmp[3]; unsigned long bits; pnp_irq_mask_t map; unsigned char flags = IORESOURCE_IRQ_HIGHEDGE; isapnp_peek(tmp, size); bits = (tmp[1] << 8) | tmp[0]; bitmap_zero(map.bits, PNP_IRQ_NR); bitmap_copy(map.bits, &bits, 16); if (size > 2) flags = tmp[2]; pnp_register_irq_resource(dev, option_flags, &map, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay3532.41%222.22%
Björn Helgaas3431.48%444.44%
Linus Torvalds (pre-git)2422.22%222.22%
Len Brown1513.89%111.11%
Total108100.00%9100.00%

/* * Add DMA resource to resources list. */
static void __init isapnp_parse_dma_resource(struct pnp_dev *dev, unsigned int option_flags, int size) { unsigned char tmp[2]; isapnp_peek(tmp, size); pnp_register_dma_resource(dev, option_flags, tmp[0], tmp[1]); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay2448.00%228.57%
Linus Torvalds (pre-git)1326.00%114.29%
Björn Helgaas1326.00%457.14%
Total50100.00%7100.00%

/* * Add port resource to resources list. */
static void __init isapnp_parse_port_resource(struct pnp_dev *dev, unsigned int option_flags, int size) { unsigned char tmp[7]; resource_size_t min, max, align, len; unsigned char flags; isapnp_peek(tmp, size); min = (tmp[2] << 8) | tmp[1]; max = (tmp[4] << 8) | tmp[3]; align = tmp[5]; len = tmp[6]; flags = tmp[0] ? IORESOURCE_IO_16BIT_ADDR : 0; pnp_register_port_resource(dev, option_flags, min, max, align, len, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay6352.50%228.57%
Björn Helgaas3327.50%457.14%
Linus Torvalds (pre-git)2420.00%114.29%
Total120100.00%7100.00%

/* * Add fixed port resource to resources list. */
static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev, unsigned int option_flags, int size) { unsigned char tmp[3]; resource_size_t base, len; isapnp_peek(tmp, size); base = (tmp[1] << 8) | tmp[0]; len = tmp[2]; pnp_register_port_resource(dev, option_flags, base, base, 0, len, IORESOURCE_IO_FIXED); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay2835.90%233.33%
Linus Torvalds (pre-git)2532.05%116.67%
Björn Helgaas2532.05%350.00%
Total78100.00%6100.00%

/* * Add memory resource to resources list. */
static void __init isapnp_parse_mem_resource(struct pnp_dev *dev, unsigned int option_flags, int size) { unsigned char tmp[9]; resource_size_t min, max, align, len; unsigned char flags; isapnp_peek(tmp, size); min = ((tmp[2] << 8) | tmp[1]) << 8; max = ((tmp[4] << 8) | tmp[3]) << 8; align = (tmp[6] << 8) | tmp[5]; len = ((tmp[8] << 8) | tmp[7]) << 8; flags = tmp[0]; pnp_register_mem_resource(dev, option_flags, min, max, align, len, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay8759.59%233.33%
Björn Helgaas3221.92%350.00%
Linus Torvalds (pre-git)2718.49%116.67%
Total146100.00%6100.00%

/* * Add 32-bit memory resource to resources list. */
static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev, unsigned int option_flags, int size) { unsigned char tmp[17]; resource_size_t min, max, align, len; unsigned char flags; isapnp_peek(tmp, size); min = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; max = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5]; align = (tmp[12] << 24) | (tmp[11] << 16) | (tmp[10] << 8) | tmp[9]; len = (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13]; flags = tmp[0]; pnp_register_mem_resource(dev, option_flags, min, max, align, len, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay16479.61%342.86%
Björn Helgaas3215.53%342.86%
Linus Torvalds (pre-git)104.85%114.29%
Total206100.00%7100.00%

/* * Add 32-bit fixed memory resource to resources list. */
static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev, unsigned int option_flags, int size) { unsigned char tmp[9]; resource_size_t base, len; unsigned char flags; isapnp_peek(tmp, size); base = (tmp[4] << 24) | (tmp[3] << 16) | (tmp[2] << 8) | tmp[1]; len = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5]; flags = tmp[0]; pnp_register_mem_resource(dev, option_flags, base, base, 0, len, flags); }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay10376.87%342.86%
Björn Helgaas2921.64%342.86%
Linus Torvalds (pre-git)21.49%114.29%
Total134100.00%7100.00%

/* * Parse card name for ISA PnP device. */
static void __init isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size) { if (name[0] == '\0') { unsigned short size1 = *size >= name_max ? (name_max - 1) : *size; isapnp_peek(name, size1); name[size1] = '\0'; *size -= size1; /* clean whitespace from end of string */ while (size1 > 0 && name[--size1] == ' ') name[size1] = '\0'; } }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay8493.33%266.67%
Linus Torvalds (pre-git)66.67%133.33%
Total90100.00%3100.00%

/* * Parse resource map for logical device. */
static int __init isapnp_create_device(struct pnp_card *card, unsigned short size) { int number = 0, skip = 0, priority, compat = 0; unsigned char type, tmp[17]; unsigned int option_flags; struct pnp_dev *dev; u32 eisa_id; char id[8]; if ((dev = isapnp_parse_device(card, size, number++)) == NULL) return 1; option_flags = 0; pnp_add_card_device(card, dev); while (1) { if (isapnp_read_tag(&type, &size) < 0) return 1; if (skip && type != _STAG_LOGDEVID && type != _STAG_END) goto __skip; switch (type) { case _STAG_LOGDEVID: if (size >= 5 && size <= 6) { if ((dev = isapnp_parse_device(card, size, number++)) == NULL) return 1; size = 0; skip = 0; option_flags = 0; pnp_add_card_device(card, dev); } else { skip = 1; } compat = 0; break; case _STAG_COMPATDEVID: if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) { isapnp_peek(tmp, 4); eisa_id = tmp[0] | tmp[1] << 8 | tmp[2] << 16 | tmp[3] << 24; pnp_eisa_id_to_string(eisa_id, id); pnp_add_id(dev, id); compat++; size = 0; } break; case _STAG_IRQ: if (size < 2 || size > 3) goto __skip; isapnp_parse_irq_resource(dev, option_flags, size); size = 0; break; case _STAG_DMA: if (size != 2) goto __skip; isapnp_parse_dma_resource(dev, option_flags, size); size = 0; break; case _STAG_STARTDEP: if (size > 1) goto __skip; priority = PNP_RES_PRIORITY_ACCEPTABLE; if (size > 0) { isapnp_peek(tmp, size); priority = tmp[0]; size = 0; } option_flags = pnp_new_dependent_set(dev, priority); break; case _STAG_ENDDEP: if (size != 0) goto __skip; option_flags = 0; break; case _STAG_IOPORT: if (size != 7) goto __skip; isapnp_parse_port_resource(dev, option_flags, size); size = 0; break; case _STAG_FIXEDIO: if (size != 3) goto __skip; isapnp_parse_fixed_port_resource(dev, option_flags, size); size = 0; break; case _STAG_VENDOR: break; case _LTAG_MEMRANGE: if (size != 9) goto __skip; isapnp_parse_mem_resource(dev, option_flags, size); size = 0; break; case _LTAG_ANSISTR: isapnp_parse_name(dev->name, sizeof(dev->name), &size); break; case _LTAG_UNICODESTR: /* silently ignore */ /* who use unicode for hardware identification? */ break; case _LTAG_VENDOR: break; case _LTAG_MEM32RANGE: if (size != 17) goto __skip; isapnp_parse_mem32_resource(dev, option_flags, size); size = 0; break; case _LTAG_FIXEDMEM32RANGE: if (size != 9) goto __skip; isapnp_parse_fixed_mem32_resource(dev, option_flags, size); size = 0; break; case _STAG_END: if (size > 0) isapnp_skip_bytes(size); return 1; default: dev_err(&dev->dev, "unknown tag %#x (card %i), " "ignored\n", type, card->number); } __skip: if (size > 0) isapnp_skip_bytes(size); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay43771.29%533.33%
Linus Torvalds (pre-git)9615.66%213.33%
Björn Helgaas7712.56%533.33%
Jesper Juhl10.16%16.67%
Dave Jones10.16%16.67%
Jaroslav Kysela10.16%16.67%
Total613100.00%15100.00%

/* * Parse resource map for ISA PnP card. */
static void __init isapnp_parse_resource_map(struct pnp_card *card) { unsigned char type, tmp[17]; unsigned short size; while (1) { if (isapnp_read_tag(&type, &size) < 0) return; switch (type) { case _STAG_PNPVERNO: if (size != 2) goto __skip; isapnp_peek(tmp, 2); card->pnpver = tmp[0]; card->productver = tmp[1]; size = 0; break; case _STAG_LOGDEVID: if (size >= 5 && size <= 6) { if (isapnp_create_device(card, size) == 1) return; size = 0; } break; case _STAG_VENDOR: break; case _LTAG_ANSISTR: isapnp_parse_name(card->name, sizeof(card->name), &size); break; case _LTAG_UNICODESTR: /* silently ignore */ /* who use unicode for hardware identification? */ break; case _LTAG_VENDOR: break; case _STAG_END: if (size > 0) isapnp_skip_bytes(size); return; default: dev_err(&card->dev, "unknown tag %#x, ignored\n", type); } __skip: if (size > 0) isapnp_skip_bytes(size); } }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay16280.60%125.00%
Linus Torvalds (pre-git)3215.92%250.00%
Björn Helgaas73.48%125.00%
Total201100.00%4100.00%

/* * Compute ISA PnP checksum for first eight bytes. */
static unsigned char __init isapnp_checksum(unsigned char *data) { int i, j; unsigned char checksum = 0x6a, bit, b; for (i = 0; i < 8; i++) { b = data[i]; for (j = 0; j < 8; j++) { bit = 0; if (b & (1 << j)) bit = 1; checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1); } } return checksum; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay9077.59%150.00%
Linus Torvalds (pre-git)2622.41%150.00%
Total116100.00%2100.00%

/* * Build device list for all present ISA PnP devices. */
static int __init isapnp_build_device_list(void) { int csn; unsigned char header[9], checksum; struct pnp_card *card; u32 eisa_id; char id[8]; isapnp_wait(); isapnp_key(); for (csn = 1; csn <= isapnp_csn_count; csn++) { isapnp_wake(csn); isapnp_peek(header, 9); checksum = isapnp_checksum(header); eisa_id = header[0] | header[1] << 8 | header[2] << 16 | header[3] << 24; pnp_eisa_id_to_string(eisa_id, id); card = pnp_alloc_card(&isapnp_protocol, csn, id); if (!card) continue; INIT_LIST_HEAD(&card->devices); card->serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | header[4]; isapnp_checksum_value = 0x00; isapnp_parse_resource_map(card); if (isapnp_checksum_value != 0x00) dev_err(&card->dev, "invalid checksum %#x\n", isapnp_checksum_value); card->checksum = isapnp_checksum_value; pnp_add_card(card); } isapnp_wait(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay12658.33%555.56%
Björn Helgaas5927.31%333.33%
Linus Torvalds (pre-git)3114.35%111.11%
Total216100.00%9100.00%

/* * Basic configuration routines. */
int isapnp_present(void) { struct pnp_card *card; pnp_for_each_card(card) { if (card->protocol == &isapnp_protocol) return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay2369.70%250.00%
Jaroslav Kysela515.15%125.00%
Linus Torvalds (pre-git)515.15%125.00%
Total33100.00%4100.00%


int isapnp_cfg_begin(int csn, int logdev) { if (csn < 1 || csn > isapnp_csn_count || logdev > 10) return -EINVAL; mutex_lock(&isapnp_cfg_mutex); isapnp_wait(); isapnp_key(); isapnp_wake(csn); #if 0 /* to avoid malfunction when the isapnptools package is used */ /* we must set RDP to our value again */ /* it is possible to set RDP only in the isolation phase */ /* Jens Thoms Toerring <Jens.Toerring@physik.fu-berlin.de> */ isapnp_write_byte(0x02, 0x04); /* clear CSN of card */ mdelay(2); /* is this necessary? */ isapnp_wake(csn); /* bring card into sleep state */ isapnp_wake(0); /* bring card into isolation state */ isapnp_set_rdp(); /* reset the RDP port */ udelay(1000); /* delay 1000us */ isapnp_write_byte(0x06, csn); /* reset CSN to previous value */ udelay(250); /* is this necessary? */ #endif if (logdev >= 0) isapnp_device(logdev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay8296.47%466.67%
Linus Torvalds22.35%116.67%
Ingo Molnar11.18%116.67%
Total85100.00%6100.00%


int isapnp_cfg_end(void) { isapnp_wait(); mutex_unlock(&isapnp_cfg_mutex); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay1789.47%250.00%
Ingo Molnar15.26%125.00%
Linus Torvalds (pre-git)15.26%125.00%
Total19100.00%4100.00%

/* * Initialization. */ EXPORT_SYMBOL(isapnp_protocol); EXPORT_SYMBOL(isapnp_present); EXPORT_SYMBOL(isapnp_cfg_begin); EXPORT_SYMBOL(isapnp_cfg_end); EXPORT_SYMBOL(isapnp_write_byte);
static int isapnp_get_resources(struct pnp_dev *dev) { int i, ret; pnp_dbg(&dev->dev, "get resources\n"); pnp_init_resources(dev); isapnp_cfg_begin(dev->card->number, dev->number); dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE); if (!dev->active) goto __end; for (i = 0; i < ISAPNP_MAX_PORT; i++) { ret = isapnp_read_word(ISAPNP_CFG_PORT + (i << 1)); pnp_add_io_resource(dev, ret, ret, ret == 0 ? IORESOURCE_DISABLED : 0); } for (i = 0; i < ISAPNP_MAX_MEM; i++) { ret = isapnp_read_word(ISAPNP_CFG_MEM + (i << 3)) << 8; pnp_add_mem_resource(dev, ret, ret, ret == 0 ? IORESOURCE_DISABLED : 0); } for (i = 0; i < ISAPNP_MAX_IRQ; i++) { ret = isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1)) >> 8; pnp_add_irq_resource(dev, ret, ret == 0 ? IORESOURCE_DISABLED : 0); } for (i = 0; i < ISAPNP_MAX_DMA; i++) { ret = isapnp_read_byte(ISAPNP_CFG_DMA + i); pnp_add_dma_resource(dev, ret, ret == 4 ? IORESOURCE_DISABLED : 0); } __end: isapnp_cfg_end(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Björn Helgaas12651.01%1066.67%
Adam Belay11345.75%213.33%
Jaroslav Kysela41.62%213.33%
Linus Torvalds (pre-git)41.62%16.67%
Total247100.00%15100.00%


static int isapnp_set_resources(struct pnp_dev *dev) { struct resource *res; int tmp; pnp_dbg(&dev->dev, "set resources\n"); isapnp_cfg_begin(dev->card->number, dev->number); dev->active = 1; for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) { res = pnp_get_resource(dev, IORESOURCE_IO, tmp); if (pnp_resource_enabled(res)) { pnp_dbg(&dev->dev, " set io %d to %#llx\n", tmp, (unsigned long long) res->start); isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1), res->start); } } for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) { res = pnp_get_resource(dev, IORESOURCE_IRQ, tmp); if (pnp_resource_enabled(res)) { int irq = res->start; if (irq == 2) irq = 9; pnp_dbg(&dev->dev, " set irq %d to %d\n", tmp, irq); isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq); } } for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) { res = pnp_get_resource(dev, IORESOURCE_DMA, tmp); if (pnp_resource_enabled(res)) { pnp_dbg(&dev->dev, " set dma %d to %lld\n", tmp, (unsigned long long) res->start); isapnp_write_byte(ISAPNP_CFG_DMA + tmp, res->start); } } for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) { res = pnp_get_resource(dev, IORESOURCE_MEM, tmp); if (pnp_resource_enabled(res)) { pnp_dbg(&dev->dev, " set mem %d to %#llx\n", tmp, (unsigned long long) res->start); isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3), (res->start >> 8) & 0xffff); } } /* FIXME: We aren't handling 32bit mems properly here */ isapnp_activate(dev->number); isapnp_cfg_end(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Björn Helgaas18551.97%758.33%
Adam Belay14239.89%325.00%
Linus Torvalds (pre-git)298.15%216.67%
Total356100.00%12100.00%


static int isapnp_disable_resources(struct pnp_dev *dev) { if (!dev->active) return -EINVAL; isapnp_cfg_begin(dev->card->number, dev->number); isapnp_deactivate(dev->number); dev->active = 0; isapnp_cfg_end(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay3666.67%150.00%
Linus Torvalds (pre-git)1833.33%150.00%
Total54100.00%2100.00%

struct pnp_protocol isapnp_protocol = { .name = "ISA Plug and Play", .get = isapnp_get_resources, .set = isapnp_set_resources, .disable = isapnp_disable_resources, };
static int __init isapnp_init(void) { int cards; struct pnp_card *card; struct pnp_dev *dev; if (isapnp_disable) { printk(KERN_INFO "isapnp: ISA Plug & Play support disabled\n"); return 0; } #ifdef CONFIG_PPC if (check_legacy_ioport(_PIDXR) || check_legacy_ioport(_PNPWRP)) return -EINVAL; #endif #ifdef ISAPNP_REGION_OK if (!request_region(_PIDXR, 1, "isapnp index")) { printk(KERN_ERR "isapnp: Index Register 0x%x already used\n", _PIDXR); return -EBUSY; } #endif if (!request_region(_PNPWRP, 1, "isapnp write")) { printk(KERN_ERR "isapnp: Write Data Register 0x%x already used\n", _PNPWRP); #ifdef ISAPNP_REGION_OK release_region(_PIDXR, 1); #endif return -EBUSY; } if (pnp_register_protocol(&isapnp_protocol) < 0) return -EBUSY; /* * Print a message. The existing ISAPnP code is hanging machines * so let the user know where. */ printk(KERN_INFO "isapnp: Scanning for PnP cards...\n"); if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff) { isapnp_rdp |= 3; if (!request_region(isapnp_rdp, 1, "isapnp read")) { printk(KERN_ERR "isapnp: Read Data Register 0x%x already used\n", isapnp_rdp); #ifdef ISAPNP_REGION_OK release_region(_PIDXR, 1); #endif release_region(_PNPWRP, 1); return -EBUSY; } isapnp_set_rdp(); } if (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff) { cards = isapnp_isolate(); if (cards < 0 || (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff)) { #ifdef ISAPNP_REGION_OK release_region(_PIDXR, 1); #endif release_region(_PNPWRP, 1); printk(KERN_INFO "isapnp: No Plug & Play device found\n"); return 0; } request_region(isapnp_rdp, 1, "isapnp read"); } isapnp_build_device_list(); cards = 0; protocol_for_each_card(&isapnp_protocol, card) { cards++; if (isapnp_verbose) { dev_info(&card->dev, "card '%s'\n", card->name[0] ? card->name : "unknown"); if (isapnp_verbose < 2) continue; card_for_each_dev(card, dev) { dev_info(&card->dev, "device '%s'\n", dev->name[0] ? dev->name : "unknown"); } } } if (cards) printk(KERN_INFO "isapnp: %i Plug & Play card%s detected total\n", cards, cards > 1 ? "s" : ""); else printk(KERN_INFO "isapnp: No Plug & Play card found\n"); isapnp_proc_init(); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay23357.96%325.00%
Linus Torvalds (pre-git)11027.36%18.33%
David Woodhouse204.98%18.33%
Björn Helgaas174.23%216.67%
Jaroslav Kysela112.74%216.67%
Dave Jones92.24%18.33%
Adrian Bunk10.25%18.33%
Kumar Gala10.25%18.33%
Total402100.00%12100.00%

device_initcall(isapnp_init); /* format is: noisapnp */
static int __init isapnp_setup_disable(char *str) { isapnp_disable = 1; return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay1161.11%150.00%
Linus Torvalds (pre-git)738.89%150.00%
Total18100.00%2100.00%

__setup("noisapnp", isapnp_setup_disable); /* format is: isapnp=rdp,reset,skip_pci_scan,verbose */
static int __init isapnp_setup_isapnp(char *str) { (void)((get_option(&str, &isapnp_rdp) == 2) && (get_option(&str, &isapnp_reset) == 2) && (get_option(&str, &isapnp_verbose) == 2)); return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Adam Belay5086.21%150.00%
Linus Torvalds (pre-git)813.79%150.00%
Total58100.00%2100.00%

__setup("isapnp=", isapnp_setup_isapnp);

Overall Contributors

PersonTokensPropCommitsCommitProp
Adam Belay323464.71%710.45%
Linus Torvalds (pre-git)82516.51%710.45%
Björn Helgaas76515.31%3044.78%
Jaroslav Kysela470.94%68.96%
Alan Cox300.60%11.49%
David Woodhouse200.40%11.49%
Jan Dittmer160.32%11.49%
Len Brown150.30%11.49%
Adrian Bunk100.20%11.49%
Dave Jones100.20%22.99%
Art Haas80.16%11.49%
Ingo Molnar60.12%11.49%
Robert Love30.06%11.49%
Al Viro20.04%11.49%
Linus Torvalds20.04%11.49%
Jesper Juhl10.02%11.49%
Paul Gortmaker10.02%11.49%
Kumar Gala10.02%11.49%
David S. Miller10.02%11.49%
Ivan Kokshaysky10.02%11.49%
Total4998100.00%67100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.