pnp - ISAPnP Updates (5/12) 2.5.59-bk3
Subsystems (2)
PATCH 1/1 pnp - ISAPnP Updates (5/12) 2.5.59-bk3
Contains many isapnp improvements including true get resource support which is necessary to get active configs on boot and to ensure a resource set was accepted. It also adds some initial MEM32 support, more work in that area will come in the near future.
Please apply,
Adam
drivers/pnp/isapnp/core.c +113 -84
@@ -101,7 +101,6 @@/* some prototypes */ -static int isapnp_config_prepare (struct pnp_dev *dev);extern struct pnp_protocol isapnp_protocol;static inline void write_data (unsigned char x)
@@ -260,7 +259,7 @@* We cannot use NE2000 probe spaces for ISAPnP or we * will lock up machines. */ -if ((rdp <0x280 || rdp >0x380 ) && !check_region (rdp,1 )) +if ((rdp <0x280 || rdp >0x380 ) && !check_region (rdp,1 )) { isapnp_rdp = rdp;return 0 ;
@@ -580,14 +579,18 @@ int depnum, int size) {unsigned char tmp[17 ]; -struct pnp_mem32 *mem32; +struct pnp_mem *mem;isapnp_peek (tmp, size); - mem32 =isapnp_alloc (sizeof (struct pnp_mem32 )); -if (!mem32) + mem =isapnp_alloc (sizeof (struct pnp_mem )); +if (!mem)return ; -memcpy (mem32->data, tmp,17 ); -pnp_add_mem32_resource (dev,depnum,mem32); + mem->min = (tmp[4 ] <<24 ) | (tmp[3 ] <<16 ) | (tmp[2 ] <<8 ) | tmp[1 ]; + mem->max = (tmp[8 ] <<24 ) | (tmp[7 ] <<16 ) | (tmp[6 ] <<8 ) | tmp[5 ]; + mem->align = (tmp[12 ] <<24 ) | (tmp[11 ] <<16 ) | (tmp[10 ] <<8 ) | tmp[9 ]; + mem->size = (tmp[16 ] <<24 ) | (tmp[15 ] <<16 ) | (tmp[14 ] <<8 ) | tmp[13 ]; + mem->flags = tmp[0 ]; +pnp_add_mem_resource (dev,depnum,mem); }/*
@@ -597,15 +600,18 @@static void __init isapnp_add_fixed_mem32_resource (struct pnp_dev *dev,int depnum,int size) { -unsigned char tmp[17 ]; -struct pnp_mem32 *mem32; +unsigned char tmp[9 ]; +struct pnp_mem *mem;isapnp_peek (tmp, size); - mem32 =isapnp_alloc (sizeof (struct pnp_mem32 )); -if (!mem32) + mem =isapnp_alloc (sizeof (struct pnp_mem )); +if (!mem)return ; -memcpy (mem32->data, tmp,17 ); -pnp_add_mem32_resource (dev,depnum,mem32); + mem->min = mem->max = (tmp[4 ] <<24 ) | (tmp[3 ] <<16 ) | (tmp[2 ] <<8 ) | tmp[1 ]; + mem->size = (tmp[8 ] <<24 ) | (tmp[7 ] <<16 ) | (tmp[6 ] <<8 ) | tmp[5 ]; + mem->align =0 ; + mem->flags = tmp[0 ]; +pnp_add_mem_resource (dev,depnum,mem); }/*
@@ -650,7 +656,6 @@switch (type) {case _STAG_LOGDEVID:if (size >=5 && size <=6 ) { -isapnp_config_prepare (dev);if ((dev =isapnp_parse_device (card, size, number++)) ==NULL )return 1 ;pnp_build_resource (dev,0 );
@@ -723,7 +728,7 @@ size =0 ;break ;case _LTAG_ANSISTR: -isapnp_parse_name (dev->name,sizeof (dev->name), &size); +isapnp_parse_name (dev->dev.name,sizeof (dev->dev.name), &size);break ;case _LTAG_UNICODESTR:/* silently ignore */
@@ -738,7 +743,7 @@ size =0 ;break ;case _LTAG_FIXEDMEM32RANGE: -if (size !=17 ) +if (size !=9 ) goto __skip;isapnp_add_fixed_mem32_resource (dev, depnum, size); size =0 ;
@@ -746,7 +751,6 @@case _STAG_END:if (size >0 )isapnp_skip_bytes (size); -isapnp_config_prepare (dev);return 1 ;default :printk (KERN_ERR "isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n" , type, dev->number, card->number);
@@ -755,7 +759,6 @@if (size >0 )isapnp_skip_bytes (size); } -isapnp_config_prepare (dev);return 0 ; }
@@ -790,7 +793,7 @@case _STAG_VENDOR:break ;case _LTAG_ANSISTR: -isapnp_parse_name (card->name,sizeof (card->name), &size); +isapnp_parse_name (card->dev.name,sizeof (card->dev.name), &size);break ;case _LTAG_UNICODESTR:/* silently ignore */
@@ -852,6 +855,64 @@pnpc_add_id (id,card); } + +static int isapnp_parse_current_resources (struct pnp_dev *dev,struct pnp_resource_table * res) +{ +int tmp, ret; +struct pnp_rule_table rule; +if (dev->rule) + rule = *dev->rule; +else { +if (!pnp_generate_rule (dev,1 ,&rule)) +return -EINVAL ; + } + + dev->active =isapnp_read_byte (ISAPNP_CFG_ACTIVATE ); +if (dev->active) { +for (tmp =0 ; tmp <PNP_MAX_PORT ; tmp++) { + ret =isapnp_read_word (ISAPNP_CFG_PORT + (tmp <<1 )); +if (!ret) +continue ; + res->port_resource[tmp].start = ret; +if (rule.port[tmp]) + res->port_resource[tmp].end = ret + rule.port[tmp]->size -1 ; +else + res->port_resource[tmp].end = ret +1 ;/* all we can do is assume 1 :-( */ + res->port_resource[tmp].flags =IORESOURCE_IO ; + } +for (tmp =0 ; tmp <PNP_MAX_MEM ; tmp++) { + ret =isapnp_read_dword (ISAPNP_CFG_MEM + (tmp <<3 )); +if (!ret) +continue ; + res->mem_resource[tmp].start = ret; +if (rule.mem[tmp]) + res->mem_resource[tmp].end = ret + rule.mem[tmp]->size -1 ; +else + res->mem_resource[tmp].end = ret +1 ;/* all we can do is assume 1 :-( */ + res->mem_resource[tmp].flags =IORESOURCE_MEM ; + } +for (tmp =0 ; tmp <PNP_MAX_IRQ ; tmp++) { + ret = (isapnp_read_word (ISAPNP_CFG_IRQ + (tmp <<1 )) >>8 ); +if (!ret) +continue ; + res->irq_resource[tmp].start = res->irq_resource[tmp].end = ret; + res->irq_resource[tmp].flags =IORESOURCE_IRQ ; + } +for (tmp =0 ; tmp <PNP_MAX_DMA ; tmp++) { + ret =isapnp_read_byte (ISAPNP_CFG_DMA + tmp); +pnp_info ("dma %d" , tmp); +if (ret ==4 ) +continue ; +if (rule.dma[tmp]) {/* some isapnp systems forget to set this to 4 so we have to check */ + res->dma_resource[tmp].start = res->dma_resource[tmp].end = ret; + res->dma_resource[tmp].flags =IORESOURCE_DMA ; + } + } + } +return 0 ; +} + +/* * Build device list for all present ISA PnP devices. */
@@ -861,6 +922,7 @@int csn;unsigned char header[9 ], checksum;struct pnp_card *card; +struct pnp_dev *dev;isapnp_wait ();isapnp_key ();
@@ -893,8 +955,17 @@printk (KERN_ERR "isapnp: checksum for device %i is not valid (0x%x)\n" , csn, isapnp_checksum_value); card->checksum = isapnp_checksum_value; card->protocol = &isapnp_protocol; + +/* read the current resource data */ +card_for_each_dev (card,dev) { +isapnp_device (dev->number); +pnp_init_resource_table (&dev->res); +isapnp_parse_current_resources (dev, &dev->res); + } +pnpc_add_card (card); } +isapnp_wait ();return 0 ; }
@@ -948,39 +1019,6 @@return 0 ; } -static int isapnp_config_prepare (struct pnp_dev *dev) -{ -int idx; -if (dev ==NULL ) -return -EINVAL ; -if (dev->active || dev->lock_resources) -return -EBUSY ; -for (idx =0 ; idx <DEVICE_COUNT_IRQ ; idx++) { - dev->irq_resource[idx].name =NULL ; - dev->irq_resource[idx].start =-1 ; - dev->irq_resource[idx].end =-1 ; - dev->irq_resource[idx].flags =IORESOURCE_IRQ |IORESOURCE_UNSET ; - } -for (idx =0 ; idx <DEVICE_COUNT_DMA ; idx++) { - dev->dma_resource[idx].name =NULL ; - dev->dma_resource[idx].start =-1 ; - dev->dma_resource[idx].end =-1 ; - dev->dma_resource[idx].flags =IORESOURCE_DMA |IORESOURCE_UNSET ; - } -for (idx =0 ; idx <DEVICE_COUNT_IO ; idx++) { - dev->io_resource[idx].name =NULL ; - dev->io_resource[idx].start =0 ; - dev->io_resource[idx].end =0 ; - dev->io_resource[idx].flags =IORESOURCE_IO |IORESOURCE_UNSET ; - } -for (idx =0 ; idx <DEVICE_COUNT_MEM ; idx++) { - dev->mem_resource[idx].name =NULL ; - dev->mem_resource[idx].start =0 ; - dev->mem_resource[idx].end =0 ; - dev->mem_resource[idx].flags =IORESOURCE_MEM |IORESOURCE_UNSET ; - } -return 0 ; -}/* * Inititialization.
@@ -999,44 +1037,35 @@EXPORT_SYMBOL (isapnp_wake);EXPORT_SYMBOL (isapnp_device); -static int isapnp_get_resources (struct pnp_dev *dev) +static int isapnp_get_resources (struct pnp_dev *dev,struct pnp_resource_table * res) { -/* We don't need to do anything but this, the rest is taken care of */ -if (pnp_port_valid (dev,0 ) ==0 && -pnp_mem_valid (dev,0 ) ==0 && -pnp_irq_valid (dev,0 ) ==0 && -pnp_dma_valid (dev,0 ) ==0 ) - dev->active =0 ; -else - dev->active =1 ; -return 0 ; +int ret; +pnp_init_resource_table (res); +isapnp_cfg_begin (dev->card->number, dev->number); + ret =isapnp_parse_current_resources (dev, res); +isapnp_cfg_end (); +return ret; } -static int isapnp_set_resources (struct pnp_dev *dev,struct pnp_cfg *cfg) +static int isapnp_set_resources (struct pnp_dev *dev,struct pnp_resource_table * res) {int tmp; -isapnp_cfg_begin (dev->card->number, dev->number); + +isapnp_cfg_begin (dev->card->number, dev->number); dev->active =1 ; - dev->irq_resource[0 ] = cfg->request.irq_resource[0 ]; - dev->irq_resource[1 ] = cfg->request.irq_resource[1 ]; - dev->dma_resource[0 ] = cfg->request.dma_resource[0 ]; - dev->dma_resource[1 ] = cfg->request.dma_resource[1 ]; -for (tmp =0 ; tmp <DEVICE_COUNT_IO ; tmp++) - dev->io_resource[tmp] = cfg->request.io_resource[tmp]; -for (tmp =0 ; tmp <DEVICE_COUNT_MEM ; tmp++) - dev->mem_resource[tmp] = cfg->request.mem_resource[tmp]; -for (tmp =0 ; tmp <8 &&pnp_port_valid (dev, tmp); tmp++) -isapnp_write_word (ISAPNP_CFG_PORT +(tmp<<1 ),pnp_port_start (dev, tmp)); -for (tmp =0 ; tmp <2 &&pnp_irq_valid (dev, tmp); tmp++) { -int irq =pnp_irq (dev, tmp); +for (tmp =0 ; tmp <PNP_MAX_PORT && res->port_resource[tmp].flags &IORESOURCE_IO ; tmp++) +isapnp_write_word (ISAPNP_CFG_PORT +(tmp<<1 ), res->port_resource[tmp].start); +for (tmp =0 ; tmp <PNP_MAX_IRQ && res->irq_resource[tmp].flags &IORESOURCE_IRQ ; tmp++) { +int irq = res->irq_resource[tmp].start;if (irq ==2 ) irq =9 ;isapnp_write_byte (ISAPNP_CFG_IRQ +(tmp<<1 ), irq); } -for (tmp =0 ; tmp <2 &&pnp_dma_valid (dev, tmp); tmp++) -isapnp_write_byte (ISAPNP_CFG_DMA +tmp,pnp_dma (dev, tmp)); -for (tmp =0 ; tmp <4 &&pnp_mem_valid (dev, tmp); tmp++) -isapnp_write_word (ISAPNP_CFG_MEM +(tmp<<2 ), (pnp_mem_start (dev, tmp) >>8 ) &0xffff ); +for (tmp =0 ; tmp <PNP_MAX_DMA && res->dma_resource[tmp].flags &IORESOURCE_DMA ; tmp++) +isapnp_write_byte (ISAPNP_CFG_DMA +tmp, res->dma_resource[tmp].start); +for (tmp =0 ; tmp <PNP_MAX_MEM && res->mem_resource[tmp].flags &IORESOURCE_MEM ; tmp++) +isapnp_write_word (ISAPNP_CFG_MEM +(tmp<<2 ), (res->mem_resource[tmp].start >>8 ) &0xffff ); +/* FIXME: We aren't handling 32bit mems properly here */ isapnp_activate (dev->number);isapnp_cfg_end ();return 0 ;
@@ -1046,7 +1075,7 @@ {if (!dev || !dev->active)return -EINVAL ; -isapnp_cfg_begin (dev->card->number, dev->number); +isapnp_cfg_begin (dev->card->number, dev->number);isapnp_deactivate (dev->number); dev->active =0 ;isapnp_cfg_end ();
@@ -1127,11 +1156,11 @@protocol_for_each_card (&isapnp_protocol,card) { cards++;if (isapnp_verbose) { -printk (KERN_INFO "isapnp: Card '%s'\n" , card->name[0 ]?card->name:"Unknown" ); +printk (KERN_INFO "isapnp: Card '%s'\n" , card->dev.name[0 ]?card->dev.name:"Unknown" );if (isapnp_verbose <2 )continue ; -pnp_card_for_each_dev (card,dev) { -printk (KERN_INFO "isapnp: Device '%s'\n" , dev->name[0 ]?dev->name:"Unknown" ); +card_for_each_dev (card,dev) { +printk (KERN_INFO "isapnp: Device '%s'\n" , dev->dev.name[0 ]?dev->dev.name:"Unknown" ); } } }