mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
Merge branch 'fixes' into for-linus
Conflicts: arch/arm/mach-versatile/core.c
This commit is contained in:
commit
2502991560
4009 changed files with 236373 additions and 124037 deletions
|
|
@ -350,7 +350,7 @@ config STALDRV
|
|||
|
||||
config STALLION
|
||||
tristate "Stallion EasyIO or EC8/32 support"
|
||||
depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI)
|
||||
depends on STALDRV && (ISA || EISA || PCI)
|
||||
help
|
||||
If you have an EasyIO or EasyConnection 8/32 multiport Stallion
|
||||
card, then this is for you; say Y. Make sure to read
|
||||
|
|
@ -361,7 +361,7 @@ config STALLION
|
|||
|
||||
config ISTALLION
|
||||
tristate "Stallion EC8/64, ONboard, Brumby support"
|
||||
depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI)
|
||||
depends on STALDRV && (ISA || EISA || PCI)
|
||||
help
|
||||
If you have an EasyConnection 8/64, ONboard, Brumby or Stallion
|
||||
serial multiport card, say Y here. Make sure to read
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#
|
||||
FONTMAPFILE = cp437.uni
|
||||
|
||||
obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o
|
||||
obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o
|
||||
|
||||
obj-$(CONFIG_LEGACY_PTYS) += pty.o
|
||||
obj-$(CONFIG_UNIX98_PTYS) += pty.o
|
||||
|
|
|
|||
|
|
@ -116,7 +116,9 @@ struct agp_bridge_driver {
|
|||
struct agp_memory *(*alloc_by_type) (size_t, int);
|
||||
void (*free_by_type)(struct agp_memory *);
|
||||
void *(*agp_alloc_page)(struct agp_bridge_data *);
|
||||
int (*agp_alloc_pages)(struct agp_bridge_data *, struct agp_memory *, size_t);
|
||||
void (*agp_destroy_page)(void *, int flags);
|
||||
void (*agp_destroy_pages)(struct agp_memory *);
|
||||
int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
|
||||
void (*chipset_flush)(struct agp_bridge_data *);
|
||||
};
|
||||
|
|
@ -277,7 +279,10 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type);
|
|||
struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type);
|
||||
void agp_generic_free_by_type(struct agp_memory *curr);
|
||||
void *agp_generic_alloc_page(struct agp_bridge_data *bridge);
|
||||
int agp_generic_alloc_pages(struct agp_bridge_data *agp_bridge,
|
||||
struct agp_memory *memory, size_t page_count);
|
||||
void agp_generic_destroy_page(void *addr, int flags);
|
||||
void agp_generic_destroy_pages(struct agp_memory *memory);
|
||||
void agp_free_key(int key);
|
||||
int agp_num_entries(void);
|
||||
u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 mode, u32 command);
|
||||
|
|
|
|||
|
|
@ -143,7 +143,9 @@ struct agp_bridge_driver alpha_core_agp_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -386,7 +386,9 @@ static const struct agp_bridge_driver amd_irongate_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -224,7 +224,9 @@ static const struct agp_bridge_driver amd_8151_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -418,7 +418,9 @@ static const struct agp_bridge_driver ati_generic_bridge = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -335,7 +335,9 @@ static const struct agp_bridge_driver efficeon_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -201,14 +201,22 @@ void agp_free_memory(struct agp_memory *curr)
|
|||
return;
|
||||
}
|
||||
if (curr->page_count != 0) {
|
||||
for (i = 0; i < curr->page_count; i++) {
|
||||
curr->memory[i] = (unsigned long)gart_to_virt(curr->memory[i]);
|
||||
curr->bridge->driver->agp_destroy_page((void *)curr->memory[i],
|
||||
AGP_PAGE_DESTROY_UNMAP);
|
||||
}
|
||||
for (i = 0; i < curr->page_count; i++) {
|
||||
curr->bridge->driver->agp_destroy_page((void *)curr->memory[i],
|
||||
AGP_PAGE_DESTROY_FREE);
|
||||
if (curr->bridge->driver->agp_destroy_pages) {
|
||||
curr->bridge->driver->agp_destroy_pages(curr);
|
||||
} else {
|
||||
|
||||
for (i = 0; i < curr->page_count; i++) {
|
||||
curr->memory[i] = (unsigned long)gart_to_virt(
|
||||
curr->memory[i]);
|
||||
curr->bridge->driver->agp_destroy_page(
|
||||
(void *)curr->memory[i],
|
||||
AGP_PAGE_DESTROY_UNMAP);
|
||||
}
|
||||
for (i = 0; i < curr->page_count; i++) {
|
||||
curr->bridge->driver->agp_destroy_page(
|
||||
(void *)curr->memory[i],
|
||||
AGP_PAGE_DESTROY_FREE);
|
||||
}
|
||||
}
|
||||
}
|
||||
agp_free_key(curr->key);
|
||||
|
|
@ -264,6 +272,15 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
|
|||
if (new == NULL)
|
||||
return NULL;
|
||||
|
||||
if (bridge->driver->agp_alloc_pages) {
|
||||
if (bridge->driver->agp_alloc_pages(bridge, new, page_count)) {
|
||||
agp_free_memory(new);
|
||||
return NULL;
|
||||
}
|
||||
new->bridge = bridge;
|
||||
return new;
|
||||
}
|
||||
|
||||
for (i = 0; i < page_count; i++) {
|
||||
void *addr = bridge->driver->agp_alloc_page(bridge);
|
||||
|
||||
|
|
@ -1203,6 +1220,39 @@ EXPORT_SYMBOL(agp_generic_alloc_user);
|
|||
* against a maximum value.
|
||||
*/
|
||||
|
||||
int agp_generic_alloc_pages(struct agp_bridge_data *bridge, struct agp_memory *mem, size_t num_pages)
|
||||
{
|
||||
struct page * page;
|
||||
int i, ret = -ENOMEM;
|
||||
|
||||
for (i = 0; i < num_pages; i++) {
|
||||
page = alloc_page(GFP_KERNEL | GFP_DMA32);
|
||||
/* agp_free_memory() needs gart address */
|
||||
if (page == NULL)
|
||||
goto out;
|
||||
|
||||
#ifndef CONFIG_X86
|
||||
map_page_into_agp(page);
|
||||
#endif
|
||||
get_page(page);
|
||||
atomic_inc(&agp_bridge->current_memory_agp);
|
||||
|
||||
/* set_memory_array_uc() needs virtual address */
|
||||
mem->memory[i] = (unsigned long)page_address(page);
|
||||
mem->page_count++;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
set_memory_array_uc(mem->memory, num_pages);
|
||||
#endif
|
||||
ret = 0;
|
||||
out:
|
||||
for (i = 0; i < mem->page_count; i++)
|
||||
mem->memory[i] = virt_to_gart((void *)mem->memory[i]);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(agp_generic_alloc_pages);
|
||||
|
||||
void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
|
||||
{
|
||||
struct page * page;
|
||||
|
|
@ -1219,6 +1269,37 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
|
|||
}
|
||||
EXPORT_SYMBOL(agp_generic_alloc_page);
|
||||
|
||||
void agp_generic_destroy_pages(struct agp_memory *mem)
|
||||
{
|
||||
int i;
|
||||
void *addr;
|
||||
struct page *page;
|
||||
|
||||
if (!mem)
|
||||
return;
|
||||
|
||||
for (i = 0; i < mem->page_count; i++)
|
||||
mem->memory[i] = (unsigned long)gart_to_virt(mem->memory[i]);
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
set_memory_array_wb(mem->memory, mem->page_count);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < mem->page_count; i++) {
|
||||
addr = (void *)mem->memory[i];
|
||||
page = virt_to_page(addr);
|
||||
|
||||
#ifndef CONFIG_X86
|
||||
unmap_page_from_agp(page);
|
||||
#endif
|
||||
|
||||
put_page(page);
|
||||
free_page((unsigned long)addr);
|
||||
atomic_dec(&agp_bridge->current_memory_agp);
|
||||
mem->memory[i] = 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(agp_generic_destroy_pages);
|
||||
|
||||
void agp_generic_destroy_page(void *addr, int flags)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -435,7 +435,9 @@ const struct agp_bridge_driver hp_zx1_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
.cant_use_aperture = true,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -575,7 +575,9 @@ const struct agp_bridge_driver intel_i460_driver = {
|
|||
.insert_memory = i460_insert_memory_small_io_page,
|
||||
.remove_memory = i460_remove_memory_small_io_page,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
#endif
|
||||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
|
|
|
|||
|
|
@ -1711,7 +1711,9 @@ static const struct agp_bridge_driver intel_generic_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
@ -1736,7 +1738,9 @@ static const struct agp_bridge_driver intel_810_driver = {
|
|||
.alloc_by_type = intel_i810_alloc_by_type,
|
||||
.free_by_type = intel_i810_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
@ -1760,7 +1764,9 @@ static const struct agp_bridge_driver intel_815_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
@ -1785,7 +1791,9 @@ static const struct agp_bridge_driver intel_830_driver = {
|
|||
.alloc_by_type = intel_i830_alloc_by_type,
|
||||
.free_by_type = intel_i810_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = intel_i830_type_to_mask_type,
|
||||
.chipset_flush = intel_i830_chipset_flush,
|
||||
};
|
||||
|
|
@ -1810,7 +1818,9 @@ static const struct agp_bridge_driver intel_820_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
@ -1834,7 +1844,9 @@ static const struct agp_bridge_driver intel_830mp_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
@ -1858,7 +1870,9 @@ static const struct agp_bridge_driver intel_840_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
@ -1882,7 +1896,9 @@ static const struct agp_bridge_driver intel_845_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
.chipset_flush = intel_i830_chipset_flush,
|
||||
};
|
||||
|
|
@ -1907,7 +1923,9 @@ static const struct agp_bridge_driver intel_850_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
@ -1931,7 +1949,9 @@ static const struct agp_bridge_driver intel_860_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
@ -1956,7 +1976,9 @@ static const struct agp_bridge_driver intel_915_driver = {
|
|||
.alloc_by_type = intel_i830_alloc_by_type,
|
||||
.free_by_type = intel_i810_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = intel_i830_type_to_mask_type,
|
||||
.chipset_flush = intel_i915_chipset_flush,
|
||||
};
|
||||
|
|
@ -1982,7 +2004,9 @@ static const struct agp_bridge_driver intel_i965_driver = {
|
|||
.alloc_by_type = intel_i830_alloc_by_type,
|
||||
.free_by_type = intel_i810_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = intel_i830_type_to_mask_type,
|
||||
.chipset_flush = intel_i915_chipset_flush,
|
||||
};
|
||||
|
|
@ -2007,7 +2031,9 @@ static const struct agp_bridge_driver intel_7505_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
@ -2032,7 +2058,9 @@ static const struct agp_bridge_driver intel_g33_driver = {
|
|||
.alloc_by_type = intel_i830_alloc_by_type,
|
||||
.free_by_type = intel_i810_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = intel_i830_type_to_mask_type,
|
||||
.chipset_flush = intel_i915_chipset_flush,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -312,7 +312,9 @@ static const struct agp_bridge_driver nvidia_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -224,7 +224,9 @@ static const struct agp_bridge_driver parisc_agp_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
.cant_use_aperture = true,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -140,7 +140,9 @@ static struct agp_bridge_driver sis_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -437,7 +437,9 @@ static const struct agp_bridge_driver sworks_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -509,7 +509,9 @@ const struct agp_bridge_driver uninorth_agp_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
.cant_use_aperture = true,
|
||||
};
|
||||
|
|
@ -534,7 +536,9 @@ const struct agp_bridge_driver u3_agp_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
.cant_use_aperture = true,
|
||||
.needs_scratch_page = true,
|
||||
|
|
|
|||
|
|
@ -190,7 +190,9 @@ static const struct agp_bridge_driver via_agp3_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
@ -214,7 +216,9 @@ static const struct agp_bridge_driver via_driver = {
|
|||
.alloc_by_type = agp_generic_alloc_by_type,
|
||||
.free_by_type = agp_generic_free_by_type,
|
||||
.agp_alloc_page = agp_generic_alloc_page,
|
||||
.agp_alloc_pages = agp_generic_alloc_pages,
|
||||
.agp_destroy_page = agp_generic_destroy_page,
|
||||
.agp_destroy_pages = agp_generic_destroy_pages,
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -837,9 +837,6 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch)
|
|||
struct async_struct *info;
|
||||
unsigned long flags;
|
||||
|
||||
if (!tty)
|
||||
return 0;
|
||||
|
||||
info = tty->driver_data;
|
||||
|
||||
if (serial_paranoia_check(info, tty->name, "rs_put_char"))
|
||||
|
|
@ -892,9 +889,6 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count
|
|||
struct async_struct *info;
|
||||
unsigned long flags;
|
||||
|
||||
if (!tty)
|
||||
return 0;
|
||||
|
||||
info = tty->driver_data;
|
||||
|
||||
if (serial_paranoia_check(info, tty->name, "rs_write"))
|
||||
|
|
|
|||
|
|
@ -712,8 +712,7 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
|
|||
|
||||
IndexCard = adgl->num_card-1;
|
||||
|
||||
if(cmd != 0 && cmd != 6 &&
|
||||
((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) {
|
||||
if(cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) {
|
||||
static int warncount = 10;
|
||||
if (warncount) {
|
||||
printk( KERN_WARNING "APPLICOM driver IOCTL, bad board number %d\n",(int)IndexCard+1);
|
||||
|
|
@ -832,8 +831,7 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
|
|||
}
|
||||
break;
|
||||
default:
|
||||
printk(KERN_INFO "APPLICOM driver ioctl, unknown function code %d\n",cmd) ;
|
||||
ret = -EINVAL;
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
Dummy = readb(apbs[IndexCard].RamIO + VERS);
|
||||
|
|
|
|||
|
|
@ -4993,12 +4993,14 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
|
|||
device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
|
||||
card_name = "Cyclom-Y";
|
||||
|
||||
addr0 = pci_iomap(pdev, 0, CyPCI_Yctl);
|
||||
addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
|
||||
CyPCI_Yctl);
|
||||
if (addr0 == NULL) {
|
||||
dev_err(&pdev->dev, "can't remap ctl region\n");
|
||||
goto err_reg;
|
||||
}
|
||||
addr2 = pci_iomap(pdev, 2, CyPCI_Ywin);
|
||||
addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
|
||||
CyPCI_Ywin);
|
||||
if (addr2 == NULL) {
|
||||
dev_err(&pdev->dev, "can't remap base region\n");
|
||||
goto err_unmap;
|
||||
|
|
@ -5013,7 +5015,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
|
|||
} else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
|
||||
struct RUNTIME_9060 __iomem *ctl_addr;
|
||||
|
||||
ctl_addr = addr0 = pci_iomap(pdev, 0, CyPCI_Zctl);
|
||||
ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
|
||||
CyPCI_Zctl);
|
||||
if (addr0 == NULL) {
|
||||
dev_err(&pdev->dev, "can't remap ctl region\n");
|
||||
goto err_reg;
|
||||
|
|
@ -5026,8 +5029,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
|
|||
|
||||
mailbox = (u32)readl(&ctl_addr->mail_box_0);
|
||||
|
||||
addr2 = pci_iomap(pdev, 2, mailbox == ZE_V1 ?
|
||||
CyPCI_Ze_win : CyPCI_Zwin);
|
||||
addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
|
||||
mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin);
|
||||
if (addr2 == NULL) {
|
||||
dev_err(&pdev->dev, "can't remap base region\n");
|
||||
goto err_unmap;
|
||||
|
|
@ -5159,9 +5162,9 @@ err_null:
|
|||
cy_card[card_no].base_addr = NULL;
|
||||
free_irq(irq, &cy_card[card_no]);
|
||||
err_unmap:
|
||||
pci_iounmap(pdev, addr0);
|
||||
iounmap(addr0);
|
||||
if (addr2)
|
||||
pci_iounmap(pdev, addr2);
|
||||
iounmap(addr2);
|
||||
err_reg:
|
||||
pci_release_regions(pdev);
|
||||
err_dis:
|
||||
|
|
@ -5186,9 +5189,9 @@ static void __devexit cy_pci_remove(struct pci_dev *pdev)
|
|||
cy_writew(cinfo->ctl_addr + 0x68,
|
||||
readw(cinfo->ctl_addr + 0x68) & ~0x0900);
|
||||
|
||||
pci_iounmap(pdev, cinfo->base_addr);
|
||||
iounmap(cinfo->base_addr);
|
||||
if (cinfo->ctl_addr)
|
||||
pci_iounmap(pdev, cinfo->ctl_addr);
|
||||
iounmap(cinfo->ctl_addr);
|
||||
if (cinfo->irq
|
||||
#ifndef CONFIG_CYZ_INTR
|
||||
&& !IS_CYC_Z(*cinfo)
|
||||
|
|
|
|||
|
|
@ -1376,6 +1376,7 @@ static void post_fep_init(unsigned int crd)
|
|||
unsigned long flags;
|
||||
u16 tseg, rseg;
|
||||
|
||||
tty_port_init(&ch->port);
|
||||
ch->brdchan = bc;
|
||||
ch->mailbox = gd;
|
||||
INIT_WORK(&ch->tqueue, do_softint);
|
||||
|
|
@ -1510,10 +1511,6 @@ static void post_fep_init(unsigned int crd)
|
|||
ch->fepstopca = 0;
|
||||
|
||||
ch->close_delay = 50;
|
||||
ch->port.count = 0;
|
||||
ch->port.blocked_open = 0;
|
||||
init_waitqueue_head(&ch->port.open_wait);
|
||||
init_waitqueue_head(&ch->port.close_wait);
|
||||
|
||||
spin_unlock_irqrestore(&epca_lock, flags);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,8 +54,6 @@ int gs_put_char(struct tty_struct * tty, unsigned char ch)
|
|||
|
||||
func_enter ();
|
||||
|
||||
if (!tty) return 0;
|
||||
|
||||
port = tty->driver_data;
|
||||
|
||||
if (!port) return 0;
|
||||
|
|
@ -97,8 +95,6 @@ int gs_write(struct tty_struct * tty,
|
|||
|
||||
func_enter ();
|
||||
|
||||
if (!tty) return 0;
|
||||
|
||||
port = tty->driver_data;
|
||||
|
||||
if (!port) return 0;
|
||||
|
|
@ -185,7 +181,6 @@ static int gs_real_chars_in_buffer(struct tty_struct *tty)
|
|||
struct gs_port *port;
|
||||
func_enter ();
|
||||
|
||||
if (!tty) return 0;
|
||||
port = tty->driver_data;
|
||||
|
||||
if (!port->rd) return 0;
|
||||
|
|
@ -274,8 +269,6 @@ void gs_flush_buffer(struct tty_struct *tty)
|
|||
|
||||
func_enter ();
|
||||
|
||||
if (!tty) return;
|
||||
|
||||
port = tty->driver_data;
|
||||
|
||||
if (!port) return;
|
||||
|
|
@ -296,8 +289,6 @@ void gs_flush_chars(struct tty_struct * tty)
|
|||
|
||||
func_enter ();
|
||||
|
||||
if (!tty) return;
|
||||
|
||||
port = tty->driver_data;
|
||||
|
||||
if (!port) return;
|
||||
|
|
@ -321,8 +312,6 @@ void gs_stop(struct tty_struct * tty)
|
|||
|
||||
func_enter ();
|
||||
|
||||
if (!tty) return;
|
||||
|
||||
port = tty->driver_data;
|
||||
|
||||
if (!port) return;
|
||||
|
|
@ -341,8 +330,6 @@ void gs_start(struct tty_struct * tty)
|
|||
{
|
||||
struct gs_port *port;
|
||||
|
||||
if (!tty) return;
|
||||
|
||||
port = tty->driver_data;
|
||||
|
||||
if (!port) return;
|
||||
|
|
@ -393,8 +380,6 @@ void gs_hangup(struct tty_struct *tty)
|
|||
|
||||
func_enter ();
|
||||
|
||||
if (!tty) return;
|
||||
|
||||
port = tty->driver_data;
|
||||
tty = port->port.tty;
|
||||
if (!tty)
|
||||
|
|
@ -426,8 +411,6 @@ int gs_block_til_ready(void *port_, struct file * filp)
|
|||
|
||||
tty = port->port.tty;
|
||||
|
||||
if (!tty) return 0;
|
||||
|
||||
gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n");
|
||||
/*
|
||||
* If the device is in the middle of being closed, then block
|
||||
|
|
@ -523,8 +506,6 @@ void gs_close(struct tty_struct * tty, struct file * filp)
|
|||
|
||||
func_enter ();
|
||||
|
||||
if (!tty) return;
|
||||
|
||||
port = (struct gs_port *) tty->driver_data;
|
||||
|
||||
if (!port) return;
|
||||
|
|
@ -621,8 +602,6 @@ void gs_set_termios (struct tty_struct * tty,
|
|||
|
||||
func_enter();
|
||||
|
||||
if (!tty) return;
|
||||
|
||||
port = tty->driver_data;
|
||||
|
||||
if (!port) return;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,11 @@
|
|||
|
||||
#define HPET_RANGE_SIZE 1024 /* from HPET spec */
|
||||
|
||||
|
||||
/* WARNING -- don't get confused. These macros are never used
|
||||
* to write the (single) counter, and rarely to read it.
|
||||
* They're badly named; to fix, someday.
|
||||
*/
|
||||
#if BITS_PER_LONG == 64
|
||||
#define write_counter(V, MC) writeq(V, MC)
|
||||
#define read_counter(MC) readq(MC)
|
||||
|
|
@ -77,7 +82,7 @@ static struct clocksource clocksource_hpet = {
|
|||
.rating = 250,
|
||||
.read = read_hpet,
|
||||
.mask = CLOCKSOURCE_MASK(64),
|
||||
.mult = 0, /*to be caluclated*/
|
||||
.mult = 0, /* to be calculated */
|
||||
.shift = 10,
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
|
@ -86,8 +91,6 @@ static struct clocksource *hpet_clocksource;
|
|||
|
||||
/* A lock for concurrent access by app and isr hpet activity. */
|
||||
static DEFINE_SPINLOCK(hpet_lock);
|
||||
/* A lock for concurrent intermodule access to hpet and isr hpet activity. */
|
||||
static DEFINE_SPINLOCK(hpet_task_lock);
|
||||
|
||||
#define HPET_DEV_NAME (7)
|
||||
|
||||
|
|
@ -99,7 +102,6 @@ struct hpet_dev {
|
|||
unsigned long hd_irqdata;
|
||||
wait_queue_head_t hd_waitqueue;
|
||||
struct fasync_struct *hd_async_queue;
|
||||
struct hpet_task *hd_task;
|
||||
unsigned int hd_flags;
|
||||
unsigned int hd_irq;
|
||||
unsigned int hd_hdwirq;
|
||||
|
|
@ -173,11 +175,6 @@ static irqreturn_t hpet_interrupt(int irq, void *data)
|
|||
writel(isr, &devp->hd_hpet->hpet_isr);
|
||||
spin_unlock(&hpet_lock);
|
||||
|
||||
spin_lock(&hpet_task_lock);
|
||||
if (devp->hd_task)
|
||||
devp->hd_task->ht_func(devp->hd_task->ht_data);
|
||||
spin_unlock(&hpet_task_lock);
|
||||
|
||||
wake_up_interruptible(&devp->hd_waitqueue);
|
||||
|
||||
kill_fasync(&devp->hd_async_queue, SIGIO, POLL_IN);
|
||||
|
|
@ -185,6 +182,67 @@ static irqreturn_t hpet_interrupt(int irq, void *data)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void hpet_timer_set_irq(struct hpet_dev *devp)
|
||||
{
|
||||
unsigned long v;
|
||||
int irq, gsi;
|
||||
struct hpet_timer __iomem *timer;
|
||||
|
||||
spin_lock_irq(&hpet_lock);
|
||||
if (devp->hd_hdwirq) {
|
||||
spin_unlock_irq(&hpet_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
timer = devp->hd_timer;
|
||||
|
||||
/* we prefer level triggered mode */
|
||||
v = readl(&timer->hpet_config);
|
||||
if (!(v & Tn_INT_TYPE_CNF_MASK)) {
|
||||
v |= Tn_INT_TYPE_CNF_MASK;
|
||||
writel(v, &timer->hpet_config);
|
||||
}
|
||||
spin_unlock_irq(&hpet_lock);
|
||||
|
||||
v = (readq(&timer->hpet_config) & Tn_INT_ROUTE_CAP_MASK) >>
|
||||
Tn_INT_ROUTE_CAP_SHIFT;
|
||||
|
||||
/*
|
||||
* In PIC mode, skip IRQ0-4, IRQ6-9, IRQ12-15 which is always used by
|
||||
* legacy device. In IO APIC mode, we skip all the legacy IRQS.
|
||||
*/
|
||||
if (acpi_irq_model == ACPI_IRQ_MODEL_PIC)
|
||||
v &= ~0xf3df;
|
||||
else
|
||||
v &= ~0xffff;
|
||||
|
||||
for (irq = find_first_bit(&v, HPET_MAX_IRQ); irq < HPET_MAX_IRQ;
|
||||
irq = find_next_bit(&v, HPET_MAX_IRQ, 1 + irq)) {
|
||||
|
||||
if (irq >= NR_IRQS) {
|
||||
irq = HPET_MAX_IRQ;
|
||||
break;
|
||||
}
|
||||
|
||||
gsi = acpi_register_gsi(irq, ACPI_LEVEL_SENSITIVE,
|
||||
ACPI_ACTIVE_LOW);
|
||||
if (gsi > 0)
|
||||
break;
|
||||
|
||||
/* FIXME: Setup interrupt source table */
|
||||
}
|
||||
|
||||
if (irq < HPET_MAX_IRQ) {
|
||||
spin_lock_irq(&hpet_lock);
|
||||
v = readl(&timer->hpet_config);
|
||||
v |= irq << Tn_INT_ROUTE_CNF_SHIFT;
|
||||
writel(v, &timer->hpet_config);
|
||||
devp->hd_hdwirq = gsi;
|
||||
spin_unlock_irq(&hpet_lock);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int hpet_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct hpet_dev *devp;
|
||||
|
|
@ -199,8 +257,7 @@ static int hpet_open(struct inode *inode, struct file *file)
|
|||
|
||||
for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
|
||||
for (i = 0; i < hpetp->hp_ntimer; i++)
|
||||
if (hpetp->hp_dev[i].hd_flags & HPET_OPEN
|
||||
|| hpetp->hp_dev[i].hd_task)
|
||||
if (hpetp->hp_dev[i].hd_flags & HPET_OPEN)
|
||||
continue;
|
||||
else {
|
||||
devp = &hpetp->hp_dev[i];
|
||||
|
|
@ -219,6 +276,8 @@ static int hpet_open(struct inode *inode, struct file *file)
|
|||
spin_unlock_irq(&hpet_lock);
|
||||
unlock_kernel();
|
||||
|
||||
hpet_timer_set_irq(devp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -441,7 +500,11 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
|
|||
devp->hd_irq = irq;
|
||||
t = devp->hd_ireqfreq;
|
||||
v = readq(&timer->hpet_config);
|
||||
g = v | Tn_INT_ENB_CNF_MASK;
|
||||
|
||||
/* 64-bit comparators are not yet supported through the ioctls,
|
||||
* so force this into 32-bit mode if it supports both modes
|
||||
*/
|
||||
g = v | Tn_32MODE_CNF_MASK | Tn_INT_ENB_CNF_MASK;
|
||||
|
||||
if (devp->hd_flags & HPET_PERIODIC) {
|
||||
write_counter(t, &timer->hpet_compare);
|
||||
|
|
@ -451,6 +514,12 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
|
|||
v |= Tn_VAL_SET_CNF_MASK;
|
||||
writeq(v, &timer->hpet_config);
|
||||
local_irq_save(flags);
|
||||
|
||||
/* NOTE: what we modify here is a hidden accumulator
|
||||
* register supported by periodic-capable comparators.
|
||||
* We never want to modify the (single) counter; that
|
||||
* would affect all the comparators.
|
||||
*/
|
||||
m = read_counter(&hpet->hpet_mc);
|
||||
write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare);
|
||||
} else {
|
||||
|
|
@ -604,57 +673,6 @@ static int hpet_is_known(struct hpet_data *hdp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int hpet_tpcheck(struct hpet_task *tp)
|
||||
{
|
||||
struct hpet_dev *devp;
|
||||
struct hpets *hpetp;
|
||||
|
||||
devp = tp->ht_opaque;
|
||||
|
||||
if (!devp)
|
||||
return -ENXIO;
|
||||
|
||||
for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
|
||||
if (devp >= hpetp->hp_dev
|
||||
&& devp < (hpetp->hp_dev + hpetp->hp_ntimer)
|
||||
&& devp->hd_hpet == hpetp->hp_hpet)
|
||||
return 0;
|
||||
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int hpet_unregister(struct hpet_task *tp)
|
||||
{
|
||||
struct hpet_dev *devp;
|
||||
struct hpet_timer __iomem *timer;
|
||||
int err;
|
||||
|
||||
if ((err = hpet_tpcheck(tp)))
|
||||
return err;
|
||||
|
||||
spin_lock_irq(&hpet_task_lock);
|
||||
spin_lock(&hpet_lock);
|
||||
|
||||
devp = tp->ht_opaque;
|
||||
if (devp->hd_task != tp) {
|
||||
spin_unlock(&hpet_lock);
|
||||
spin_unlock_irq(&hpet_task_lock);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
timer = devp->hd_timer;
|
||||
writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK),
|
||||
&timer->hpet_config);
|
||||
devp->hd_flags &= ~(HPET_IE | HPET_PERIODIC);
|
||||
devp->hd_task = NULL;
|
||||
spin_unlock(&hpet_lock);
|
||||
spin_unlock_irq(&hpet_task_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
static ctl_table hpet_table[] = {
|
||||
{
|
||||
.ctl_name = CTL_UNNUMBERED,
|
||||
|
|
@ -746,6 +764,7 @@ int hpet_alloc(struct hpet_data *hdp)
|
|||
static struct hpets *last = NULL;
|
||||
unsigned long period;
|
||||
unsigned long long temp;
|
||||
u32 remainder;
|
||||
|
||||
/*
|
||||
* hpet_alloc can be called by platform dependent code.
|
||||
|
|
@ -809,9 +828,13 @@ int hpet_alloc(struct hpet_data *hdp)
|
|||
printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
|
||||
printk("\n");
|
||||
|
||||
printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n",
|
||||
hpetp->hp_which, hpetp->hp_ntimer,
|
||||
cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, hpetp->hp_tick_freq);
|
||||
temp = hpetp->hp_tick_freq;
|
||||
remainder = do_div(temp, 1000000);
|
||||
printk(KERN_INFO
|
||||
"hpet%u: %u comparators, %d-bit %u.%06u MHz counter\n",
|
||||
hpetp->hp_which, hpetp->hp_ntimer,
|
||||
cap & HPET_COUNTER_SIZE_MASK ? 64 : 32,
|
||||
(unsigned) temp, remainder);
|
||||
|
||||
mcfg = readq(&hpet->hpet_config);
|
||||
if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) {
|
||||
|
|
@ -874,8 +897,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
|
|||
hdp->hd_address = ioremap(addr.minimum, addr.address_length);
|
||||
|
||||
if (hpet_is_known(hdp)) {
|
||||
printk(KERN_DEBUG "%s: 0x%lx is busy\n",
|
||||
__func__, hdp->hd_phys_address);
|
||||
iounmap(hdp->hd_address);
|
||||
return AE_ALREADY_EXISTS;
|
||||
}
|
||||
|
|
@ -891,8 +912,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
|
|||
HPET_RANGE_SIZE);
|
||||
|
||||
if (hpet_is_known(hdp)) {
|
||||
printk(KERN_DEBUG "%s: 0x%lx is busy\n",
|
||||
__func__, hdp->hd_phys_address);
|
||||
iounmap(hdp->hd_address);
|
||||
return AE_ALREADY_EXISTS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -819,11 +819,11 @@ static int hvc_init(void)
|
|||
hvc_driver = drv;
|
||||
return 0;
|
||||
|
||||
put_tty:
|
||||
put_tty_driver(hvc_driver);
|
||||
stop_thread:
|
||||
kthread_stop(hvc_task);
|
||||
hvc_task = NULL;
|
||||
put_tty:
|
||||
put_tty_driver(drv);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,8 +108,8 @@ static int __init xen_init(void)
|
|||
{
|
||||
struct hvc_struct *hp;
|
||||
|
||||
if (!is_running_on_xen() ||
|
||||
is_initial_xendomain() ||
|
||||
if (!xen_pv_domain() ||
|
||||
xen_initial_domain() ||
|
||||
!xen_start_info->console.domU.evtchn)
|
||||
return -ENODEV;
|
||||
|
||||
|
|
@ -142,7 +142,7 @@ static void __exit xen_fini(void)
|
|||
|
||||
static int xen_cons_init(void)
|
||||
{
|
||||
if (!is_running_on_xen())
|
||||
if (!xen_pv_domain())
|
||||
return 0;
|
||||
|
||||
hvc_instantiate(HVC_COOKIE, 0, &hvc_ops);
|
||||
|
|
|
|||
|
|
@ -736,7 +736,7 @@ static int __devexit n2rng_remove(struct of_device *op)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id n2rng_match[] = {
|
||||
static const struct of_device_id n2rng_match[] = {
|
||||
{
|
||||
.name = "random-number-generator",
|
||||
.compatible = "SUNW,n2-rng",
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@
|
|||
|
||||
obj-$(CONFIG_COMPUTONE) += ip2.o
|
||||
|
||||
ip2-objs := ip2base.o ip2main.o
|
||||
ip2-objs := ip2main.o
|
||||
|
||||
|
|
|
|||
|
|
@ -68,38 +68,6 @@ static DEFINE_RWLOCK(Dl_spinlock);
|
|||
// iiInitialize
|
||||
//=======================================================
|
||||
|
||||
//******************************************************************************
|
||||
// Function: iiEllisInit()
|
||||
// Parameters: None
|
||||
//
|
||||
// Returns: Nothing
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// This routine performs any required initialization of the iiEllis subsystem.
|
||||
//
|
||||
//******************************************************************************
|
||||
static void
|
||||
iiEllisInit(void)
|
||||
{
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// Function: iiEllisCleanup()
|
||||
// Parameters: None
|
||||
//
|
||||
// Returns: Nothing
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// This routine performs any required cleanup of the iiEllis subsystem.
|
||||
//
|
||||
//******************************************************************************
|
||||
static void
|
||||
iiEllisCleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// Function: iiSetAddress(pB, address, delay)
|
||||
// Parameters: pB - pointer to the board structure
|
||||
|
|
|
|||
|
|
@ -511,7 +511,6 @@ typedef void (*delayFunc_t)(unsigned int);
|
|||
//
|
||||
// Initialization of a board & structure is in four (five!) parts:
|
||||
//
|
||||
// 0) iiEllisInit() - Initialize iiEllis subsystem.
|
||||
// 1) iiSetAddress() - Define the board address & delay function for a board.
|
||||
// 2) iiReset() - Reset the board (provided it exists)
|
||||
// -- Note you may do this to several boards --
|
||||
|
|
@ -523,7 +522,6 @@ typedef void (*delayFunc_t)(unsigned int);
|
|||
// loadware. To change loadware, you must begin again with step 2, resetting
|
||||
// the board again (step 1 not needed).
|
||||
|
||||
static void iiEllisInit(void);
|
||||
static int iiSetAddress(i2eBordStrPtr, int, delayFunc_t );
|
||||
static int iiReset(i2eBordStrPtr);
|
||||
static int iiResetDelay(i2eBordStrPtr);
|
||||
|
|
|
|||
|
|
@ -1,108 +0,0 @@
|
|||
// ip2.c
|
||||
// This is a dummy module to make the firmware available when needed
|
||||
// and allows it to be unloaded when not. Rumor is the __initdata
|
||||
// macro doesn't always works on all platforms so we use this kludge.
|
||||
// If not compiled as a module it just makes fip_firm avaliable then
|
||||
// __initdata should work as advertized
|
||||
//
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#ifndef __init
|
||||
#define __init
|
||||
#endif
|
||||
#ifndef __initfunc
|
||||
#define __initfunc(a) a
|
||||
#endif
|
||||
#ifndef __initdata
|
||||
#define __initdata
|
||||
#endif
|
||||
|
||||
#include "ip2types.h"
|
||||
|
||||
int
|
||||
ip2_loadmain(int *, int *); // ref into ip2main.c
|
||||
|
||||
/* Note: Add compiled in defaults to these arrays, not to the structure
|
||||
in ip2.h any longer. That structure WILL get overridden
|
||||
by these values, or command line values, or insmod values!!! =mhw=
|
||||
*/
|
||||
static int io[IP2_MAX_BOARDS]= { 0, 0, 0, 0 };
|
||||
static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 };
|
||||
|
||||
static int poll_only = 0;
|
||||
|
||||
MODULE_AUTHOR("Doug McNash");
|
||||
MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
|
||||
module_param_array(irq, int, NULL, 0);
|
||||
MODULE_PARM_DESC(irq,"Interrupts for IntelliPort Cards");
|
||||
module_param_array(io, int, NULL, 0);
|
||||
MODULE_PARM_DESC(io,"I/O ports for IntelliPort Cards");
|
||||
module_param(poll_only, bool, 0);
|
||||
MODULE_PARM_DESC(poll_only,"Do not use card interrupts");
|
||||
|
||||
|
||||
static int __init ip2_init(void)
|
||||
{
|
||||
if( poll_only ) {
|
||||
/* Hard lock the interrupts to zero */
|
||||
irq[0] = irq[1] = irq[2] = irq[3] = 0;
|
||||
}
|
||||
|
||||
return ip2_loadmain(io, irq);
|
||||
}
|
||||
module_init(ip2_init);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#ifndef MODULE
|
||||
/******************************************************************************
|
||||
* ip2_setup:
|
||||
* str: kernel command line string
|
||||
*
|
||||
* Can't autoprobe the boards so user must specify configuration on
|
||||
* kernel command line. Sane people build it modular but the others
|
||||
* come here.
|
||||
*
|
||||
* Alternating pairs of io,irq for up to 4 boards.
|
||||
* ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
|
||||
*
|
||||
* io=0 => No board
|
||||
* io=1 => PCI
|
||||
* io=2 => EISA
|
||||
* else => ISA I/O address
|
||||
*
|
||||
* irq=0 or invalid for ISA will revert to polling mode
|
||||
*
|
||||
* Any value = -1, do not overwrite compiled in value.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int __init ip2_setup(char *str)
|
||||
{
|
||||
int ints[10]; /* 4 boards, 2 parameters + 2 */
|
||||
int i, j;
|
||||
|
||||
str = get_options (str, ARRAY_SIZE(ints), ints);
|
||||
|
||||
for( i = 0, j = 1; i < 4; i++ ) {
|
||||
if( j > ints[0] ) {
|
||||
break;
|
||||
}
|
||||
if( ints[j] >= 0 ) {
|
||||
io[i] = ints[j];
|
||||
}
|
||||
j++;
|
||||
if( j > ints[0] ) {
|
||||
break;
|
||||
}
|
||||
if( ints[j] >= 0 ) {
|
||||
irq[i] = ints[j];
|
||||
}
|
||||
j++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
__setup("ip2=", ip2_setup);
|
||||
#endif /* !MODULE */
|
||||
|
|
@ -150,15 +150,12 @@ static int ip2_read_proc(char *, char **, off_t, int, int *, void * );
|
|||
/*************/
|
||||
|
||||
/* String constants to identify ourselves */
|
||||
static char *pcName = "Computone IntelliPort Plus multiport driver";
|
||||
static char *pcVersion = "1.2.14";
|
||||
static const char pcName[] = "Computone IntelliPort Plus multiport driver";
|
||||
static const char pcVersion[] = "1.2.14";
|
||||
|
||||
/* String constants for port names */
|
||||
static char *pcDriver_name = "ip2";
|
||||
static char *pcIpl = "ip2ipl";
|
||||
|
||||
// cheezy kludge or genius - you decide?
|
||||
int ip2_loadmain(int *, int *);
|
||||
static const char pcDriver_name[] = "ip2";
|
||||
static const char pcIpl[] = "ip2ipl";
|
||||
|
||||
/***********************/
|
||||
/* Function Prototypes */
|
||||
|
|
@ -240,8 +237,8 @@ static const struct file_operations ip2_ipl = {
|
|||
.open = ip2_ipl_open,
|
||||
};
|
||||
|
||||
static unsigned long irq_counter = 0;
|
||||
static unsigned long bh_counter = 0;
|
||||
static unsigned long irq_counter;
|
||||
static unsigned long bh_counter;
|
||||
|
||||
// Use immediate queue to service interrupts
|
||||
#define USE_IQI
|
||||
|
|
@ -252,7 +249,6 @@ static unsigned long bh_counter = 0;
|
|||
*/
|
||||
#define POLL_TIMEOUT (jiffies + 1)
|
||||
static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0);
|
||||
static char TimerOn;
|
||||
|
||||
#ifdef IP2DEBUG_TRACE
|
||||
/* Trace (debug) buffer data */
|
||||
|
|
@ -268,8 +264,8 @@ static int tracewrap;
|
|||
/**********/
|
||||
|
||||
#if defined(MODULE) && defined(IP2DEBUG_OPEN)
|
||||
#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \
|
||||
tty->name,(pCh->flags),ip2_tty_driver->refcount, \
|
||||
#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \
|
||||
tty->name,(pCh->flags), \
|
||||
tty->count,/*GET_USE_COUNT(module)*/0,s)
|
||||
#else
|
||||
#define DBG_CNT(s)
|
||||
|
|
@ -287,8 +283,9 @@ static int tracewrap;
|
|||
|
||||
MODULE_AUTHOR("Doug McNash");
|
||||
MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int poll_only = 0;
|
||||
static int poll_only;
|
||||
|
||||
static int Eisa_irq;
|
||||
static int Eisa_slot;
|
||||
|
|
@ -297,34 +294,46 @@ static int iindx;
|
|||
static char rirqs[IP2_MAX_BOARDS];
|
||||
static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
|
||||
|
||||
/* Note: Add compiled in defaults to these arrays, not to the structure
|
||||
in ip2.h any longer. That structure WILL get overridden
|
||||
by these values, or command line values, or insmod values!!! =mhw=
|
||||
*/
|
||||
static int io[IP2_MAX_BOARDS];
|
||||
static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 };
|
||||
|
||||
MODULE_AUTHOR("Doug McNash");
|
||||
MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
|
||||
module_param_array(irq, int, NULL, 0);
|
||||
MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards");
|
||||
module_param_array(io, int, NULL, 0);
|
||||
MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards");
|
||||
module_param(poll_only, bool, 0);
|
||||
MODULE_PARM_DESC(poll_only, "Do not use card interrupts");
|
||||
|
||||
/* for sysfs class support */
|
||||
static struct class *ip2_class;
|
||||
|
||||
// Some functions to keep track of what irq's we have
|
||||
/* Some functions to keep track of what irqs we have */
|
||||
|
||||
static int
|
||||
is_valid_irq(int irq)
|
||||
static int __init is_valid_irq(int irq)
|
||||
{
|
||||
int *i = Valid_Irqs;
|
||||
|
||||
while ((*i != 0) && (*i != irq)) {
|
||||
while (*i != 0 && *i != irq)
|
||||
i++;
|
||||
}
|
||||
return (*i);
|
||||
|
||||
return *i;
|
||||
}
|
||||
|
||||
static void
|
||||
mark_requested_irq( char irq )
|
||||
static void __init mark_requested_irq(char irq)
|
||||
{
|
||||
rirqs[iindx++] = irq;
|
||||
}
|
||||
|
||||
#ifdef MODULE
|
||||
static int
|
||||
clear_requested_irq( char irq )
|
||||
static int __exit clear_requested_irq(char irq)
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
|
||||
for (i = 0; i < IP2_MAX_BOARDS; ++i) {
|
||||
if (rirqs[i] == irq) {
|
||||
rirqs[i] = 0;
|
||||
return 1;
|
||||
|
|
@ -332,17 +341,15 @@ clear_requested_irq( char irq )
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
have_requested_irq( char irq )
|
||||
static int have_requested_irq(char irq)
|
||||
{
|
||||
// array init to zeros so 0 irq will not be requested as a side effect
|
||||
/* array init to zeros so 0 irq will not be requested as a side
|
||||
* effect */
|
||||
int i;
|
||||
for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
|
||||
for (i = 0; i < IP2_MAX_BOARDS; ++i)
|
||||
if (rirqs[i] == irq)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -361,53 +368,45 @@ have_requested_irq( char irq )
|
|||
/* handle subsequent installations of the driver. All memory allocated by the */
|
||||
/* driver should be returned since it may be unloaded from memory. */
|
||||
/******************************************************************************/
|
||||
#ifdef MODULE
|
||||
void __exit
|
||||
ip2_cleanup_module(void)
|
||||
static void __exit ip2_cleanup_module(void)
|
||||
{
|
||||
int err;
|
||||
int i;
|
||||
|
||||
#ifdef IP2DEBUG_INIT
|
||||
printk (KERN_DEBUG "Unloading %s: version %s\n", pcName, pcVersion );
|
||||
#endif
|
||||
/* Stop poll timer if we had one. */
|
||||
if ( TimerOn ) {
|
||||
del_timer ( &PollTimer );
|
||||
TimerOn = 0;
|
||||
}
|
||||
del_timer_sync(&PollTimer);
|
||||
|
||||
/* Reset the boards we have. */
|
||||
for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
|
||||
if ( i2BoardPtrTable[i] ) {
|
||||
iiReset( i2BoardPtrTable[i] );
|
||||
}
|
||||
}
|
||||
for (i = 0; i < IP2_MAX_BOARDS; i++)
|
||||
if (i2BoardPtrTable[i])
|
||||
iiReset(i2BoardPtrTable[i]);
|
||||
|
||||
/* The following is done at most once, if any boards were installed. */
|
||||
for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
|
||||
if ( i2BoardPtrTable[i] ) {
|
||||
iiResetDelay( i2BoardPtrTable[i] );
|
||||
for (i = 0; i < IP2_MAX_BOARDS; i++) {
|
||||
if (i2BoardPtrTable[i]) {
|
||||
iiResetDelay(i2BoardPtrTable[i]);
|
||||
/* free io addresses and Tibet */
|
||||
release_region( ip2config.addr[i], 8 );
|
||||
release_region(ip2config.addr[i], 8);
|
||||
device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
|
||||
device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
|
||||
device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR,
|
||||
4 * i + 1));
|
||||
}
|
||||
/* Disable and remove interrupt handler. */
|
||||
if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) {
|
||||
free_irq ( ip2config.irq[i], (void *)&pcName);
|
||||
clear_requested_irq( ip2config.irq[i]);
|
||||
if (ip2config.irq[i] > 0 &&
|
||||
have_requested_irq(ip2config.irq[i])) {
|
||||
free_irq(ip2config.irq[i], (void *)&pcName);
|
||||
clear_requested_irq(ip2config.irq[i]);
|
||||
}
|
||||
}
|
||||
class_destroy(ip2_class);
|
||||
if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) {
|
||||
printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err);
|
||||
}
|
||||
err = tty_unregister_driver(ip2_tty_driver);
|
||||
if (err)
|
||||
printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n",
|
||||
err);
|
||||
put_tty_driver(ip2_tty_driver);
|
||||
unregister_chrdev(IP2_IPL_MAJOR, pcIpl);
|
||||
remove_proc_entry("ip2mem", NULL);
|
||||
|
||||
// free memory
|
||||
/* free memory */
|
||||
for (i = 0; i < IP2_MAX_BOARDS; i++) {
|
||||
void *pB;
|
||||
#ifdef CONFIG_PCI
|
||||
|
|
@ -417,24 +416,18 @@ ip2_cleanup_module(void)
|
|||
ip2config.pci_dev[i] = NULL;
|
||||
}
|
||||
#endif
|
||||
if ((pB = i2BoardPtrTable[i]) != 0 ) {
|
||||
kfree ( pB );
|
||||
pB = i2BoardPtrTable[i];
|
||||
if (pB != NULL) {
|
||||
kfree(pB);
|
||||
i2BoardPtrTable[i] = NULL;
|
||||
}
|
||||
if ((DevTableMem[i]) != NULL ) {
|
||||
kfree ( DevTableMem[i] );
|
||||
if (DevTableMem[i] != NULL) {
|
||||
kfree(DevTableMem[i]);
|
||||
DevTableMem[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cleanup the iiEllis subsystem. */
|
||||
iiEllisCleanup();
|
||||
#ifdef IP2DEBUG_INIT
|
||||
printk (KERN_DEBUG "IP2 Unloaded\n" );
|
||||
#endif
|
||||
}
|
||||
module_exit(ip2_cleanup_module);
|
||||
#endif /* MODULE */
|
||||
|
||||
static const struct tty_operations ip2_ops = {
|
||||
.open = ip2_open,
|
||||
|
|
@ -494,139 +487,168 @@ static const struct firmware *ip2_request_firmware(void)
|
|||
return fw;
|
||||
}
|
||||
|
||||
int
|
||||
ip2_loadmain(int *iop, int *irqp)
|
||||
#ifndef MODULE
|
||||
/******************************************************************************
|
||||
* ip2_setup:
|
||||
* str: kernel command line string
|
||||
*
|
||||
* Can't autoprobe the boards so user must specify configuration on
|
||||
* kernel command line. Sane people build it modular but the others
|
||||
* come here.
|
||||
*
|
||||
* Alternating pairs of io,irq for up to 4 boards.
|
||||
* ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
|
||||
*
|
||||
* io=0 => No board
|
||||
* io=1 => PCI
|
||||
* io=2 => EISA
|
||||
* else => ISA I/O address
|
||||
*
|
||||
* irq=0 or invalid for ISA will revert to polling mode
|
||||
*
|
||||
* Any value = -1, do not overwrite compiled in value.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int __init ip2_setup(char *str)
|
||||
{
|
||||
int j, ints[10]; /* 4 boards, 2 parameters + 2 */
|
||||
unsigned int i;
|
||||
|
||||
str = get_options(str, ARRAY_SIZE(ints), ints);
|
||||
|
||||
for (i = 0, j = 1; i < 4; i++) {
|
||||
if (j > ints[0])
|
||||
break;
|
||||
if (ints[j] >= 0)
|
||||
io[i] = ints[j];
|
||||
j++;
|
||||
if (j > ints[0])
|
||||
break;
|
||||
if (ints[j] >= 0)
|
||||
irq[i] = ints[j];
|
||||
j++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
__setup("ip2=", ip2_setup);
|
||||
#endif /* !MODULE */
|
||||
|
||||
static int __init ip2_loadmain(void)
|
||||
{
|
||||
int i, j, box;
|
||||
int err = 0;
|
||||
static int loaded;
|
||||
i2eBordStrPtr pB = NULL;
|
||||
int rc = -1;
|
||||
static struct pci_dev *pci_dev_i = NULL;
|
||||
struct pci_dev *pdev = NULL;
|
||||
const struct firmware *fw = NULL;
|
||||
|
||||
ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0 );
|
||||
if (poll_only) {
|
||||
/* Hard lock the interrupts to zero */
|
||||
irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0;
|
||||
}
|
||||
|
||||
ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0);
|
||||
|
||||
/* process command line arguments to modprobe or
|
||||
insmod i.e. iop & irqp */
|
||||
/* irqp and iop should ALWAYS be specified now... But we check
|
||||
them individually just to be sure, anyways... */
|
||||
for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
|
||||
if (iop) {
|
||||
ip2config.addr[i] = iop[i];
|
||||
if (irqp) {
|
||||
if( irqp[i] >= 0 ) {
|
||||
ip2config.irq[i] = irqp[i];
|
||||
} else {
|
||||
ip2config.irq[i] = 0;
|
||||
}
|
||||
// This is a little bit of a hack. If poll_only=1 on command
|
||||
// line back in ip2.c OR all IRQs on all specified boards are
|
||||
// explicitly set to 0, then drop to poll only mode and override
|
||||
// PCI or EISA interrupts. This superceeds the old hack of
|
||||
// triggering if all interrupts were zero (like da default).
|
||||
// Still a hack but less prone to random acts of terrorism.
|
||||
//
|
||||
// What we really should do, now that the IRQ default is set
|
||||
// to -1, is to use 0 as a hard coded, do not probe.
|
||||
//
|
||||
// /\/\|=mhw=|\/\/
|
||||
poll_only |= irqp[i];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < IP2_MAX_BOARDS; ++i) {
|
||||
ip2config.addr[i] = io[i];
|
||||
if (irq[i] >= 0)
|
||||
ip2config.irq[i] = irq[i];
|
||||
else
|
||||
ip2config.irq[i] = 0;
|
||||
/* This is a little bit of a hack. If poll_only=1 on command
|
||||
line back in ip2.c OR all IRQs on all specified boards are
|
||||
explicitly set to 0, then drop to poll only mode and override
|
||||
PCI or EISA interrupts. This superceeds the old hack of
|
||||
triggering if all interrupts were zero (like da default).
|
||||
Still a hack but less prone to random acts of terrorism.
|
||||
|
||||
What we really should do, now that the IRQ default is set
|
||||
to -1, is to use 0 as a hard coded, do not probe.
|
||||
|
||||
/\/\|=mhw=|\/\/
|
||||
*/
|
||||
poll_only |= irq[i];
|
||||
}
|
||||
poll_only = !poll_only;
|
||||
|
||||
/* Announce our presence */
|
||||
printk( KERN_INFO "%s version %s\n", pcName, pcVersion );
|
||||
|
||||
// ip2 can be unloaded and reloaded for no good reason
|
||||
// we can't let that happen here or bad things happen
|
||||
// second load hoses board but not system - fixme later
|
||||
if (loaded) {
|
||||
printk( KERN_INFO "Still loaded\n" );
|
||||
return 0;
|
||||
}
|
||||
loaded++;
|
||||
printk(KERN_INFO "%s version %s\n", pcName, pcVersion);
|
||||
|
||||
ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS);
|
||||
if (!ip2_tty_driver)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Initialise the iiEllis subsystem. */
|
||||
iiEllisInit();
|
||||
|
||||
/* Initialize arrays. */
|
||||
memset( i2BoardPtrTable, 0, sizeof i2BoardPtrTable );
|
||||
memset( DevTable, 0, sizeof DevTable );
|
||||
|
||||
/* Initialise all the boards we can find (up to the maximum). */
|
||||
for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
|
||||
switch ( ip2config.addr[i] ) {
|
||||
for (i = 0; i < IP2_MAX_BOARDS; ++i) {
|
||||
switch (ip2config.addr[i]) {
|
||||
case 0: /* skip this slot even if card is present */
|
||||
break;
|
||||
default: /* ISA */
|
||||
/* ISA address must be specified */
|
||||
if ( (ip2config.addr[i] < 0x100) || (ip2config.addr[i] > 0x3f8) ) {
|
||||
printk ( KERN_ERR "IP2: Bad ISA board %d address %x\n",
|
||||
i, ip2config.addr[i] );
|
||||
if (ip2config.addr[i] < 0x100 ||
|
||||
ip2config.addr[i] > 0x3f8) {
|
||||
printk(KERN_ERR "IP2: Bad ISA board %d "
|
||||
"address %x\n", i,
|
||||
ip2config.addr[i]);
|
||||
ip2config.addr[i] = 0;
|
||||
} else {
|
||||
ip2config.type[i] = ISA;
|
||||
break;
|
||||
}
|
||||
ip2config.type[i] = ISA;
|
||||
|
||||
/* Check for valid irq argument, set for polling if invalid */
|
||||
if (ip2config.irq[i] && !is_valid_irq(ip2config.irq[i])) {
|
||||
printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",ip2config.irq[i]);
|
||||
ip2config.irq[i] = 0;// 0 is polling and is valid in that sense
|
||||
}
|
||||
/* Check for valid irq argument, set for polling if
|
||||
* invalid */
|
||||
if (ip2config.irq[i] &&
|
||||
!is_valid_irq(ip2config.irq[i])) {
|
||||
printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",
|
||||
ip2config.irq[i]);
|
||||
/* 0 is polling and is valid in that sense */
|
||||
ip2config.irq[i] = 0;
|
||||
}
|
||||
break;
|
||||
case PCI:
|
||||
#ifdef CONFIG_PCI
|
||||
{
|
||||
int status;
|
||||
{
|
||||
u32 addr;
|
||||
int status;
|
||||
|
||||
pci_dev_i = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
|
||||
PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i);
|
||||
if (pci_dev_i != NULL) {
|
||||
unsigned int addr;
|
||||
|
||||
if (pci_enable_device(pci_dev_i)) {
|
||||
printk( KERN_ERR "IP2: can't enable PCI device at %s\n",
|
||||
pci_name(pci_dev_i));
|
||||
break;
|
||||
}
|
||||
ip2config.type[i] = PCI;
|
||||
ip2config.pci_dev[i] = pci_dev_get(pci_dev_i);
|
||||
status =
|
||||
pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr);
|
||||
if ( addr & 1 ) {
|
||||
ip2config.addr[i]=(USHORT)(addr&0xfffe);
|
||||
} else {
|
||||
printk( KERN_ERR "IP2: PCI I/O address error\n");
|
||||
}
|
||||
|
||||
// If the PCI BIOS assigned it, lets try and use it. If we
|
||||
// can't acquire it or it screws up, deal with it then.
|
||||
|
||||
// if (!is_valid_irq(pci_irq)) {
|
||||
// printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq);
|
||||
// pci_irq = 0;
|
||||
// }
|
||||
ip2config.irq[i] = pci_dev_i->irq;
|
||||
} else { // ann error
|
||||
ip2config.addr[i] = 0;
|
||||
printk(KERN_ERR "IP2: PCI board %d not found\n", i);
|
||||
}
|
||||
pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
|
||||
PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev);
|
||||
if (pdev == NULL) {
|
||||
ip2config.addr[i] = 0;
|
||||
printk(KERN_ERR "IP2: PCI board %d not "
|
||||
"found\n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pci_enable_device(pdev)) {
|
||||
dev_err(&pdev->dev, "can't enable device\n");
|
||||
break;
|
||||
}
|
||||
ip2config.type[i] = PCI;
|
||||
ip2config.pci_dev[i] = pci_dev_get(pdev);
|
||||
status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1,
|
||||
&addr);
|
||||
if (addr & 1)
|
||||
ip2config.addr[i] = (USHORT)(addr & 0xfffe);
|
||||
else
|
||||
dev_err(&pdev->dev, "I/O address error\n");
|
||||
|
||||
ip2config.irq[i] = pdev->irq;
|
||||
}
|
||||
#else
|
||||
printk( KERN_ERR "IP2: PCI card specified but PCI support not\n");
|
||||
printk( KERN_ERR "IP2: configured in this kernel.\n");
|
||||
printk( KERN_ERR "IP2: Recompile kernel with CONFIG_PCI defined!\n");
|
||||
printk(KERN_ERR "IP2: PCI card specified but PCI "
|
||||
"support not enabled.\n");
|
||||
printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI "
|
||||
"defined!\n");
|
||||
#endif /* CONFIG_PCI */
|
||||
break;
|
||||
case EISA:
|
||||
if ( (ip2config.addr[i] = find_eisa_board( Eisa_slot + 1 )) != 0) {
|
||||
ip2config.addr[i] = find_eisa_board(Eisa_slot + 1);
|
||||
if (ip2config.addr[i] != 0) {
|
||||
/* Eisa_irq set as side effect, boo */
|
||||
ip2config.type[i] = EISA;
|
||||
}
|
||||
|
|
@ -634,31 +656,32 @@ ip2_loadmain(int *iop, int *irqp)
|
|||
break;
|
||||
} /* switch */
|
||||
} /* for */
|
||||
if (pci_dev_i)
|
||||
pci_dev_put(pci_dev_i);
|
||||
pci_dev_put(pdev);
|
||||
|
||||
for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
|
||||
if ( ip2config.addr[i] ) {
|
||||
for (i = 0; i < IP2_MAX_BOARDS; ++i) {
|
||||
if (ip2config.addr[i]) {
|
||||
pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL);
|
||||
if (pB) {
|
||||
i2BoardPtrTable[i] = pB;
|
||||
iiSetAddress( pB, ip2config.addr[i], ii2DelayTimer );
|
||||
iiReset( pB );
|
||||
} else {
|
||||
printk(KERN_ERR "IP2: board memory allocation error\n");
|
||||
}
|
||||
iiSetAddress(pB, ip2config.addr[i],
|
||||
ii2DelayTimer);
|
||||
iiReset(pB);
|
||||
} else
|
||||
printk(KERN_ERR "IP2: board memory allocation "
|
||||
"error\n");
|
||||
}
|
||||
}
|
||||
for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
|
||||
if ( ( pB = i2BoardPtrTable[i] ) != NULL ) {
|
||||
iiResetDelay( pB );
|
||||
for (i = 0; i < IP2_MAX_BOARDS; ++i) {
|
||||
pB = i2BoardPtrTable[i];
|
||||
if (pB != NULL) {
|
||||
iiResetDelay(pB);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
|
||||
for (i = 0; i < IP2_MAX_BOARDS; ++i) {
|
||||
/* We don't want to request the firmware unless we have at
|
||||
least one board */
|
||||
if ( i2BoardPtrTable[i] != NULL ) {
|
||||
if (i2BoardPtrTable[i] != NULL) {
|
||||
if (!fw)
|
||||
fw = ip2_request_firmware();
|
||||
if (!fw)
|
||||
|
|
@ -669,7 +692,7 @@ ip2_loadmain(int *iop, int *irqp)
|
|||
if (fw)
|
||||
release_firmware(fw);
|
||||
|
||||
ip2trace (ITRC_NO_PORT, ITRC_INIT, 2, 0 );
|
||||
ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0);
|
||||
|
||||
ip2_tty_driver->owner = THIS_MODULE;
|
||||
ip2_tty_driver->name = "ttyF";
|
||||
|
|
@ -680,20 +703,23 @@ ip2_loadmain(int *iop, int *irqp)
|
|||
ip2_tty_driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
ip2_tty_driver->init_termios = tty_std_termios;
|
||||
ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
|
||||
ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV;
|
||||
tty_set_operations(ip2_tty_driver, &ip2_ops);
|
||||
|
||||
ip2trace (ITRC_NO_PORT, ITRC_INIT, 3, 0 );
|
||||
ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0);
|
||||
|
||||
/* Register the tty devices. */
|
||||
if ( ( err = tty_register_driver ( ip2_tty_driver ) ) ) {
|
||||
printk(KERN_ERR "IP2: failed to register tty driver (%d)\n", err);
|
||||
err = tty_register_driver(ip2_tty_driver);
|
||||
if (err) {
|
||||
printk(KERN_ERR "IP2: failed to register tty driver\n");
|
||||
put_tty_driver(ip2_tty_driver);
|
||||
return -EINVAL;
|
||||
} else
|
||||
/* Register the IPL driver. */
|
||||
if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) ) {
|
||||
printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err );
|
||||
return err; /* leaking resources */
|
||||
}
|
||||
|
||||
err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl);
|
||||
if (err) {
|
||||
printk(KERN_ERR "IP2: failed to register IPL device (%d)\n",
|
||||
err);
|
||||
} else {
|
||||
/* create the sysfs class */
|
||||
ip2_class = class_create(THIS_MODULE, "ip2");
|
||||
|
|
@ -705,84 +731,86 @@ ip2_loadmain(int *iop, int *irqp)
|
|||
/* Register the read_procmem thing */
|
||||
if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) {
|
||||
printk(KERN_ERR "IP2: failed to register read_procmem\n");
|
||||
} else {
|
||||
return -EIO; /* leaking resources */
|
||||
}
|
||||
|
||||
ip2trace (ITRC_NO_PORT, ITRC_INIT, 4, 0 );
|
||||
/* Register the interrupt handler or poll handler, depending upon the
|
||||
* specified interrupt.
|
||||
*/
|
||||
ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0);
|
||||
/* Register the interrupt handler or poll handler, depending upon the
|
||||
* specified interrupt.
|
||||
*/
|
||||
|
||||
for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
|
||||
if ( 0 == ip2config.addr[i] ) {
|
||||
continue;
|
||||
}
|
||||
for (i = 0; i < IP2_MAX_BOARDS; ++i) {
|
||||
if (ip2config.addr[i] == 0)
|
||||
continue;
|
||||
|
||||
if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
|
||||
device_create_drvdata(ip2_class, NULL,
|
||||
MKDEV(IP2_IPL_MAJOR, 4 * i),
|
||||
NULL, "ipl%d", i);
|
||||
device_create_drvdata(ip2_class, NULL,
|
||||
MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
|
||||
NULL, "stat%d", i);
|
||||
pB = i2BoardPtrTable[i];
|
||||
if (pB != NULL) {
|
||||
device_create_drvdata(ip2_class, NULL,
|
||||
MKDEV(IP2_IPL_MAJOR, 4 * i),
|
||||
NULL, "ipl%d", i);
|
||||
device_create_drvdata(ip2_class, NULL,
|
||||
MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
|
||||
NULL, "stat%d", i);
|
||||
|
||||
for ( box = 0; box < ABS_MAX_BOXES; ++box )
|
||||
{
|
||||
for ( j = 0; j < ABS_BIGGEST_BOX; ++j )
|
||||
{
|
||||
if ( pB->i2eChannelMap[box] & (1 << j) )
|
||||
{
|
||||
tty_register_device(ip2_tty_driver,
|
||||
j + ABS_BIGGEST_BOX *
|
||||
(box+i*ABS_MAX_BOXES), NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (poll_only) {
|
||||
// Poll only forces driver to only use polling and
|
||||
// to ignore the probed PCI or EISA interrupts.
|
||||
ip2config.irq[i] = CIR_POLL;
|
||||
}
|
||||
if ( ip2config.irq[i] == CIR_POLL ) {
|
||||
retry:
|
||||
if (!TimerOn) {
|
||||
PollTimer.expires = POLL_TIMEOUT;
|
||||
add_timer ( &PollTimer );
|
||||
TimerOn = 1;
|
||||
printk( KERN_INFO "IP2: polling\n");
|
||||
}
|
||||
} else {
|
||||
if (have_requested_irq(ip2config.irq[i]))
|
||||
continue;
|
||||
rc = request_irq( ip2config.irq[i], ip2_interrupt,
|
||||
IP2_SA_FLAGS | (ip2config.type[i] == PCI ? IRQF_SHARED : 0),
|
||||
pcName, i2BoardPtrTable[i]);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "IP2: an request_irq failed: error %d\n",rc);
|
||||
ip2config.irq[i] = CIR_POLL;
|
||||
printk( KERN_INFO "IP2: Polling %ld/sec.\n",
|
||||
(POLL_TIMEOUT - jiffies));
|
||||
goto retry;
|
||||
}
|
||||
mark_requested_irq(ip2config.irq[i]);
|
||||
/* Initialise the interrupt handler bottom half (aka slih). */
|
||||
}
|
||||
for (box = 0; box < ABS_MAX_BOXES; box++)
|
||||
for (j = 0; j < ABS_BIGGEST_BOX; j++)
|
||||
if (pB->i2eChannelMap[box] & (1 << j))
|
||||
tty_register_device(
|
||||
ip2_tty_driver,
|
||||
j + ABS_BIGGEST_BOX *
|
||||
(box+i*ABS_MAX_BOXES),
|
||||
NULL);
|
||||
}
|
||||
for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
|
||||
if ( i2BoardPtrTable[i] ) {
|
||||
set_irq( i, ip2config.irq[i] ); /* set and enable board interrupt */
|
||||
|
||||
if (poll_only) {
|
||||
/* Poll only forces driver to only use polling and
|
||||
to ignore the probed PCI or EISA interrupts. */
|
||||
ip2config.irq[i] = CIR_POLL;
|
||||
}
|
||||
if (ip2config.irq[i] == CIR_POLL) {
|
||||
retry:
|
||||
if (!timer_pending(&PollTimer)) {
|
||||
mod_timer(&PollTimer, POLL_TIMEOUT);
|
||||
printk(KERN_INFO "IP2: polling\n");
|
||||
}
|
||||
} else {
|
||||
if (have_requested_irq(ip2config.irq[i]))
|
||||
continue;
|
||||
rc = request_irq(ip2config.irq[i], ip2_interrupt,
|
||||
IP2_SA_FLAGS |
|
||||
(ip2config.type[i] == PCI ? IRQF_SHARED : 0),
|
||||
pcName, i2BoardPtrTable[i]);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "IP2: request_irq failed: "
|
||||
"error %d\n", rc);
|
||||
ip2config.irq[i] = CIR_POLL;
|
||||
printk(KERN_INFO "IP2: Polling %ld/sec.\n",
|
||||
(POLL_TIMEOUT - jiffies));
|
||||
goto retry;
|
||||
}
|
||||
mark_requested_irq(ip2config.irq[i]);
|
||||
/* Initialise the interrupt handler bottom half
|
||||
* (aka slih). */
|
||||
}
|
||||
}
|
||||
ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0 );
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < IP2_MAX_BOARDS; ++i) {
|
||||
if (i2BoardPtrTable[i]) {
|
||||
/* set and enable board interrupt */
|
||||
set_irq(i, ip2config.irq[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
out_chrdev:
|
||||
unregister_chrdev(IP2_IPL_MAJOR, "ip2");
|
||||
out:
|
||||
/* unregister and put tty here */
|
||||
return err;
|
||||
}
|
||||
module_init(ip2_loadmain);
|
||||
|
||||
/******************************************************************************/
|
||||
/* Function: ip2_init_board() */
|
||||
|
|
@ -1199,9 +1227,8 @@ ip2_polled_interrupt(void)
|
|||
{
|
||||
int i;
|
||||
i2eBordStrPtr pB;
|
||||
const int irq = 0;
|
||||
|
||||
ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, irq );
|
||||
ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0);
|
||||
|
||||
/* Service just the boards on the list using this irq */
|
||||
for( i = 0; i < i2nBoards; ++i ) {
|
||||
|
|
@ -1210,9 +1237,8 @@ ip2_polled_interrupt(void)
|
|||
// Only process those boards which match our IRQ.
|
||||
// IRQ = 0 for polled boards, we won't poll "IRQ" boards
|
||||
|
||||
if ( pB && (pB->i2eUsingIrq == irq) ) {
|
||||
if (pB && pB->i2eUsingIrq == 0)
|
||||
ip2_irq_work(pB);
|
||||
}
|
||||
}
|
||||
|
||||
++irq_counter;
|
||||
|
|
@ -1250,16 +1276,12 @@ ip2_poll(unsigned long arg)
|
|||
{
|
||||
ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 );
|
||||
|
||||
TimerOn = 0; // it's the truth but not checked in service
|
||||
|
||||
// Just polled boards, IRQ = 0 will hit all non-interrupt boards.
|
||||
// It will NOT poll boards handled by hard interrupts.
|
||||
// The issue of queued BH interrupts is handled in ip2_interrupt().
|
||||
ip2_polled_interrupt();
|
||||
|
||||
PollTimer.expires = POLL_TIMEOUT;
|
||||
add_timer( &PollTimer );
|
||||
TimerOn = 1;
|
||||
mod_timer(&PollTimer, POLL_TIMEOUT);
|
||||
|
||||
ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
|
||||
}
|
||||
|
|
@ -2871,7 +2893,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
|
|||
case 13:
|
||||
switch ( cmd ) {
|
||||
case 64: /* Driver - ip2stat */
|
||||
rc = put_user(ip2_tty_driver->refcount, pIndex++ );
|
||||
rc = put_user(-1, pIndex++ );
|
||||
rc = put_user(irq_counter, pIndex++ );
|
||||
rc = put_user(bh_counter, pIndex++ );
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -421,17 +421,16 @@ static void isicom_tx(unsigned long _data)
|
|||
if (retries >= 100)
|
||||
goto unlock;
|
||||
|
||||
tty = tty_port_tty_get(&port->port);
|
||||
if (tty == NULL)
|
||||
goto put_unlock;
|
||||
|
||||
for (; count > 0; count--, port++) {
|
||||
/* port not active or tx disabled to force flow control */
|
||||
if (!(port->port.flags & ASYNC_INITIALIZED) ||
|
||||
!(port->status & ISI_TXOK))
|
||||
continue;
|
||||
|
||||
tty = port->port.tty;
|
||||
|
||||
if (tty == NULL)
|
||||
continue;
|
||||
|
||||
txcount = min_t(short, TX_SIZE, port->xmit_cnt);
|
||||
if (txcount <= 0 || tty->stopped || tty->hw_stopped)
|
||||
continue;
|
||||
|
|
@ -489,6 +488,8 @@ static void isicom_tx(unsigned long _data)
|
|||
tty_wakeup(tty);
|
||||
}
|
||||
|
||||
put_unlock:
|
||||
tty_kref_put(tty);
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
|
||||
/* schedule another tx for hopefully in about 10ms */
|
||||
|
|
@ -547,7 +548,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
tty = port->port.tty;
|
||||
tty = tty_port_tty_get(&port->port);
|
||||
if (tty == NULL) {
|
||||
word_count = byte_count >> 1;
|
||||
while (byte_count > 1) {
|
||||
|
|
@ -588,7 +589,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
|
|||
}
|
||||
|
||||
if (port->port.flags & ASYNC_CTS_FLOW) {
|
||||
if (port->port.tty->hw_stopped) {
|
||||
if (tty->hw_stopped) {
|
||||
if (header & ISI_CTS) {
|
||||
port->port.tty->hw_stopped = 0;
|
||||
/* start tx ing */
|
||||
|
|
@ -597,7 +598,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
|
|||
tty_wakeup(tty);
|
||||
}
|
||||
} else if (!(header & ISI_CTS)) {
|
||||
port->port.tty->hw_stopped = 1;
|
||||
tty->hw_stopped = 1;
|
||||
/* stop tx ing */
|
||||
port->status &= ~(ISI_TXOK | ISI_CTS);
|
||||
}
|
||||
|
|
@ -660,24 +661,21 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
|
|||
}
|
||||
outw(0x0000, base+0x04); /* enable interrupts */
|
||||
spin_unlock(&card->card_lock);
|
||||
tty_kref_put(tty);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void isicom_config_port(struct isi_port *port)
|
||||
static void isicom_config_port(struct tty_struct *tty)
|
||||
{
|
||||
struct isi_port *port = tty->driver_data;
|
||||
struct isi_board *card = port->card;
|
||||
struct tty_struct *tty;
|
||||
unsigned long baud;
|
||||
unsigned long base = card->base;
|
||||
u16 channel_setup, channel = port->channel,
|
||||
shift_count = card->shift_count;
|
||||
unsigned char flow_ctrl;
|
||||
|
||||
tty = port->port.tty;
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
/* FIXME: Switch to new tty baud API */
|
||||
baud = C_BAUD(tty);
|
||||
if (baud & CBAUDEX) {
|
||||
|
|
@ -690,7 +688,7 @@ static void isicom_config_port(struct isi_port *port)
|
|||
|
||||
/* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
|
||||
if (baud < 1 || baud > 4)
|
||||
port->port.tty->termios->c_cflag &= ~CBAUDEX;
|
||||
tty->termios->c_cflag &= ~CBAUDEX;
|
||||
else
|
||||
baud += 15;
|
||||
}
|
||||
|
|
@ -797,8 +795,9 @@ static inline void isicom_setup_board(struct isi_board *bp)
|
|||
spin_unlock_irqrestore(&bp->card_lock, flags);
|
||||
}
|
||||
|
||||
static int isicom_setup_port(struct isi_port *port)
|
||||
static int isicom_setup_port(struct tty_struct *tty)
|
||||
{
|
||||
struct isi_port *port = tty->driver_data;
|
||||
struct isi_board *card = port->card;
|
||||
unsigned long flags;
|
||||
|
||||
|
|
@ -808,8 +807,7 @@ static int isicom_setup_port(struct isi_port *port)
|
|||
return -ENOMEM;
|
||||
|
||||
spin_lock_irqsave(&card->card_lock, flags);
|
||||
if (port->port.tty)
|
||||
clear_bit(TTY_IO_ERROR, &port->port.tty->flags);
|
||||
clear_bit(TTY_IO_ERROR, &tty->flags);
|
||||
if (port->port.count == 1)
|
||||
card->count++;
|
||||
|
||||
|
|
@ -823,7 +821,7 @@ static int isicom_setup_port(struct isi_port *port)
|
|||
InterruptTheCard(card->base);
|
||||
}
|
||||
|
||||
isicom_config_port(port);
|
||||
isicom_config_port(tty);
|
||||
port->port.flags |= ASYNC_INITIALIZED;
|
||||
spin_unlock_irqrestore(&card->card_lock, flags);
|
||||
|
||||
|
|
@ -934,8 +932,8 @@ static int isicom_open(struct tty_struct *tty, struct file *filp)
|
|||
|
||||
port->port.count++;
|
||||
tty->driver_data = port;
|
||||
port->port.tty = tty;
|
||||
error = isicom_setup_port(port);
|
||||
tty_port_tty_set(&port->port, tty);
|
||||
error = isicom_setup_port(tty);
|
||||
if (error == 0)
|
||||
error = block_til_ready(tty, filp, port);
|
||||
return error;
|
||||
|
|
@ -955,15 +953,17 @@ static void isicom_shutdown_port(struct isi_port *port)
|
|||
struct isi_board *card = port->card;
|
||||
struct tty_struct *tty;
|
||||
|
||||
tty = port->port.tty;
|
||||
tty = tty_port_tty_get(&port->port);
|
||||
|
||||
if (!(port->port.flags & ASYNC_INITIALIZED))
|
||||
if (!(port->port.flags & ASYNC_INITIALIZED)) {
|
||||
tty_kref_put(tty);
|
||||
return;
|
||||
}
|
||||
|
||||
tty_port_free_xmit_buf(&port->port);
|
||||
port->port.flags &= ~ASYNC_INITIALIZED;
|
||||
/* 3rd October 2000 : Vinayak P Risbud */
|
||||
port->port.tty = NULL;
|
||||
tty_port_tty_set(&port->port, NULL);
|
||||
|
||||
/*Fix done by Anil .S on 30-04-2001
|
||||
remote login through isi port has dtr toggle problem
|
||||
|
|
@ -1243,9 +1243,10 @@ static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int isicom_set_serial_info(struct isi_port *port,
|
||||
struct serial_struct __user *info)
|
||||
static int isicom_set_serial_info(struct tty_struct *tty,
|
||||
struct serial_struct __user *info)
|
||||
{
|
||||
struct isi_port *port = tty->driver_data;
|
||||
struct serial_struct newinfo;
|
||||
int reconfig_port;
|
||||
|
||||
|
|
@ -1276,7 +1277,7 @@ static int isicom_set_serial_info(struct isi_port *port,
|
|||
if (reconfig_port) {
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&port->card->card_lock, flags);
|
||||
isicom_config_port(port);
|
||||
isicom_config_port(tty);
|
||||
spin_unlock_irqrestore(&port->card->card_lock, flags);
|
||||
}
|
||||
unlock_kernel();
|
||||
|
|
@ -1318,7 +1319,7 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
|
|||
return isicom_get_serial_info(port, argp);
|
||||
|
||||
case TIOCSSERIAL:
|
||||
return isicom_set_serial_info(port, argp);
|
||||
return isicom_set_serial_info(tty, argp);
|
||||
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
|
|
@ -1341,7 +1342,7 @@ static void isicom_set_termios(struct tty_struct *tty,
|
|||
return;
|
||||
|
||||
spin_lock_irqsave(&port->card->card_lock, flags);
|
||||
isicom_config_port(port);
|
||||
isicom_config_port(tty);
|
||||
spin_unlock_irqrestore(&port->card->card_lock, flags);
|
||||
|
||||
if ((old_termios->c_cflag & CRTSCTS) &&
|
||||
|
|
@ -1419,7 +1420,7 @@ static void isicom_hangup(struct tty_struct *tty)
|
|||
|
||||
port->port.count = 0;
|
||||
port->port.flags &= ~ASYNC_NORMAL_ACTIVE;
|
||||
port->port.tty = NULL;
|
||||
tty_port_tty_set(&port->port, NULL);
|
||||
wake_up_interruptible(&port->port.open_wait);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -623,24 +623,25 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
|
|||
static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp);
|
||||
static void stli_poll(unsigned long arg);
|
||||
static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp);
|
||||
static int stli_initopen(struct stlibrd *brdp, struct stliport *portp);
|
||||
static int stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp);
|
||||
static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
|
||||
static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
|
||||
static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp);
|
||||
static int stli_setport(struct stliport *portp);
|
||||
static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp,
|
||||
struct stliport *portp, struct file *filp);
|
||||
static int stli_setport(struct tty_struct *tty);
|
||||
static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
|
||||
static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
|
||||
static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
|
||||
static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp);
|
||||
static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp);
|
||||
static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp, asyport_t *pp, struct ktermios *tiosp);
|
||||
static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts);
|
||||
static long stli_mktiocm(unsigned long sigvalue);
|
||||
static void stli_read(struct stlibrd *brdp, struct stliport *portp);
|
||||
static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp);
|
||||
static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp);
|
||||
static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp);
|
||||
static int stli_getbrdstats(combrd_t __user *bp);
|
||||
static int stli_getportstats(struct stliport *portp, comstats_t __user *cp);
|
||||
static int stli_portcmdstats(struct stliport *portp);
|
||||
static int stli_getportstats(struct tty_struct *tty, struct stliport *portp, comstats_t __user *cp);
|
||||
static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp);
|
||||
static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp);
|
||||
static int stli_getportstruct(struct stliport __user *arg);
|
||||
static int stli_getbrdstruct(struct stlibrd __user *arg);
|
||||
|
|
@ -731,12 +732,16 @@ static void stli_cleanup_ports(struct stlibrd *brdp)
|
|||
{
|
||||
struct stliport *portp;
|
||||
unsigned int j;
|
||||
struct tty_struct *tty;
|
||||
|
||||
for (j = 0; j < STL_MAXPORTS; j++) {
|
||||
portp = brdp->ports[j];
|
||||
if (portp != NULL) {
|
||||
if (portp->port.tty != NULL)
|
||||
tty_hangup(portp->port.tty);
|
||||
tty = tty_port_tty_get(&portp->port);
|
||||
if (tty != NULL) {
|
||||
tty_hangup(tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
kfree(portp);
|
||||
}
|
||||
}
|
||||
|
|
@ -824,7 +829,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
|
|||
* requires several commands to the board we will need to wait for any
|
||||
* other open that is already initializing the port.
|
||||
*/
|
||||
portp->port.tty = tty;
|
||||
tty_port_tty_set(&portp->port, tty);
|
||||
tty->driver_data = portp;
|
||||
portp->port.count++;
|
||||
|
||||
|
|
@ -835,7 +840,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
|
|||
|
||||
if ((portp->port.flags & ASYNC_INITIALIZED) == 0) {
|
||||
set_bit(ST_INITIALIZING, &portp->state);
|
||||
if ((rc = stli_initopen(brdp, portp)) >= 0) {
|
||||
if ((rc = stli_initopen(tty, brdp, portp)) >= 0) {
|
||||
portp->port.flags |= ASYNC_INITIALIZED;
|
||||
clear_bit(TTY_IO_ERROR, &tty->flags);
|
||||
}
|
||||
|
|
@ -864,7 +869,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
|
|||
* then also we might have to wait for carrier.
|
||||
*/
|
||||
if (!(filp->f_flags & O_NONBLOCK)) {
|
||||
if ((rc = stli_waitcarrier(brdp, portp, filp)) != 0)
|
||||
if ((rc = stli_waitcarrier(tty, brdp, portp, filp)) != 0)
|
||||
return rc;
|
||||
}
|
||||
portp->port.flags |= ASYNC_NORMAL_ACTIVE;
|
||||
|
|
@ -930,7 +935,7 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
|
|||
stli_flushbuffer(tty);
|
||||
|
||||
tty->closing = 0;
|
||||
portp->port.tty = NULL;
|
||||
tty_port_tty_set(&portp->port, NULL);
|
||||
|
||||
if (portp->openwaitcnt) {
|
||||
if (portp->close_delay)
|
||||
|
|
@ -952,9 +957,9 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
|
|||
* this still all happens pretty quickly.
|
||||
*/
|
||||
|
||||
static int stli_initopen(struct stlibrd *brdp, struct stliport *portp)
|
||||
static int stli_initopen(struct tty_struct *tty,
|
||||
struct stlibrd *brdp, struct stliport *portp)
|
||||
{
|
||||
struct tty_struct *tty;
|
||||
asynotify_t nt;
|
||||
asyport_t aport;
|
||||
int rc;
|
||||
|
|
@ -969,10 +974,7 @@ static int stli_initopen(struct stlibrd *brdp, struct stliport *portp)
|
|||
sizeof(asynotify_t), 0)) < 0)
|
||||
return rc;
|
||||
|
||||
tty = portp->port.tty;
|
||||
if (tty == NULL)
|
||||
return -ENODEV;
|
||||
stli_mkasyport(portp, &aport, tty->termios);
|
||||
stli_mkasyport(tty, portp, &aport, tty->termios);
|
||||
if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport,
|
||||
sizeof(asyport_t), 0)) < 0)
|
||||
return rc;
|
||||
|
|
@ -1161,22 +1163,21 @@ static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned l
|
|||
* waiting for the command to complete - so must have user context.
|
||||
*/
|
||||
|
||||
static int stli_setport(struct stliport *portp)
|
||||
static int stli_setport(struct tty_struct *tty)
|
||||
{
|
||||
struct stliport *portp = tty->driver_data;
|
||||
struct stlibrd *brdp;
|
||||
asyport_t aport;
|
||||
|
||||
if (portp == NULL)
|
||||
return -ENODEV;
|
||||
if (portp->port.tty == NULL)
|
||||
return -ENODEV;
|
||||
if (portp->brdnr >= stli_nrbrds)
|
||||
return -ENODEV;
|
||||
brdp = stli_brds[portp->brdnr];
|
||||
if (brdp == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
stli_mkasyport(portp, &aport, portp->port.tty->termios);
|
||||
stli_mkasyport(tty, portp, &aport, tty->termios);
|
||||
return(stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0));
|
||||
}
|
||||
|
||||
|
|
@ -1187,7 +1188,8 @@ static int stli_setport(struct stliport *portp)
|
|||
* maybe because if we are clocal then we don't need to wait...
|
||||
*/
|
||||
|
||||
static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp)
|
||||
static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp,
|
||||
struct stliport *portp, struct file *filp)
|
||||
{
|
||||
unsigned long flags;
|
||||
int rc, doclocal;
|
||||
|
|
@ -1195,7 +1197,7 @@ static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct
|
|||
rc = 0;
|
||||
doclocal = 0;
|
||||
|
||||
if (portp->port.tty->termios->c_cflag & CLOCAL)
|
||||
if (tty->termios->c_cflag & CLOCAL)
|
||||
doclocal++;
|
||||
|
||||
spin_lock_irqsave(&stli_lock, flags);
|
||||
|
|
@ -1373,8 +1375,6 @@ static void stli_flushchars(struct tty_struct *tty)
|
|||
stli_txcookrealsize = 0;
|
||||
stli_txcooktty = NULL;
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
if (cooktty == NULL)
|
||||
return;
|
||||
if (tty != cooktty)
|
||||
|
|
@ -1572,10 +1572,11 @@ static int stli_getserial(struct stliport *portp, struct serial_struct __user *s
|
|||
* just quietly ignore any requests to change irq, etc.
|
||||
*/
|
||||
|
||||
static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp)
|
||||
static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
|
||||
{
|
||||
struct serial_struct sio;
|
||||
int rc;
|
||||
struct stliport *portp = tty->driver_data;
|
||||
|
||||
if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
|
||||
return -EFAULT;
|
||||
|
|
@ -1594,7 +1595,7 @@ static int stli_setserial(struct stliport *portp, struct serial_struct __user *s
|
|||
portp->closing_wait = sio.closing_wait;
|
||||
portp->custom_divisor = sio.custom_divisor;
|
||||
|
||||
if ((rc = stli_setport(portp)) < 0)
|
||||
if ((rc = stli_setport(tty)) < 0)
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1685,17 +1686,17 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
|
|||
rc = stli_getserial(portp, argp);
|
||||
break;
|
||||
case TIOCSSERIAL:
|
||||
rc = stli_setserial(portp, argp);
|
||||
rc = stli_setserial(tty, argp);
|
||||
break;
|
||||
case STL_GETPFLAG:
|
||||
rc = put_user(portp->pflag, (unsigned __user *)argp);
|
||||
break;
|
||||
case STL_SETPFLAG:
|
||||
if ((rc = get_user(portp->pflag, (unsigned __user *)argp)) == 0)
|
||||
stli_setport(portp);
|
||||
stli_setport(tty);
|
||||
break;
|
||||
case COM_GETPORTSTATS:
|
||||
rc = stli_getportstats(portp, argp);
|
||||
rc = stli_getportstats(tty, portp, argp);
|
||||
break;
|
||||
case COM_CLRPORTSTATS:
|
||||
rc = stli_clrportstats(portp, argp);
|
||||
|
|
@ -1729,8 +1730,6 @@ static void stli_settermios(struct tty_struct *tty, struct ktermios *old)
|
|||
struct ktermios *tiosp;
|
||||
asyport_t aport;
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return;
|
||||
|
|
@ -1742,7 +1741,7 @@ static void stli_settermios(struct tty_struct *tty, struct ktermios *old)
|
|||
|
||||
tiosp = tty->termios;
|
||||
|
||||
stli_mkasyport(portp, &aport, tiosp);
|
||||
stli_mkasyport(tty, portp, &aport, tiosp);
|
||||
stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0);
|
||||
stli_mkasysigs(&portp->asig, ((tiosp->c_cflag & CBAUD) ? 1 : 0), -1);
|
||||
stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
|
||||
|
|
@ -1854,7 +1853,7 @@ static void stli_hangup(struct tty_struct *tty)
|
|||
clear_bit(ST_TXBUSY, &portp->state);
|
||||
clear_bit(ST_RXSTOP, &portp->state);
|
||||
set_bit(TTY_IO_ERROR, &tty->flags);
|
||||
portp->port.tty = NULL;
|
||||
tty_port_tty_set(&portp->port, NULL);
|
||||
portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
|
||||
portp->port.count = 0;
|
||||
spin_unlock_irqrestore(&stli_lock, flags);
|
||||
|
|
@ -1935,8 +1934,6 @@ static void stli_waituntilsent(struct tty_struct *tty, int timeout)
|
|||
struct stliport *portp;
|
||||
unsigned long tend;
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return;
|
||||
|
|
@ -1998,7 +1995,7 @@ static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portn
|
|||
char *sp, *uart;
|
||||
int rc, cnt;
|
||||
|
||||
rc = stli_portcmdstats(portp);
|
||||
rc = stli_portcmdstats(NULL, portp);
|
||||
|
||||
uart = "UNKNOWN";
|
||||
if (brdp->state & BST_STARTED) {
|
||||
|
|
@ -2188,7 +2185,7 @@ static void stli_read(struct stlibrd *brdp, struct stliport *portp)
|
|||
|
||||
if (test_bit(ST_RXSTOP, &portp->state))
|
||||
return;
|
||||
tty = portp->port.tty;
|
||||
tty = tty_port_tty_get(&portp->port);
|
||||
if (tty == NULL)
|
||||
return;
|
||||
|
||||
|
|
@ -2230,6 +2227,7 @@ static void stli_read(struct stlibrd *brdp, struct stliport *portp)
|
|||
set_bit(ST_RXING, &portp->state);
|
||||
|
||||
tty_schedule_flip(tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -2362,7 +2360,7 @@ static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp)
|
|||
if (ap->notify) {
|
||||
nt = ap->changed;
|
||||
ap->notify = 0;
|
||||
tty = portp->port.tty;
|
||||
tty = tty_port_tty_get(&portp->port);
|
||||
|
||||
if (nt.signal & SG_DCD) {
|
||||
oldsigs = portp->sigs;
|
||||
|
|
@ -2399,6 +2397,7 @@ static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp)
|
|||
tty_schedule_flip(tty);
|
||||
}
|
||||
}
|
||||
tty_kref_put(tty);
|
||||
|
||||
if (nt.data & DT_RXBUSY) {
|
||||
donerx++;
|
||||
|
|
@ -2535,14 +2534,15 @@ static void stli_poll(unsigned long arg)
|
|||
* the slave.
|
||||
*/
|
||||
|
||||
static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp)
|
||||
static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp,
|
||||
asyport_t *pp, struct ktermios *tiosp)
|
||||
{
|
||||
memset(pp, 0, sizeof(asyport_t));
|
||||
|
||||
/*
|
||||
* Start of by setting the baud, char size, parity and stop bit info.
|
||||
*/
|
||||
pp->baudout = tty_get_baud_rate(portp->port.tty);
|
||||
pp->baudout = tty_get_baud_rate(tty);
|
||||
if ((tiosp->c_cflag & CBAUD) == B38400) {
|
||||
if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
|
||||
pp->baudout = 57600;
|
||||
|
|
@ -2695,7 +2695,7 @@ static int stli_initports(struct stlibrd *brdp)
|
|||
printk("STALLION: failed to allocate port structure\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
tty_port_init(&portp->port);
|
||||
portp->magic = STLI_PORTMAGIC;
|
||||
portp->portnr = i;
|
||||
portp->brdnr = brdp->brdnr;
|
||||
|
|
@ -4220,7 +4220,7 @@ static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr,
|
|||
* what port to get stats for (used through board control device).
|
||||
*/
|
||||
|
||||
static int stli_portcmdstats(struct stliport *portp)
|
||||
static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct stlibrd *brdp;
|
||||
|
|
@ -4249,15 +4249,15 @@ static int stli_portcmdstats(struct stliport *portp)
|
|||
stli_comstats.flags = portp->port.flags;
|
||||
|
||||
spin_lock_irqsave(&brd_lock, flags);
|
||||
if (portp->port.tty != NULL) {
|
||||
if (portp->port.tty->driver_data == portp) {
|
||||
stli_comstats.ttystate = portp->port.tty->flags;
|
||||
if (tty != NULL) {
|
||||
if (portp->port.tty == tty) {
|
||||
stli_comstats.ttystate = tty->flags;
|
||||
stli_comstats.rxbuffered = -1;
|
||||
if (portp->port.tty->termios != NULL) {
|
||||
stli_comstats.cflags = portp->port.tty->termios->c_cflag;
|
||||
stli_comstats.iflags = portp->port.tty->termios->c_iflag;
|
||||
stli_comstats.oflags = portp->port.tty->termios->c_oflag;
|
||||
stli_comstats.lflags = portp->port.tty->termios->c_lflag;
|
||||
if (tty->termios != NULL) {
|
||||
stli_comstats.cflags = tty->termios->c_cflag;
|
||||
stli_comstats.iflags = tty->termios->c_iflag;
|
||||
stli_comstats.oflags = tty->termios->c_oflag;
|
||||
stli_comstats.lflags = tty->termios->c_lflag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4294,7 +4294,8 @@ static int stli_portcmdstats(struct stliport *portp)
|
|||
* what port to get stats for (used through board control device).
|
||||
*/
|
||||
|
||||
static int stli_getportstats(struct stliport *portp, comstats_t __user *cp)
|
||||
static int stli_getportstats(struct tty_struct *tty, struct stliport *portp,
|
||||
comstats_t __user *cp)
|
||||
{
|
||||
struct stlibrd *brdp;
|
||||
int rc;
|
||||
|
|
@ -4312,7 +4313,7 @@ static int stli_getportstats(struct stliport *portp, comstats_t __user *cp)
|
|||
if (!brdp)
|
||||
return -ENODEV;
|
||||
|
||||
if ((rc = stli_portcmdstats(portp)) < 0)
|
||||
if ((rc = stli_portcmdstats(tty, portp)) < 0)
|
||||
return rc;
|
||||
|
||||
return copy_to_user(cp, &stli_comstats, sizeof(comstats_t)) ?
|
||||
|
|
@ -4427,7 +4428,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
|
|||
|
||||
switch (cmd) {
|
||||
case COM_GETPORTSTATS:
|
||||
rc = stli_getportstats(NULL, argp);
|
||||
rc = stli_getportstats(NULL, NULL, argp);
|
||||
done++;
|
||||
break;
|
||||
case COM_CLRPORTSTATS:
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
|
|||
static void moxa_poll(unsigned long);
|
||||
static void moxa_set_tty_param(struct tty_struct *, struct ktermios *);
|
||||
static void moxa_setup_empty_event(struct tty_struct *);
|
||||
static void moxa_shut_down(struct moxa_port *);
|
||||
static void moxa_shut_down(struct tty_struct *);
|
||||
/*
|
||||
* moxa board interface functions:
|
||||
*/
|
||||
|
|
@ -217,7 +217,7 @@ static void MoxaPortLineCtrl(struct moxa_port *, int, int);
|
|||
static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int);
|
||||
static int MoxaPortLineStatus(struct moxa_port *);
|
||||
static void MoxaPortFlushData(struct moxa_port *, int);
|
||||
static int MoxaPortWriteData(struct moxa_port *, const unsigned char *, int);
|
||||
static int MoxaPortWriteData(struct tty_struct *, const unsigned char *, int);
|
||||
static int MoxaPortReadData(struct moxa_port *);
|
||||
static int MoxaPortTxQueue(struct moxa_port *);
|
||||
static int MoxaPortRxQueue(struct moxa_port *);
|
||||
|
|
@ -332,6 +332,7 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file,
|
|||
for (i = 0; i < MAX_BOARDS; i++) {
|
||||
p = moxa_boards[i].ports;
|
||||
for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
|
||||
struct tty_struct *ttyp;
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
if (!moxa_boards[i].ready)
|
||||
goto copy;
|
||||
|
|
@ -344,10 +345,12 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file,
|
|||
if (status & 4)
|
||||
tmp.dcd = 1;
|
||||
|
||||
if (!p->port.tty || !p->port.tty->termios)
|
||||
ttyp = tty_port_tty_get(&p->port);
|
||||
if (!ttyp || !ttyp->termios)
|
||||
tmp.cflag = p->cflag;
|
||||
else
|
||||
tmp.cflag = p->port.tty->termios->c_cflag;
|
||||
tmp.cflag = ttyp->termios->c_cflag;
|
||||
tty_kref_put(tty);
|
||||
copy:
|
||||
if (copy_to_user(argm, &tmp, sizeof(tmp))) {
|
||||
mutex_unlock(&moxa_openlock);
|
||||
|
|
@ -880,8 +883,14 @@ static void moxa_board_deinit(struct moxa_board_conf *brd)
|
|||
|
||||
/* pci hot-un-plug support */
|
||||
for (a = 0; a < brd->numPorts; a++)
|
||||
if (brd->ports[a].port.flags & ASYNC_INITIALIZED)
|
||||
tty_hangup(brd->ports[a].port.tty);
|
||||
if (brd->ports[a].port.flags & ASYNC_INITIALIZED) {
|
||||
struct tty_struct *tty = tty_port_tty_get(
|
||||
&brd->ports[a].port);
|
||||
if (tty) {
|
||||
tty_hangup(tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
}
|
||||
while (1) {
|
||||
opened = 0;
|
||||
for (a = 0; a < brd->numPorts; a++)
|
||||
|
|
@ -1096,13 +1105,14 @@ static void __exit moxa_exit(void)
|
|||
module_init(moxa_init);
|
||||
module_exit(moxa_exit);
|
||||
|
||||
static void moxa_close_port(struct moxa_port *ch)
|
||||
static void moxa_close_port(struct tty_struct *tty)
|
||||
{
|
||||
moxa_shut_down(ch);
|
||||
struct moxa_port *ch = tty->driver_data;
|
||||
moxa_shut_down(tty);
|
||||
MoxaPortFlushData(ch, 2);
|
||||
ch->port.flags &= ~ASYNC_NORMAL_ACTIVE;
|
||||
ch->port.tty->driver_data = NULL;
|
||||
ch->port.tty = NULL;
|
||||
tty->driver_data = NULL;
|
||||
tty_port_tty_set(&ch->port, NULL);
|
||||
}
|
||||
|
||||
static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
|
||||
|
|
@ -1161,7 +1171,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
|
|||
ch = &brd->ports[port % MAX_PORTS_PER_BOARD];
|
||||
ch->port.count++;
|
||||
tty->driver_data = ch;
|
||||
ch->port.tty = tty;
|
||||
tty_port_tty_set(&ch->port, tty);
|
||||
if (!(ch->port.flags & ASYNC_INITIALIZED)) {
|
||||
ch->statusflags = 0;
|
||||
moxa_set_tty_param(tty, tty->termios);
|
||||
|
|
@ -1179,7 +1189,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
|
|||
if (retval) {
|
||||
if (ch->port.count) /* 0 means already hung up... */
|
||||
if (--ch->port.count == 0)
|
||||
moxa_close_port(ch);
|
||||
moxa_close_port(tty);
|
||||
} else
|
||||
ch->port.flags |= ASYNC_NORMAL_ACTIVE;
|
||||
mutex_unlock(&moxa_openlock);
|
||||
|
|
@ -1219,7 +1229,7 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
|
|||
tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */
|
||||
}
|
||||
|
||||
moxa_close_port(ch);
|
||||
moxa_close_port(tty);
|
||||
unlock:
|
||||
mutex_unlock(&moxa_openlock);
|
||||
}
|
||||
|
|
@ -1234,7 +1244,7 @@ static int moxa_write(struct tty_struct *tty,
|
|||
return 0;
|
||||
|
||||
spin_lock_bh(&moxa_lock);
|
||||
len = MoxaPortWriteData(ch, buf, count);
|
||||
len = MoxaPortWriteData(tty, buf, count);
|
||||
spin_unlock_bh(&moxa_lock);
|
||||
|
||||
ch->statusflags |= LOWWAIT;
|
||||
|
|
@ -1409,7 +1419,7 @@ static void moxa_hangup(struct tty_struct *tty)
|
|||
return;
|
||||
}
|
||||
ch->port.count = 0;
|
||||
moxa_close_port(ch);
|
||||
moxa_close_port(tty);
|
||||
mutex_unlock(&moxa_openlock);
|
||||
|
||||
wake_up_interruptible(&ch->port.open_wait);
|
||||
|
|
@ -1417,11 +1427,14 @@ static void moxa_hangup(struct tty_struct *tty)
|
|||
|
||||
static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
|
||||
{
|
||||
struct tty_struct *tty;
|
||||
dcd = !!dcd;
|
||||
|
||||
if (dcd != p->DCDState && p->port.tty && C_CLOCAL(p->port.tty)) {
|
||||
if (!dcd)
|
||||
tty_hangup(p->port.tty);
|
||||
if (dcd != p->DCDState) {
|
||||
tty = tty_port_tty_get(&p->port);
|
||||
if (tty && C_CLOCAL(tty) && !dcd)
|
||||
tty_hangup(tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
p->DCDState = dcd;
|
||||
}
|
||||
|
|
@ -1429,7 +1442,7 @@ static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
|
|||
static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
|
||||
u16 __iomem *ip)
|
||||
{
|
||||
struct tty_struct *tty = p->port.tty;
|
||||
struct tty_struct *tty = tty_port_tty_get(&p->port);
|
||||
void __iomem *ofsAddr;
|
||||
unsigned int inited = p->port.flags & ASYNC_INITIALIZED;
|
||||
u16 intr;
|
||||
|
|
@ -1476,6 +1489,7 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
|
|||
tty_insert_flip_char(tty, 0, TTY_BREAK);
|
||||
tty_schedule_flip(tty);
|
||||
}
|
||||
tty_kref_put(tty);
|
||||
|
||||
if (intr & IntrLine)
|
||||
moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state);
|
||||
|
|
@ -1560,9 +1574,9 @@ static void moxa_setup_empty_event(struct tty_struct *tty)
|
|||
spin_unlock_bh(&moxa_lock);
|
||||
}
|
||||
|
||||
static void moxa_shut_down(struct moxa_port *ch)
|
||||
static void moxa_shut_down(struct tty_struct *tty)
|
||||
{
|
||||
struct tty_struct *tp = ch->port.tty;
|
||||
struct moxa_port *ch = tty->driver_data;
|
||||
|
||||
if (!(ch->port.flags & ASYNC_INITIALIZED))
|
||||
return;
|
||||
|
|
@ -1572,7 +1586,7 @@ static void moxa_shut_down(struct moxa_port *ch)
|
|||
/*
|
||||
* If we're a modem control device and HUPCL is on, drop RTS & DTR.
|
||||
*/
|
||||
if (C_HUPCL(tp))
|
||||
if (C_HUPCL(tty))
|
||||
MoxaPortLineCtrl(ch, 0, 0);
|
||||
|
||||
spin_lock_bh(&moxa_lock);
|
||||
|
|
@ -1953,9 +1967,10 @@ static int MoxaPortLineStatus(struct moxa_port *port)
|
|||
return val;
|
||||
}
|
||||
|
||||
static int MoxaPortWriteData(struct moxa_port *port,
|
||||
static int MoxaPortWriteData(struct tty_struct *tty,
|
||||
const unsigned char *buffer, int len)
|
||||
{
|
||||
struct moxa_port *port = tty->driver_data;
|
||||
void __iomem *baseAddr, *ofsAddr, *ofs;
|
||||
unsigned int c, total;
|
||||
u16 head, tail, tx_mask, spage, epage;
|
||||
|
|
|
|||
|
|
@ -610,15 +610,13 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mxser_set_baud(struct mxser_port *info, long newspd)
|
||||
static int mxser_set_baud(struct tty_struct *tty, long newspd)
|
||||
{
|
||||
struct mxser_port *info = tty->driver_data;
|
||||
int quot = 0, baud;
|
||||
unsigned char cval;
|
||||
|
||||
if (!info->port.tty || !info->port.tty->termios)
|
||||
return -1;
|
||||
|
||||
if (!(info->ioaddr))
|
||||
if (!info->ioaddr)
|
||||
return -1;
|
||||
|
||||
if (newspd > info->max_baud)
|
||||
|
|
@ -626,13 +624,13 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
|
|||
|
||||
if (newspd == 134) {
|
||||
quot = 2 * info->baud_base / 269;
|
||||
tty_encode_baud_rate(info->port.tty, 134, 134);
|
||||
tty_encode_baud_rate(tty, 134, 134);
|
||||
} else if (newspd) {
|
||||
quot = info->baud_base / newspd;
|
||||
if (quot == 0)
|
||||
quot = 1;
|
||||
baud = info->baud_base/quot;
|
||||
tty_encode_baud_rate(info->port.tty, baud, baud);
|
||||
tty_encode_baud_rate(tty, baud, baud);
|
||||
} else {
|
||||
quot = 0;
|
||||
}
|
||||
|
|
@ -658,7 +656,7 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
|
|||
outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */
|
||||
|
||||
#ifdef BOTHER
|
||||
if (C_BAUD(info->port.tty) == BOTHER) {
|
||||
if (C_BAUD(tty) == BOTHER) {
|
||||
quot = info->baud_base % newspd;
|
||||
quot *= 8;
|
||||
if (quot % newspd > newspd / 2) {
|
||||
|
|
@ -679,21 +677,20 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
|
|||
* This routine is called to set the UART divisor registers to match
|
||||
* the specified baud rate for a serial port.
|
||||
*/
|
||||
static int mxser_change_speed(struct mxser_port *info,
|
||||
struct ktermios *old_termios)
|
||||
static int mxser_change_speed(struct tty_struct *tty,
|
||||
struct ktermios *old_termios)
|
||||
{
|
||||
struct mxser_port *info = tty->driver_data;
|
||||
unsigned cflag, cval, fcr;
|
||||
int ret = 0;
|
||||
unsigned char status;
|
||||
|
||||
if (!info->port.tty || !info->port.tty->termios)
|
||||
return ret;
|
||||
cflag = info->port.tty->termios->c_cflag;
|
||||
if (!(info->ioaddr))
|
||||
cflag = tty->termios->c_cflag;
|
||||
if (!info->ioaddr)
|
||||
return ret;
|
||||
|
||||
if (mxser_set_baud_method[info->port.tty->index] == 0)
|
||||
mxser_set_baud(info, tty_get_baud_rate(info->port.tty));
|
||||
if (mxser_set_baud_method[tty->index] == 0)
|
||||
mxser_set_baud(tty, tty_get_baud_rate(tty));
|
||||
|
||||
/* byte size and parity */
|
||||
switch (cflag & CSIZE) {
|
||||
|
|
@ -762,9 +759,9 @@ static int mxser_change_speed(struct mxser_port *info,
|
|||
info->MCR |= UART_MCR_AFE;
|
||||
} else {
|
||||
status = inb(info->ioaddr + UART_MSR);
|
||||
if (info->port.tty->hw_stopped) {
|
||||
if (tty->hw_stopped) {
|
||||
if (status & UART_MSR_CTS) {
|
||||
info->port.tty->hw_stopped = 0;
|
||||
tty->hw_stopped = 0;
|
||||
if (info->type != PORT_16550A &&
|
||||
!info->board->chip_flag) {
|
||||
outb(info->IER & ~UART_IER_THRI,
|
||||
|
|
@ -774,11 +771,11 @@ static int mxser_change_speed(struct mxser_port *info,
|
|||
outb(info->IER, info->ioaddr +
|
||||
UART_IER);
|
||||
}
|
||||
tty_wakeup(info->port.tty);
|
||||
tty_wakeup(tty);
|
||||
}
|
||||
} else {
|
||||
if (!(status & UART_MSR_CTS)) {
|
||||
info->port.tty->hw_stopped = 1;
|
||||
tty->hw_stopped = 1;
|
||||
if ((info->type != PORT_16550A) &&
|
||||
(!info->board->chip_flag)) {
|
||||
info->IER &= ~UART_IER_THRI;
|
||||
|
|
@ -804,21 +801,21 @@ static int mxser_change_speed(struct mxser_port *info,
|
|||
* Set up parity check flag
|
||||
*/
|
||||
info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
|
||||
if (I_INPCK(info->port.tty))
|
||||
if (I_INPCK(tty))
|
||||
info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
|
||||
if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
|
||||
if (I_BRKINT(tty) || I_PARMRK(tty))
|
||||
info->read_status_mask |= UART_LSR_BI;
|
||||
|
||||
info->ignore_status_mask = 0;
|
||||
|
||||
if (I_IGNBRK(info->port.tty)) {
|
||||
if (I_IGNBRK(tty)) {
|
||||
info->ignore_status_mask |= UART_LSR_BI;
|
||||
info->read_status_mask |= UART_LSR_BI;
|
||||
/*
|
||||
* If we're ignore parity and break indicators, ignore
|
||||
* overruns too. (For real raw support).
|
||||
*/
|
||||
if (I_IGNPAR(info->port.tty)) {
|
||||
if (I_IGNPAR(tty)) {
|
||||
info->ignore_status_mask |=
|
||||
UART_LSR_OE |
|
||||
UART_LSR_PE |
|
||||
|
|
@ -830,16 +827,16 @@ static int mxser_change_speed(struct mxser_port *info,
|
|||
}
|
||||
}
|
||||
if (info->board->chip_flag) {
|
||||
mxser_set_must_xon1_value(info->ioaddr, START_CHAR(info->port.tty));
|
||||
mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(info->port.tty));
|
||||
if (I_IXON(info->port.tty)) {
|
||||
mxser_set_must_xon1_value(info->ioaddr, START_CHAR(tty));
|
||||
mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(tty));
|
||||
if (I_IXON(tty)) {
|
||||
mxser_enable_must_rx_software_flow_control(
|
||||
info->ioaddr);
|
||||
} else {
|
||||
mxser_disable_must_rx_software_flow_control(
|
||||
info->ioaddr);
|
||||
}
|
||||
if (I_IXOFF(info->port.tty)) {
|
||||
if (I_IXOFF(tty)) {
|
||||
mxser_enable_must_tx_software_flow_control(
|
||||
info->ioaddr);
|
||||
} else {
|
||||
|
|
@ -855,7 +852,8 @@ static int mxser_change_speed(struct mxser_port *info,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void mxser_check_modem_status(struct mxser_port *port, int status)
|
||||
static void mxser_check_modem_status(struct tty_struct *tty,
|
||||
struct mxser_port *port, int status)
|
||||
{
|
||||
/* update input line counters */
|
||||
if (status & UART_MSR_TERI)
|
||||
|
|
@ -874,10 +872,11 @@ static void mxser_check_modem_status(struct mxser_port *port, int status)
|
|||
wake_up_interruptible(&port->port.open_wait);
|
||||
}
|
||||
|
||||
tty = tty_port_tty_get(&port->port);
|
||||
if (port->port.flags & ASYNC_CTS_FLOW) {
|
||||
if (port->port.tty->hw_stopped) {
|
||||
if (tty->hw_stopped) {
|
||||
if (status & UART_MSR_CTS) {
|
||||
port->port.tty->hw_stopped = 0;
|
||||
tty->hw_stopped = 0;
|
||||
|
||||
if ((port->type != PORT_16550A) &&
|
||||
(!port->board->chip_flag)) {
|
||||
|
|
@ -887,11 +886,11 @@ static void mxser_check_modem_status(struct mxser_port *port, int status)
|
|||
outb(port->IER, port->ioaddr +
|
||||
UART_IER);
|
||||
}
|
||||
tty_wakeup(port->port.tty);
|
||||
tty_wakeup(tty);
|
||||
}
|
||||
} else {
|
||||
if (!(status & UART_MSR_CTS)) {
|
||||
port->port.tty->hw_stopped = 1;
|
||||
tty->hw_stopped = 1;
|
||||
if (port->type != PORT_16550A &&
|
||||
!port->board->chip_flag) {
|
||||
port->IER &= ~UART_IER_THRI;
|
||||
|
|
@ -903,8 +902,9 @@ static void mxser_check_modem_status(struct mxser_port *port, int status)
|
|||
}
|
||||
}
|
||||
|
||||
static int mxser_startup(struct mxser_port *info)
|
||||
static int mxser_startup(struct tty_struct *tty)
|
||||
{
|
||||
struct mxser_port *info = tty->driver_data;
|
||||
unsigned long page;
|
||||
unsigned long flags;
|
||||
|
||||
|
|
@ -921,8 +921,7 @@ static int mxser_startup(struct mxser_port *info)
|
|||
}
|
||||
|
||||
if (!info->ioaddr || !info->type) {
|
||||
if (info->port.tty)
|
||||
set_bit(TTY_IO_ERROR, &info->port.tty->flags);
|
||||
set_bit(TTY_IO_ERROR, &tty->flags);
|
||||
free_page(page);
|
||||
spin_unlock_irqrestore(&info->slock, flags);
|
||||
return 0;
|
||||
|
|
@ -952,8 +951,8 @@ static int mxser_startup(struct mxser_port *info)
|
|||
if (inb(info->ioaddr + UART_LSR) == 0xff) {
|
||||
spin_unlock_irqrestore(&info->slock, flags);
|
||||
if (capable(CAP_SYS_ADMIN)) {
|
||||
if (info->port.tty)
|
||||
set_bit(TTY_IO_ERROR, &info->port.tty->flags);
|
||||
if (tty)
|
||||
set_bit(TTY_IO_ERROR, &tty->flags);
|
||||
return 0;
|
||||
} else
|
||||
return -ENODEV;
|
||||
|
|
@ -991,14 +990,13 @@ static int mxser_startup(struct mxser_port *info)
|
|||
(void) inb(info->ioaddr + UART_IIR);
|
||||
(void) inb(info->ioaddr + UART_MSR);
|
||||
|
||||
if (info->port.tty)
|
||||
clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
|
||||
clear_bit(TTY_IO_ERROR, &tty->flags);
|
||||
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
|
||||
|
||||
/*
|
||||
* and set the speed of the serial port
|
||||
*/
|
||||
mxser_change_speed(info, NULL);
|
||||
mxser_change_speed(tty, NULL);
|
||||
info->port.flags |= ASYNC_INITIALIZED;
|
||||
spin_unlock_irqrestore(&info->slock, flags);
|
||||
|
||||
|
|
@ -1009,8 +1007,9 @@ static int mxser_startup(struct mxser_port *info)
|
|||
* This routine will shutdown a serial port; interrupts maybe disabled, and
|
||||
* DTR is dropped if the hangup on close termio flag is on.
|
||||
*/
|
||||
static void mxser_shutdown(struct mxser_port *info)
|
||||
static void mxser_shutdown(struct tty_struct *tty)
|
||||
{
|
||||
struct mxser_port *info = tty->driver_data;
|
||||
unsigned long flags;
|
||||
|
||||
if (!(info->port.flags & ASYNC_INITIALIZED))
|
||||
|
|
@ -1035,7 +1034,7 @@ static void mxser_shutdown(struct mxser_port *info)
|
|||
info->IER = 0;
|
||||
outb(0x00, info->ioaddr + UART_IER);
|
||||
|
||||
if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL))
|
||||
if (tty->termios->c_cflag & HUPCL)
|
||||
info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
|
||||
outb(info->MCR, info->ioaddr + UART_MCR);
|
||||
|
||||
|
|
@ -1051,8 +1050,7 @@ static void mxser_shutdown(struct mxser_port *info)
|
|||
/* read data port to reset things */
|
||||
(void) inb(info->ioaddr + UART_RX);
|
||||
|
||||
if (info->port.tty)
|
||||
set_bit(TTY_IO_ERROR, &info->port.tty->flags);
|
||||
set_bit(TTY_IO_ERROR, &tty->flags);
|
||||
|
||||
info->port.flags &= ~ASYNC_INITIALIZED;
|
||||
|
||||
|
|
@ -1084,14 +1082,14 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
|
|||
return -ENODEV;
|
||||
|
||||
tty->driver_data = info;
|
||||
info->port.tty = tty;
|
||||
tty_port_tty_set(&info->port, tty);
|
||||
/*
|
||||
* Start up serial port
|
||||
*/
|
||||
spin_lock_irqsave(&info->slock, flags);
|
||||
info->port.count++;
|
||||
spin_unlock_irqrestore(&info->slock, flags);
|
||||
retval = mxser_startup(info);
|
||||
retval = mxser_startup(tty);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
|
|
@ -1209,13 +1207,13 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
|
|||
break;
|
||||
}
|
||||
}
|
||||
mxser_shutdown(info);
|
||||
mxser_shutdown(tty);
|
||||
|
||||
mxser_flush_buffer(tty);
|
||||
tty_ldisc_flush(tty);
|
||||
|
||||
tty->closing = 0;
|
||||
info->port.tty = NULL;
|
||||
tty_port_tty_set(&info->port, NULL);
|
||||
if (info->port.blocked_open) {
|
||||
if (info->port.close_delay)
|
||||
schedule_timeout_interruptible(info->port.close_delay);
|
||||
|
|
@ -1337,12 +1335,13 @@ static int mxser_chars_in_buffer(struct tty_struct *tty)
|
|||
* friends of mxser_ioctl()
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
static int mxser_get_serial_info(struct mxser_port *info,
|
||||
static int mxser_get_serial_info(struct tty_struct *tty,
|
||||
struct serial_struct __user *retinfo)
|
||||
{
|
||||
struct mxser_port *info = tty->driver_data;
|
||||
struct serial_struct tmp = {
|
||||
.type = info->type,
|
||||
.line = info->port.tty->index,
|
||||
.line = tty->index,
|
||||
.port = info->ioaddr,
|
||||
.irq = info->board->irq,
|
||||
.flags = info->port.flags,
|
||||
|
|
@ -1357,9 +1356,10 @@ static int mxser_get_serial_info(struct mxser_port *info,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mxser_set_serial_info(struct mxser_port *info,
|
||||
static int mxser_set_serial_info(struct tty_struct *tty,
|
||||
struct serial_struct __user *new_info)
|
||||
{
|
||||
struct mxser_port *info = tty->driver_data;
|
||||
struct serial_struct new_serial;
|
||||
speed_t baud;
|
||||
unsigned long sl_flags;
|
||||
|
|
@ -1393,14 +1393,14 @@ static int mxser_set_serial_info(struct mxser_port *info,
|
|||
(new_serial.flags & ASYNC_FLAGS));
|
||||
info->port.close_delay = new_serial.close_delay * HZ / 100;
|
||||
info->port.closing_wait = new_serial.closing_wait * HZ / 100;
|
||||
info->port.tty->low_latency =
|
||||
(info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
|
||||
tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY)
|
||||
? 1 : 0;
|
||||
if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
|
||||
(new_serial.baud_base != info->baud_base ||
|
||||
new_serial.custom_divisor !=
|
||||
info->custom_divisor)) {
|
||||
baud = new_serial.baud_base / new_serial.custom_divisor;
|
||||
tty_encode_baud_rate(info->port.tty, baud, baud);
|
||||
tty_encode_baud_rate(tty, baud, baud);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1411,11 +1411,11 @@ static int mxser_set_serial_info(struct mxser_port *info,
|
|||
if (info->port.flags & ASYNC_INITIALIZED) {
|
||||
if (flags != (info->port.flags & ASYNC_SPD_MASK)) {
|
||||
spin_lock_irqsave(&info->slock, sl_flags);
|
||||
mxser_change_speed(info, NULL);
|
||||
mxser_change_speed(tty, NULL);
|
||||
spin_unlock_irqrestore(&info->slock, sl_flags);
|
||||
}
|
||||
} else
|
||||
retval = mxser_startup(info);
|
||||
retval = mxser_startup(tty);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -1461,7 +1461,7 @@ static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
|
|||
spin_lock_irqsave(&info->slock, flags);
|
||||
status = inb(info->ioaddr + UART_MSR);
|
||||
if (status & UART_MSR_ANY_DELTA)
|
||||
mxser_check_modem_status(info, status);
|
||||
mxser_check_modem_status(tty, info, status);
|
||||
spin_unlock_irqrestore(&info->slock, flags);
|
||||
return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
|
||||
((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
|
||||
|
|
@ -1606,6 +1606,7 @@ static int __init mxser_read_register(int port, unsigned short *regs)
|
|||
static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
|
||||
{
|
||||
struct mxser_port *port;
|
||||
struct tty_struct *tty;
|
||||
int result, status;
|
||||
unsigned int i, j;
|
||||
int ret = 0;
|
||||
|
|
@ -1643,12 +1644,14 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
|
|||
|
||||
if (!port->ioaddr)
|
||||
goto copy;
|
||||
|
||||
tty = tty_port_tty_get(&port->port);
|
||||
|
||||
if (!port->port.tty || !port->port.tty->termios)
|
||||
if (!tty || !tty->termios)
|
||||
ms.cflag = port->normal_termios.c_cflag;
|
||||
else
|
||||
ms.cflag = port->port.tty->termios->c_cflag;
|
||||
|
||||
ms.cflag = tty->termios->c_cflag;
|
||||
tty_kref_put(tty);
|
||||
status = inb(port->ioaddr + UART_MSR);
|
||||
if (status & UART_MSR_DCD)
|
||||
ms.dcd = 1;
|
||||
|
|
@ -1704,15 +1707,18 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
|
|||
me->up_txcnt[p] = port->mon_data.up_txcnt;
|
||||
me->modem_status[p] =
|
||||
port->mon_data.modem_status;
|
||||
me->baudrate[p] = tty_get_baud_rate(port->port.tty);
|
||||
tty = tty_port_tty_get(&port->port);
|
||||
|
||||
if (!port->port.tty || !port->port.tty->termios) {
|
||||
if (!tty || !tty->termios) {
|
||||
cflag = port->normal_termios.c_cflag;
|
||||
iflag = port->normal_termios.c_iflag;
|
||||
me->baudrate[p] = tty_termios_baud_rate(&port->normal_termios);
|
||||
} else {
|
||||
cflag = port->port.tty->termios->c_cflag;
|
||||
iflag = port->port.tty->termios->c_iflag;
|
||||
cflag = tty->termios->c_cflag;
|
||||
iflag = tty->termios->c_iflag;
|
||||
me->baudrate[p] = tty_get_baud_rate(tty);
|
||||
}
|
||||
tty_kref_put(tty);
|
||||
|
||||
me->databits[p] = cflag & CSIZE;
|
||||
me->stopbits[p] = cflag & CSTOPB;
|
||||
|
|
@ -1822,12 +1828,12 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
|
|||
switch (cmd) {
|
||||
case TIOCGSERIAL:
|
||||
lock_kernel();
|
||||
retval = mxser_get_serial_info(info, argp);
|
||||
retval = mxser_get_serial_info(tty, argp);
|
||||
unlock_kernel();
|
||||
return retval;
|
||||
case TIOCSSERIAL:
|
||||
lock_kernel();
|
||||
retval = mxser_set_serial_info(info, argp);
|
||||
retval = mxser_set_serial_info(tty, argp);
|
||||
unlock_kernel();
|
||||
return retval;
|
||||
case TIOCSERGETLSR: /* Get line status register */
|
||||
|
|
@ -1896,7 +1902,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
|
|||
|
||||
lock_kernel();
|
||||
status = mxser_get_msr(info->ioaddr, 1, tty->index);
|
||||
mxser_check_modem_status(info, status);
|
||||
mxser_check_modem_status(tty, info, status);
|
||||
|
||||
mcr = inb(info->ioaddr + UART_MCR);
|
||||
if (mcr & MOXA_MUST_MCR_XON_FLAG)
|
||||
|
|
@ -1909,7 +1915,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
|
|||
else
|
||||
info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT;
|
||||
|
||||
if (info->port.tty->hw_stopped)
|
||||
if (tty->hw_stopped)
|
||||
info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD;
|
||||
else
|
||||
info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD;
|
||||
|
|
@ -1958,7 +1964,7 @@ static void mxser_stoprx(struct tty_struct *tty)
|
|||
}
|
||||
}
|
||||
|
||||
if (info->port.tty->termios->c_cflag & CRTSCTS) {
|
||||
if (tty->termios->c_cflag & CRTSCTS) {
|
||||
info->MCR &= ~UART_MCR_RTS;
|
||||
outb(info->MCR, info->ioaddr + UART_MCR);
|
||||
}
|
||||
|
|
@ -1995,7 +2001,7 @@ static void mxser_unthrottle(struct tty_struct *tty)
|
|||
}
|
||||
}
|
||||
|
||||
if (info->port.tty->termios->c_cflag & CRTSCTS) {
|
||||
if (tty->termios->c_cflag & CRTSCTS) {
|
||||
info->MCR |= UART_MCR_RTS;
|
||||
outb(info->MCR, info->ioaddr + UART_MCR);
|
||||
}
|
||||
|
|
@ -2040,7 +2046,7 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&info->slock, flags);
|
||||
mxser_change_speed(info, old_termios);
|
||||
mxser_change_speed(tty, old_termios);
|
||||
spin_unlock_irqrestore(&info->slock, flags);
|
||||
|
||||
if ((old_termios->c_cflag & CRTSCTS) &&
|
||||
|
|
@ -2138,10 +2144,10 @@ static void mxser_hangup(struct tty_struct *tty)
|
|||
struct mxser_port *info = tty->driver_data;
|
||||
|
||||
mxser_flush_buffer(tty);
|
||||
mxser_shutdown(info);
|
||||
mxser_shutdown(tty);
|
||||
info->port.count = 0;
|
||||
info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
|
||||
info->port.tty = NULL;
|
||||
tty_port_tty_set(&info->port, NULL);
|
||||
wake_up_interruptible(&info->port.open_wait);
|
||||
}
|
||||
|
||||
|
|
@ -2164,9 +2170,9 @@ static int mxser_rs_break(struct tty_struct *tty, int break_state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void mxser_receive_chars(struct mxser_port *port, int *status)
|
||||
static void mxser_receive_chars(struct tty_struct *tty,
|
||||
struct mxser_port *port, int *status)
|
||||
{
|
||||
struct tty_struct *tty = port->port.tty;
|
||||
unsigned char ch, gdl;
|
||||
int ignored = 0;
|
||||
int cnt = 0;
|
||||
|
|
@ -2174,9 +2180,8 @@ static void mxser_receive_chars(struct mxser_port *port, int *status)
|
|||
int max = 256;
|
||||
|
||||
recv_room = tty->receive_room;
|
||||
if ((recv_room == 0) && (!port->ldisc_stop_rx))
|
||||
if (recv_room == 0 && !port->ldisc_stop_rx)
|
||||
mxser_stoprx(tty);
|
||||
|
||||
if (port->board->chip_flag != MOXA_OTHER_UART) {
|
||||
|
||||
if (*status & UART_LSR_SPECIAL)
|
||||
|
|
@ -2253,7 +2258,7 @@ intr_old:
|
|||
} while (*status & UART_LSR_DR);
|
||||
|
||||
end_intr:
|
||||
mxvar_log.rxcnt[port->port.tty->index] += cnt;
|
||||
mxvar_log.rxcnt[tty->index] += cnt;
|
||||
port->mon_data.rxcnt += cnt;
|
||||
port->mon_data.up_rxcnt += cnt;
|
||||
|
||||
|
|
@ -2267,14 +2272,14 @@ end_intr:
|
|||
spin_lock(&port->slock);
|
||||
}
|
||||
|
||||
static void mxser_transmit_chars(struct mxser_port *port)
|
||||
static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port)
|
||||
{
|
||||
int count, cnt;
|
||||
|
||||
if (port->x_char) {
|
||||
outb(port->x_char, port->ioaddr + UART_TX);
|
||||
port->x_char = 0;
|
||||
mxvar_log.txcnt[port->port.tty->index]++;
|
||||
mxvar_log.txcnt[tty->index]++;
|
||||
port->mon_data.txcnt++;
|
||||
port->mon_data.up_txcnt++;
|
||||
port->icount.tx++;
|
||||
|
|
@ -2284,8 +2289,8 @@ static void mxser_transmit_chars(struct mxser_port *port)
|
|||
if (port->port.xmit_buf == NULL)
|
||||
return;
|
||||
|
||||
if ((port->xmit_cnt <= 0) || port->port.tty->stopped ||
|
||||
(port->port.tty->hw_stopped &&
|
||||
if (port->xmit_cnt <= 0 || tty->stopped ||
|
||||
(tty->hw_stopped &&
|
||||
(port->type != PORT_16550A) &&
|
||||
(!port->board->chip_flag))) {
|
||||
port->IER &= ~UART_IER_THRI;
|
||||
|
|
@ -2302,14 +2307,14 @@ static void mxser_transmit_chars(struct mxser_port *port)
|
|||
if (--port->xmit_cnt <= 0)
|
||||
break;
|
||||
} while (--count > 0);
|
||||
mxvar_log.txcnt[port->port.tty->index] += (cnt - port->xmit_cnt);
|
||||
mxvar_log.txcnt[tty->index] += (cnt - port->xmit_cnt);
|
||||
|
||||
port->mon_data.txcnt += (cnt - port->xmit_cnt);
|
||||
port->mon_data.up_txcnt += (cnt - port->xmit_cnt);
|
||||
port->icount.tx += (cnt - port->xmit_cnt);
|
||||
|
||||
if (port->xmit_cnt < WAKEUP_CHARS)
|
||||
tty_wakeup(port->port.tty);
|
||||
if (port->xmit_cnt < WAKEUP_CHARS && tty)
|
||||
tty_wakeup(tty);
|
||||
|
||||
if (port->xmit_cnt <= 0) {
|
||||
port->IER &= ~UART_IER_THRI;
|
||||
|
|
@ -2328,6 +2333,7 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
|
|||
int max, irqbits, bits, msr;
|
||||
unsigned int int_cnt, pass_counter = 0;
|
||||
int handled = IRQ_NONE;
|
||||
struct tty_struct *tty;
|
||||
|
||||
for (i = 0; i < MXSER_BOARDS; i++)
|
||||
if (dev_id == &mxser_boards[i]) {
|
||||
|
|
@ -2360,13 +2366,15 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
|
|||
if (iir & UART_IIR_NO_INT)
|
||||
break;
|
||||
iir &= MOXA_MUST_IIR_MASK;
|
||||
if (!port->port.tty ||
|
||||
tty = tty_port_tty_get(&port->port);
|
||||
if (!tty ||
|
||||
(port->port.flags & ASYNC_CLOSING) ||
|
||||
!(port->port.flags &
|
||||
ASYNC_INITIALIZED)) {
|
||||
status = inb(port->ioaddr + UART_LSR);
|
||||
outb(0x27, port->ioaddr + UART_FCR);
|
||||
inb(port->ioaddr + UART_MSR);
|
||||
tty_kref_put(tty);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -2387,27 +2395,28 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
|
|||
iir == MOXA_MUST_IIR_RDA ||
|
||||
iir == MOXA_MUST_IIR_RTO ||
|
||||
iir == MOXA_MUST_IIR_LSR)
|
||||
mxser_receive_chars(port,
|
||||
mxser_receive_chars(tty, port,
|
||||
&status);
|
||||
|
||||
} else {
|
||||
status &= port->read_status_mask;
|
||||
if (status & UART_LSR_DR)
|
||||
mxser_receive_chars(port,
|
||||
mxser_receive_chars(tty, port,
|
||||
&status);
|
||||
}
|
||||
msr = inb(port->ioaddr + UART_MSR);
|
||||
if (msr & UART_MSR_ANY_DELTA)
|
||||
mxser_check_modem_status(port, msr);
|
||||
mxser_check_modem_status(tty, port, msr);
|
||||
|
||||
if (port->board->chip_flag) {
|
||||
if (iir == 0x02 && (status &
|
||||
UART_LSR_THRE))
|
||||
mxser_transmit_chars(port);
|
||||
mxser_transmit_chars(tty, port);
|
||||
} else {
|
||||
if (status & UART_LSR_THRE)
|
||||
mxser_transmit_chars(port);
|
||||
mxser_transmit_chars(tty, port);
|
||||
}
|
||||
tty_kref_put(tty);
|
||||
} while (int_cnt++ < MXSER_ISR_PASS_LIMIT);
|
||||
spin_unlock(&port->slock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -764,7 +764,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,
|
|||
break;
|
||||
|
||||
default:
|
||||
error = n_tty_ioctl (tty, file, cmd, arg);
|
||||
error = n_tty_ioctl_helper(tty, file, cmd, arg);
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
|
|
|
|||
|
|
@ -372,14 +372,8 @@ static void remove_from_rx_queue(struct r3964_info *pInfo,
|
|||
static void put_char(struct r3964_info *pInfo, unsigned char ch)
|
||||
{
|
||||
struct tty_struct *tty = pInfo->tty;
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
|
||||
/* FIXME: put_char should not be called from an IRQ */
|
||||
if (tty->ops->put_char) {
|
||||
tty->ops->put_char(tty, ch);
|
||||
}
|
||||
tty_put_char(tty, ch);
|
||||
pInfo->bcc ^= ch;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
*
|
||||
* 2002/03/18 Implemented n_tty_wakeup to send SIGIO POLL_OUTs to
|
||||
* waiting writing processes-Sapan Bhatia <sapan@corewars.org>.
|
||||
* Also fixed a bug in BLOCKING mode where write_chan returns
|
||||
* Also fixed a bug in BLOCKING mode where n_tty_write returns
|
||||
* EAGAIN
|
||||
*/
|
||||
|
||||
|
|
@ -99,6 +99,7 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
|
|||
|
||||
static void n_tty_set_room(struct tty_struct *tty)
|
||||
{
|
||||
/* tty->read_cnt is not read locked ? */
|
||||
int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
|
||||
|
||||
/*
|
||||
|
|
@ -121,6 +122,16 @@ static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* put_tty_queue - add character to tty
|
||||
* @c: character
|
||||
* @tty: tty device
|
||||
*
|
||||
* Add a character to the tty read_buf queue. This is done under the
|
||||
* read_lock to serialize character addition and also to protect us
|
||||
* against parallel reads or flushes
|
||||
*/
|
||||
|
||||
static void put_tty_queue(unsigned char c, struct tty_struct *tty)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
|
@ -137,14 +148,11 @@ static void put_tty_queue(unsigned char c, struct tty_struct *tty)
|
|||
* check_unthrottle - allow new receive data
|
||||
* @tty; tty device
|
||||
*
|
||||
* Check whether to call the driver.unthrottle function.
|
||||
* We test the TTY_THROTTLED bit first so that it always
|
||||
* indicates the current state. The decision about whether
|
||||
* it is worth allowing more input has been taken by the caller.
|
||||
* Check whether to call the driver unthrottle functions
|
||||
*
|
||||
* Can sleep, may be called under the atomic_read_lock mutex but
|
||||
* this is not guaranteed.
|
||||
*/
|
||||
|
||||
static void check_unthrottle(struct tty_struct *tty)
|
||||
{
|
||||
if (tty->count)
|
||||
|
|
@ -158,6 +166,8 @@ static void check_unthrottle(struct tty_struct *tty)
|
|||
* Reset the read buffer counters, clear the flags,
|
||||
* and make sure the driver is unthrottled. Called
|
||||
* from n_tty_open() and n_tty_flush_buffer().
|
||||
*
|
||||
* Locking: tty_read_lock for read fields.
|
||||
*/
|
||||
static void reset_buffer_flags(struct tty_struct *tty)
|
||||
{
|
||||
|
|
@ -181,7 +191,7 @@ static void reset_buffer_flags(struct tty_struct *tty)
|
|||
* at hangup) or when the N_TTY line discipline internally has to
|
||||
* clean the pending queue (for example some signals).
|
||||
*
|
||||
* Locking: ctrl_lock
|
||||
* Locking: ctrl_lock, read_lock.
|
||||
*/
|
||||
|
||||
static void n_tty_flush_buffer(struct tty_struct *tty)
|
||||
|
|
@ -207,6 +217,8 @@ static void n_tty_flush_buffer(struct tty_struct *tty)
|
|||
*
|
||||
* Report the number of characters buffered to be delivered to user
|
||||
* at this instant in time.
|
||||
*
|
||||
* Locking: read_lock
|
||||
*/
|
||||
|
||||
static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
|
||||
|
|
@ -346,7 +358,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
|
|||
* the simple cases normally found and helps to generate blocks of
|
||||
* symbols for the console driver and thus improve performance.
|
||||
*
|
||||
* Called from write_chan under the tty layer write lock. Relies
|
||||
* Called from n_tty_write under the tty layer write lock. Relies
|
||||
* on lock_kernel for the tty->column state.
|
||||
*/
|
||||
|
||||
|
|
@ -410,6 +422,8 @@ break_out:
|
|||
*
|
||||
* Echo user input back onto the screen. This must be called only when
|
||||
* L_ECHO(tty) is true. Called from the driver receive_buf path.
|
||||
*
|
||||
* Relies on BKL for tty column locking
|
||||
*/
|
||||
|
||||
static void echo_char(unsigned char c, struct tty_struct *tty)
|
||||
|
|
@ -422,6 +436,12 @@ static void echo_char(unsigned char c, struct tty_struct *tty)
|
|||
opost(c, tty);
|
||||
}
|
||||
|
||||
/**
|
||||
* finsh_erasing - complete erase
|
||||
* @tty: tty doing the erase
|
||||
*
|
||||
* Relies on BKL for tty column locking
|
||||
*/
|
||||
static inline void finish_erasing(struct tty_struct *tty)
|
||||
{
|
||||
if (tty->erasing) {
|
||||
|
|
@ -439,6 +459,8 @@ static inline void finish_erasing(struct tty_struct *tty)
|
|||
* Perform erase and necessary output when an erase character is
|
||||
* present in the stream from the driver layer. Handles the complexities
|
||||
* of UTF-8 multibyte symbols.
|
||||
*
|
||||
* Locking: read_lock for tty buffers, BKL for column/erasing state
|
||||
*/
|
||||
|
||||
static void eraser(unsigned char c, struct tty_struct *tty)
|
||||
|
|
@ -447,6 +469,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
|
|||
int head, seen_alnums, cnt;
|
||||
unsigned long flags;
|
||||
|
||||
/* FIXME: locking needed ? */
|
||||
if (tty->read_head == tty->canon_head) {
|
||||
/* opost('\a', tty); */ /* what do you think? */
|
||||
return;
|
||||
|
|
@ -481,6 +504,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
|
|||
}
|
||||
|
||||
seen_alnums = 0;
|
||||
/* FIXME: Locking ?? */
|
||||
while (tty->read_head != tty->canon_head) {
|
||||
head = tty->read_head;
|
||||
|
||||
|
|
@ -583,6 +607,8 @@ static void eraser(unsigned char c, struct tty_struct *tty)
|
|||
* may caus terminal flushing to take place according to the termios
|
||||
* settings and character used. Called from the driver receive_buf
|
||||
* path so serialized.
|
||||
*
|
||||
* Locking: ctrl_lock, read_lock (both via flush buffer)
|
||||
*/
|
||||
|
||||
static inline void isig(int sig, struct tty_struct *tty, int flush)
|
||||
|
|
@ -1007,12 +1033,26 @@ int is_ignored(int sig)
|
|||
* and is protected from re-entry by the tty layer. The user is
|
||||
* guaranteed that this function will not be re-entered or in progress
|
||||
* when the ldisc is closed.
|
||||
*
|
||||
* Locking: Caller holds tty->termios_mutex
|
||||
*/
|
||||
|
||||
static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
|
||||
{
|
||||
if (!tty)
|
||||
return;
|
||||
int canon_change = 1;
|
||||
BUG_ON(!tty);
|
||||
|
||||
if (old)
|
||||
canon_change = (old->c_lflag ^ tty->termios->c_lflag) & ICANON;
|
||||
if (canon_change) {
|
||||
memset(&tty->read_flags, 0, sizeof tty->read_flags);
|
||||
tty->canon_head = tty->read_tail;
|
||||
tty->canon_data = 0;
|
||||
tty->erasing = 0;
|
||||
}
|
||||
|
||||
if (canon_change && !L_ICANON(tty) && tty->read_cnt)
|
||||
wake_up_interruptible(&tty->read_wait);
|
||||
|
||||
tty->icanon = (L_ICANON(tty) != 0);
|
||||
if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
|
||||
|
|
@ -1143,7 +1183,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt)
|
|||
* @b: user data
|
||||
* @nr: size of data
|
||||
*
|
||||
* Helper function to speed up read_chan. It is only called when
|
||||
* Helper function to speed up n_tty_read. It is only called when
|
||||
* ICANON is off; it copies characters straight from the tty queue to
|
||||
* user space directly. It can be profitably called twice; once to
|
||||
* drain the space from the tail pointer to the (physical) end of the
|
||||
|
|
@ -1210,7 +1250,7 @@ static int job_control(struct tty_struct *tty, struct file *file)
|
|||
if (file->f_op->write != redirected_tty_write &&
|
||||
current->signal->tty == tty) {
|
||||
if (!tty->pgrp)
|
||||
printk(KERN_ERR "read_chan: no tty->pgrp!\n");
|
||||
printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
|
||||
else if (task_pgrp(current) != tty->pgrp) {
|
||||
if (is_ignored(SIGTTIN) ||
|
||||
is_current_pgrp_orphaned())
|
||||
|
|
@ -1225,7 +1265,7 @@ static int job_control(struct tty_struct *tty, struct file *file)
|
|||
|
||||
|
||||
/**
|
||||
* read_chan - read function for tty
|
||||
* n_tty_read - read function for tty
|
||||
* @tty: tty device
|
||||
* @file: file object
|
||||
* @buf: userspace buffer pointer
|
||||
|
|
@ -1239,7 +1279,7 @@ static int job_control(struct tty_struct *tty, struct file *file)
|
|||
* This code must be sure never to sleep through a hangup.
|
||||
*/
|
||||
|
||||
static ssize_t read_chan(struct tty_struct *tty, struct file *file,
|
||||
static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
|
||||
unsigned char __user *buf, size_t nr)
|
||||
{
|
||||
unsigned char __user *b = buf;
|
||||
|
|
@ -1254,10 +1294,7 @@ static ssize_t read_chan(struct tty_struct *tty, struct file *file,
|
|||
|
||||
do_it_again:
|
||||
|
||||
if (!tty->read_buf) {
|
||||
printk(KERN_ERR "n_tty_read_chan: read_buf == NULL?!?\n");
|
||||
return -EIO;
|
||||
}
|
||||
BUG_ON(!tty->read_buf);
|
||||
|
||||
c = job_control(tty, file);
|
||||
if (c < 0)
|
||||
|
|
@ -1444,7 +1481,7 @@ do_it_again:
|
|||
}
|
||||
|
||||
/**
|
||||
* write_chan - write function for tty
|
||||
* n_tty_write - write function for tty
|
||||
* @tty: tty device
|
||||
* @file: file object
|
||||
* @buf: userspace buffer pointer
|
||||
|
|
@ -1458,7 +1495,7 @@ do_it_again:
|
|||
* This code must be sure never to sleep through a hangup.
|
||||
*/
|
||||
|
||||
static ssize_t write_chan(struct tty_struct *tty, struct file *file,
|
||||
static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
|
||||
const unsigned char *buf, size_t nr)
|
||||
{
|
||||
const unsigned char *b = buf;
|
||||
|
|
@ -1532,7 +1569,7 @@ break_out:
|
|||
}
|
||||
|
||||
/**
|
||||
* normal_poll - poll method for N_TTY
|
||||
* n_tty_poll - poll method for N_TTY
|
||||
* @tty: terminal device
|
||||
* @file: file accessing it
|
||||
* @wait: poll table
|
||||
|
|
@ -1545,7 +1582,7 @@ break_out:
|
|||
* Called without the kernel lock held - fine
|
||||
*/
|
||||
|
||||
static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
|
||||
static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
|
||||
poll_table *wait)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
|
|
@ -1573,6 +1610,44 @@ static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
|
|||
return mask;
|
||||
}
|
||||
|
||||
static unsigned long inq_canon(struct tty_struct *tty)
|
||||
{
|
||||
int nr, head, tail;
|
||||
|
||||
if (!tty->canon_data)
|
||||
return 0;
|
||||
head = tty->canon_head;
|
||||
tail = tty->read_tail;
|
||||
nr = (head - tail) & (N_TTY_BUF_SIZE-1);
|
||||
/* Skip EOF-chars.. */
|
||||
while (head != tail) {
|
||||
if (test_bit(tail, tty->read_flags) &&
|
||||
tty->read_buf[tail] == __DISABLED_CHAR)
|
||||
nr--;
|
||||
tail = (tail+1) & (N_TTY_BUF_SIZE-1);
|
||||
}
|
||||
return nr;
|
||||
}
|
||||
|
||||
static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int retval;
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCOUTQ:
|
||||
return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
|
||||
case TIOCINQ:
|
||||
/* FIXME: Locking */
|
||||
retval = tty->read_cnt;
|
||||
if (L_ICANON(tty))
|
||||
retval = inq_canon(tty);
|
||||
return put_user(retval, (unsigned int __user *) arg);
|
||||
default:
|
||||
return n_tty_ioctl_helper(tty, file, cmd, arg);
|
||||
}
|
||||
}
|
||||
|
||||
struct tty_ldisc_ops tty_ldisc_N_TTY = {
|
||||
.magic = TTY_LDISC_MAGIC,
|
||||
.name = "n_tty",
|
||||
|
|
@ -1580,11 +1655,11 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = {
|
|||
.close = n_tty_close,
|
||||
.flush_buffer = n_tty_flush_buffer,
|
||||
.chars_in_buffer = n_tty_chars_in_buffer,
|
||||
.read = read_chan,
|
||||
.write = write_chan,
|
||||
.read = n_tty_read,
|
||||
.write = n_tty_write,
|
||||
.ioctl = n_tty_ioctl,
|
||||
.set_termios = n_tty_set_termios,
|
||||
.poll = normal_poll,
|
||||
.poll = n_tty_poll,
|
||||
.receive_buf = n_tty_receive_buf,
|
||||
.write_wakeup = n_tty_write_wakeup
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1599,7 +1599,10 @@ static int ntty_open(struct tty_struct *tty, struct file *file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Called when the userspace process close the tty, /dev/noz*. */
|
||||
/* Called when the userspace process close the tty, /dev/noz*. Also
|
||||
called immediately if ntty_open fails in which case tty->driver_data
|
||||
will be NULL an we exit by the first return */
|
||||
|
||||
static void ntty_close(struct tty_struct *tty, struct file *file)
|
||||
{
|
||||
struct nozomi *dc = get_dc_by_tty(tty);
|
||||
|
|
|
|||
|
|
@ -1759,65 +1759,40 @@ static void cmm_cm4000_release(struct pcmcia_device * link)
|
|||
|
||||
/*==== Interface to PCMCIA Layer =======================================*/
|
||||
|
||||
static int cm4000_config_check(struct pcmcia_device *p_dev,
|
||||
cistpl_cftable_entry_t *cfg,
|
||||
cistpl_cftable_entry_t *dflt,
|
||||
unsigned int vcc,
|
||||
void *priv_data)
|
||||
{
|
||||
if (!cfg->io.nwin)
|
||||
return -ENODEV;
|
||||
|
||||
/* Get the IOaddr */
|
||||
p_dev->io.BasePort1 = cfg->io.win[0].base;
|
||||
p_dev->io.NumPorts1 = cfg->io.win[0].len;
|
||||
p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
|
||||
if (!(cfg->io.flags & CISTPL_IO_8BIT))
|
||||
p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
|
||||
if (!(cfg->io.flags & CISTPL_IO_16BIT))
|
||||
p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
|
||||
p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK;
|
||||
|
||||
return pcmcia_request_io(p_dev, &p_dev->io);
|
||||
}
|
||||
|
||||
static int cm4000_config(struct pcmcia_device * link, int devno)
|
||||
{
|
||||
struct cm4000_dev *dev;
|
||||
tuple_t tuple;
|
||||
cisparse_t parse;
|
||||
u_char buf[64];
|
||||
int fail_fn, fail_rc;
|
||||
int rc;
|
||||
|
||||
/* read the config-tuples */
|
||||
tuple.Attributes = 0;
|
||||
tuple.TupleData = buf;
|
||||
tuple.TupleDataMax = sizeof(buf);
|
||||
tuple.TupleOffset = 0;
|
||||
|
||||
link->io.BasePort2 = 0;
|
||||
link->io.NumPorts2 = 0;
|
||||
link->io.Attributes2 = 0;
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
for (rc = pcmcia_get_first_tuple(link, &tuple);
|
||||
rc == CS_SUCCESS; rc = pcmcia_get_next_tuple(link, &tuple)) {
|
||||
|
||||
rc = pcmcia_get_tuple_data(link, &tuple);
|
||||
if (rc != CS_SUCCESS)
|
||||
continue;
|
||||
rc = pcmcia_parse_tuple(link, &tuple, &parse);
|
||||
if (rc != CS_SUCCESS)
|
||||
continue;
|
||||
|
||||
link->conf.ConfigIndex = parse.cftable_entry.index;
|
||||
|
||||
if (!parse.cftable_entry.io.nwin)
|
||||
continue;
|
||||
|
||||
/* Get the IOaddr */
|
||||
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
|
||||
link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
|
||||
if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT))
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
|
||||
if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT))
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
|
||||
link->io.IOAddrLines = parse.cftable_entry.io.flags
|
||||
& CISTPL_IO_LINES_MASK;
|
||||
|
||||
rc = pcmcia_request_io(link, &link->io);
|
||||
if (rc == CS_SUCCESS)
|
||||
break; /* we are done */
|
||||
}
|
||||
if (rc != CS_SUCCESS)
|
||||
if (pcmcia_loop_config(link, cm4000_config_check, NULL))
|
||||
goto cs_release;
|
||||
|
||||
link->conf.IntType = 00000002;
|
||||
|
||||
if ((fail_rc =
|
||||
pcmcia_request_configuration(link, &link->conf)) != CS_SUCCESS) {
|
||||
fail_fn = RequestConfiguration;
|
||||
if (pcmcia_request_configuration(link, &link->conf))
|
||||
goto cs_release;
|
||||
}
|
||||
|
||||
dev = link->priv;
|
||||
sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno);
|
||||
|
|
|
|||
|
|
@ -526,65 +526,49 @@ static void cm4040_reader_release(struct pcmcia_device *link)
|
|||
return;
|
||||
}
|
||||
|
||||
static int cm4040_config_check(struct pcmcia_device *p_dev,
|
||||
cistpl_cftable_entry_t *cfg,
|
||||
cistpl_cftable_entry_t *dflt,
|
||||
unsigned int vcc,
|
||||
void *priv_data)
|
||||
{
|
||||
int rc;
|
||||
if (!cfg->io.nwin)
|
||||
return -ENODEV;
|
||||
|
||||
/* Get the IOaddr */
|
||||
p_dev->io.BasePort1 = cfg->io.win[0].base;
|
||||
p_dev->io.NumPorts1 = cfg->io.win[0].len;
|
||||
p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
|
||||
if (!(cfg->io.flags & CISTPL_IO_8BIT))
|
||||
p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
|
||||
if (!(cfg->io.flags & CISTPL_IO_16BIT))
|
||||
p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
|
||||
p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK;
|
||||
|
||||
rc = pcmcia_request_io(p_dev, &p_dev->io);
|
||||
dev_printk(KERN_INFO, &handle_to_dev(p_dev),
|
||||
"pcmcia_request_io returned 0x%x\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int reader_config(struct pcmcia_device *link, int devno)
|
||||
{
|
||||
struct reader_dev *dev;
|
||||
tuple_t tuple;
|
||||
cisparse_t parse;
|
||||
u_char buf[64];
|
||||
int fail_fn, fail_rc;
|
||||
int rc;
|
||||
|
||||
tuple.Attributes = 0;
|
||||
tuple.TupleData = buf;
|
||||
tuple.TupleDataMax = sizeof(buf);
|
||||
tuple.TupleOffset = 0;
|
||||
int fail_rc;
|
||||
|
||||
link->io.BasePort2 = 0;
|
||||
link->io.NumPorts2 = 0;
|
||||
link->io.Attributes2 = 0;
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
for (rc = pcmcia_get_first_tuple(link, &tuple);
|
||||
rc == CS_SUCCESS;
|
||||
rc = pcmcia_get_next_tuple(link, &tuple)) {
|
||||
rc = pcmcia_get_tuple_data(link, &tuple);
|
||||
if (rc != CS_SUCCESS)
|
||||
continue;
|
||||
rc = pcmcia_parse_tuple(link, &tuple, &parse);
|
||||
if (rc != CS_SUCCESS)
|
||||
continue;
|
||||
|
||||
link->conf.ConfigIndex = parse.cftable_entry.index;
|
||||
|
||||
if (!parse.cftable_entry.io.nwin)
|
||||
continue;
|
||||
|
||||
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
|
||||
link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
|
||||
if (!(parse.cftable_entry.io.flags & CISTPL_IO_8BIT))
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
|
||||
if (!(parse.cftable_entry.io.flags & CISTPL_IO_16BIT))
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
|
||||
link->io.IOAddrLines = parse.cftable_entry.io.flags
|
||||
& CISTPL_IO_LINES_MASK;
|
||||
rc = pcmcia_request_io(link, &link->io);
|
||||
|
||||
dev_printk(KERN_INFO, &handle_to_dev(link), "foo");
|
||||
if (rc == CS_SUCCESS)
|
||||
break;
|
||||
else
|
||||
dev_printk(KERN_INFO, &handle_to_dev(link),
|
||||
"pcmcia_request_io failed 0x%x\n", rc);
|
||||
}
|
||||
if (rc != CS_SUCCESS)
|
||||
if (pcmcia_loop_config(link, cm4040_config_check, NULL))
|
||||
goto cs_release;
|
||||
|
||||
link->conf.IntType = 00000002;
|
||||
|
||||
if ((fail_rc = pcmcia_request_configuration(link,&link->conf))
|
||||
!=CS_SUCCESS) {
|
||||
fail_fn = RequestConfiguration;
|
||||
fail_rc = pcmcia_request_configuration(link, &link->conf);
|
||||
if (fail_rc != 0) {
|
||||
dev_printk(KERN_INFO, &handle_to_dev(link),
|
||||
"pcmcia_request_configuration failed 0x%x\n",
|
||||
fail_rc);
|
||||
|
|
|
|||
|
|
@ -65,9 +65,9 @@ static void signalled_reboot_work(struct work_struct *work_reboot)
|
|||
struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev,
|
||||
work_reboot);
|
||||
struct pcmcia_device *link = ipw->link;
|
||||
int ret = pccard_reset_card(link->socket);
|
||||
int ret = pcmcia_reset_card(link->socket);
|
||||
|
||||
if (ret != CS_SUCCESS)
|
||||
if (ret != 0)
|
||||
cs_error(link, ResetCard, ret);
|
||||
}
|
||||
|
||||
|
|
@ -83,7 +83,6 @@ static int config_ipwireless(struct ipw_dev *ipw)
|
|||
{
|
||||
struct pcmcia_device *link = ipw->link;
|
||||
int ret;
|
||||
config_info_t conf;
|
||||
tuple_t tuple;
|
||||
unsigned short buf[64];
|
||||
cisparse_t parse;
|
||||
|
|
@ -105,7 +104,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
|
|||
while (ret == 0) {
|
||||
ret = pcmcia_get_tuple_data(link, &tuple);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, GetTupleData, ret);
|
||||
goto exit0;
|
||||
}
|
||||
|
|
@ -116,21 +115,21 @@ static int config_ipwireless(struct ipw_dev *ipw)
|
|||
|
||||
ret = pcmcia_get_first_tuple(link, &tuple);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, GetFirstTuple, ret);
|
||||
goto exit0;
|
||||
}
|
||||
|
||||
ret = pcmcia_get_tuple_data(link, &tuple);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, GetTupleData, ret);
|
||||
goto exit0;
|
||||
}
|
||||
|
||||
ret = pcmcia_parse_tuple(link, &tuple, &parse);
|
||||
ret = pcmcia_parse_tuple(&tuple, &parse);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, ParseTuple, ret);
|
||||
goto exit0;
|
||||
}
|
||||
|
|
@ -152,21 +151,21 @@ static int config_ipwireless(struct ipw_dev *ipw)
|
|||
|
||||
ret = pcmcia_get_first_tuple(link, &tuple);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, GetFirstTuple, ret);
|
||||
goto exit0;
|
||||
}
|
||||
|
||||
ret = pcmcia_get_tuple_data(link, &tuple);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, GetTupleData, ret);
|
||||
goto exit0;
|
||||
}
|
||||
|
||||
ret = pcmcia_parse_tuple(link, &tuple, &parse);
|
||||
ret = pcmcia_parse_tuple(&tuple, &parse);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, GetTupleData, ret);
|
||||
goto exit0;
|
||||
}
|
||||
|
|
@ -181,7 +180,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
|
|||
|
||||
ret = pcmcia_request_io(link, &link->io);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, RequestIO, ret);
|
||||
goto exit0;
|
||||
}
|
||||
|
|
@ -195,21 +194,21 @@ static int config_ipwireless(struct ipw_dev *ipw)
|
|||
|
||||
ret = pcmcia_get_first_tuple(link, &tuple);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, GetFirstTuple, ret);
|
||||
goto exit1;
|
||||
}
|
||||
|
||||
ret = pcmcia_get_tuple_data(link, &tuple);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, GetTupleData, ret);
|
||||
goto exit1;
|
||||
}
|
||||
|
||||
ret = pcmcia_parse_tuple(link, &tuple, &parse);
|
||||
ret = pcmcia_parse_tuple(&tuple, &parse);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, ParseTuple, ret);
|
||||
goto exit1;
|
||||
}
|
||||
|
|
@ -227,7 +226,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
|
|||
ret = pcmcia_request_window(&link, &ipw->request_common_memory,
|
||||
&ipw->handle_common_memory);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, RequestWindow, ret);
|
||||
goto exit1;
|
||||
}
|
||||
|
|
@ -239,7 +238,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
|
|||
ret = pcmcia_map_mem_page(ipw->handle_common_memory,
|
||||
&memreq_common_memory);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, MapMemPage, ret);
|
||||
goto exit1;
|
||||
}
|
||||
|
|
@ -261,7 +260,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
|
|||
ret = pcmcia_request_window(&link, &ipw->request_attr_memory,
|
||||
&ipw->handle_attr_memory);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, RequestWindow, ret);
|
||||
goto exit2;
|
||||
}
|
||||
|
|
@ -272,7 +271,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
|
|||
ret = pcmcia_map_mem_page(ipw->handle_attr_memory,
|
||||
&memreq_attr_memory);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, MapMemPage, ret);
|
||||
goto exit2;
|
||||
}
|
||||
|
|
@ -292,20 +291,11 @@ static int config_ipwireless(struct ipw_dev *ipw)
|
|||
|
||||
ret = pcmcia_request_irq(link, &link->irq);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, RequestIRQ, ret);
|
||||
goto exit3;
|
||||
}
|
||||
|
||||
/* Look up current Vcc */
|
||||
|
||||
ret = pcmcia_get_configuration_info(link, &conf);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
cs_error(link, GetConfigurationInfo, ret);
|
||||
goto exit4;
|
||||
}
|
||||
|
||||
printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",
|
||||
ipw->is_v2_card ? "V2/V3" : "V1");
|
||||
printk(KERN_INFO IPWIRELESS_PCCARD_NAME
|
||||
|
|
@ -341,7 +331,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
|
|||
*/
|
||||
ret = pcmcia_request_configuration(link, &link->conf);
|
||||
|
||||
if (ret != CS_SUCCESS) {
|
||||
if (ret != 0) {
|
||||
cs_error(link, RequestConfiguration, ret);
|
||||
goto exit4;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -276,6 +276,7 @@ static int ipw_write_room(struct tty_struct *linux_tty)
|
|||
struct ipw_tty *tty = linux_tty->driver_data;
|
||||
int room;
|
||||
|
||||
/* FIXME: Exactly how is the tty object locked here .. */
|
||||
if (!tty)
|
||||
return -ENODEV;
|
||||
|
||||
|
|
@ -397,6 +398,7 @@ static int set_control_lines(struct ipw_tty *tty, unsigned int set,
|
|||
static int ipw_tiocmget(struct tty_struct *linux_tty, struct file *file)
|
||||
{
|
||||
struct ipw_tty *tty = linux_tty->driver_data;
|
||||
/* FIXME: Exactly how is the tty object locked here .. */
|
||||
|
||||
if (!tty)
|
||||
return -ENODEV;
|
||||
|
|
@ -412,6 +414,7 @@ ipw_tiocmset(struct tty_struct *linux_tty, struct file *file,
|
|||
unsigned int set, unsigned int clear)
|
||||
{
|
||||
struct ipw_tty *tty = linux_tty->driver_data;
|
||||
/* FIXME: Exactly how is the tty object locked here .. */
|
||||
|
||||
if (!tty)
|
||||
return -ENODEV;
|
||||
|
|
@ -433,6 +436,8 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file,
|
|||
if (!tty->open_count)
|
||||
return -EINVAL;
|
||||
|
||||
/* FIXME: Exactly how is the tty object locked here .. */
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCGSERIAL:
|
||||
return ipwireless_get_serial_info(tty, (void __user *) arg);
|
||||
|
|
@ -467,13 +472,6 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file,
|
|||
}
|
||||
return 0;
|
||||
|
||||
case TCGETS:
|
||||
case TCGETA:
|
||||
return n_tty_ioctl(linux_tty, file, cmd, arg);
|
||||
|
||||
case TCFLSH:
|
||||
return n_tty_ioctl(linux_tty, file, cmd, arg);
|
||||
|
||||
case FIONREAD:
|
||||
{
|
||||
int val = 0;
|
||||
|
|
@ -482,10 +480,11 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file,
|
|||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
case TCFLSH:
|
||||
return tty_perform_flush(linux_tty, arg);
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOIOCTLCMD;
|
||||
return tty_mode_ioctl(linux_tty, file, cmd , arg);
|
||||
}
|
||||
|
||||
static int add_tty(dev_node_t *nodesp, int j,
|
||||
|
|
@ -588,6 +587,8 @@ void ipwireless_tty_free(struct ipw_tty *tty)
|
|||
tty_hangup(ttyj->linux_tty);
|
||||
/* Wait till the tty_hangup has completed */
|
||||
flush_scheduled_work();
|
||||
/* FIXME: Exactly how is the tty object locked here
|
||||
against a parallel ioctl etc */
|
||||
mutex_lock(&ttyj->ipw_tty_mutex);
|
||||
}
|
||||
while (ttyj->open_count)
|
||||
|
|
|
|||
|
|
@ -601,7 +601,7 @@ static int mgslpc_config(struct pcmcia_device *link)
|
|||
|
||||
cfg = &(parse.cftable_entry);
|
||||
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
|
||||
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
|
||||
CS_CHECK(ParseTuple, pcmcia_parse_tuple(&tuple, &parse));
|
||||
|
||||
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
|
||||
if (cfg->index == 0)
|
||||
|
|
|
|||
|
|
@ -8,10 +8,12 @@
|
|||
* Added TTY_DO_WRITE_WAKEUP to enable n_tty to send POLL_OUT to
|
||||
* waiting writers -- Sapan Bhatia <sapan@corewars.org>
|
||||
*
|
||||
*
|
||||
* When reading this code see also fs/devpts. In particular note that the
|
||||
* driver_data field is used by the devpts side as a binding to the devpts
|
||||
* inode.
|
||||
*/
|
||||
|
||||
#include <linux/module.h> /* For EXPORT_SYMBOL */
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
|
@ -23,26 +25,25 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sysctl.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/system.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/devpts_fs.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
|
||||
/* These are global because they are accessed in tty_io.c */
|
||||
#ifdef CONFIG_UNIX98_PTYS
|
||||
struct tty_driver *ptm_driver;
|
||||
static struct tty_driver *pts_driver;
|
||||
#endif
|
||||
|
||||
static void pty_close(struct tty_struct * tty, struct file * filp)
|
||||
static void pty_close(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
if (!tty)
|
||||
return;
|
||||
if (tty->driver->subtype == PTY_TYPE_MASTER) {
|
||||
if (tty->count > 1)
|
||||
printk("master pty_close: count = %d!!\n", tty->count);
|
||||
} else {
|
||||
BUG_ON(!tty);
|
||||
if (tty->driver->subtype == PTY_TYPE_MASTER)
|
||||
WARN_ON(tty->count > 1);
|
||||
else {
|
||||
if (tty->count > 2)
|
||||
return;
|
||||
}
|
||||
|
|
@ -59,7 +60,7 @@ static void pty_close(struct tty_struct * tty, struct file * filp)
|
|||
set_bit(TTY_OTHER_CLOSED, &tty->flags);
|
||||
#ifdef CONFIG_UNIX98_PTYS
|
||||
if (tty->driver == ptm_driver)
|
||||
devpts_pty_kill(tty->index);
|
||||
devpts_pty_kill(tty->link);
|
||||
#endif
|
||||
tty_vhangup(tty->link);
|
||||
}
|
||||
|
|
@ -69,13 +70,13 @@ static void pty_close(struct tty_struct * tty, struct file * filp)
|
|||
* The unthrottle routine is called by the line discipline to signal
|
||||
* that it can receive more characters. For PTY's, the TTY_THROTTLED
|
||||
* flag is always set, to force the line discipline to always call the
|
||||
* unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE
|
||||
* unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE
|
||||
* characters in the queue. This is necessary since each time this
|
||||
* happens, we need to wake up any sleeping processes that could be
|
||||
* (1) trying to send data to the pty, or (2) waiting in wait_until_sent()
|
||||
* for the pty buffer to be drained.
|
||||
*/
|
||||
static void pty_unthrottle(struct tty_struct * tty)
|
||||
static void pty_unthrottle(struct tty_struct *tty)
|
||||
{
|
||||
struct tty_struct *o_tty = tty->link;
|
||||
|
||||
|
|
@ -87,7 +88,7 @@ static void pty_unthrottle(struct tty_struct * tty)
|
|||
}
|
||||
|
||||
/*
|
||||
* WSH 05/24/97: modified to
|
||||
* WSH 05/24/97: modified to
|
||||
* (1) use space in tty->flip instead of a shared temp buffer
|
||||
* The flip buffers aren't being used for a pty, so there's lots
|
||||
* of space available. The buffer is protected by a per-pty
|
||||
|
|
@ -100,7 +101,8 @@ static void pty_unthrottle(struct tty_struct * tty)
|
|||
* not our partners. We can't just take the other one blindly without
|
||||
* risking deadlocks.
|
||||
*/
|
||||
static int pty_write(struct tty_struct * tty, const unsigned char *buf, int count)
|
||||
static int pty_write(struct tty_struct *tty, const unsigned char *buf,
|
||||
int count)
|
||||
{
|
||||
struct tty_struct *to = tty->link;
|
||||
int c;
|
||||
|
|
@ -112,7 +114,7 @@ static int pty_write(struct tty_struct * tty, const unsigned char *buf, int coun
|
|||
if (c > count)
|
||||
c = count;
|
||||
to->ldisc.ops->receive_buf(to, buf, NULL, c);
|
||||
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
|
@ -128,17 +130,17 @@ static int pty_write_room(struct tty_struct *tty)
|
|||
|
||||
/*
|
||||
* WSH 05/24/97: Modified for asymmetric MASTER/SLAVE behavior
|
||||
* The chars_in_buffer() value is used by the ldisc select() function
|
||||
* The chars_in_buffer() value is used by the ldisc select() function
|
||||
* to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256).
|
||||
* The pty driver chars_in_buffer() Master/Slave must behave differently:
|
||||
*
|
||||
* The Master side needs to allow typed-ahead commands to accumulate
|
||||
* while being canonicalized, so we report "our buffer" as empty until
|
||||
* some threshold is reached, and then report the count. (Any count >
|
||||
* WAKEUP_CHARS is regarded by select() as "full".) To avoid deadlock
|
||||
* the count returned must be 0 if no canonical data is available to be
|
||||
* WAKEUP_CHARS is regarded by select() as "full".) To avoid deadlock
|
||||
* the count returned must be 0 if no canonical data is available to be
|
||||
* read. (The N_TTY ldisc.chars_in_buffer now knows this.)
|
||||
*
|
||||
*
|
||||
* The Slave side passes all characters in raw mode to the Master side's
|
||||
* buffer where they can be read immediately, so in this case we can
|
||||
* return the true count in the buffer.
|
||||
|
|
@ -155,21 +157,22 @@ static int pty_chars_in_buffer(struct tty_struct *tty)
|
|||
/* The ldisc must report 0 if no characters available to be read */
|
||||
count = to->ldisc.ops->chars_in_buffer(to);
|
||||
|
||||
if (tty->driver->subtype == PTY_TYPE_SLAVE) return count;
|
||||
if (tty->driver->subtype == PTY_TYPE_SLAVE)
|
||||
return count;
|
||||
|
||||
/* Master side driver ... if the other side's read buffer is less than
|
||||
/* Master side driver ... if the other side's read buffer is less than
|
||||
* half full, return 0 to allow writers to proceed; otherwise return
|
||||
* the count. This leaves a comfortable margin to avoid overflow,
|
||||
* the count. This leaves a comfortable margin to avoid overflow,
|
||||
* and still allows half a buffer's worth of typed-ahead commands.
|
||||
*/
|
||||
return ((count < N_TTY_BUF_SIZE/2) ? 0 : count);
|
||||
return (count < N_TTY_BUF_SIZE/2) ? 0 : count;
|
||||
}
|
||||
|
||||
/* Set the lock flag on a pty */
|
||||
static int pty_set_lock(struct tty_struct *tty, int __user * arg)
|
||||
static int pty_set_lock(struct tty_struct *tty, int __user *arg)
|
||||
{
|
||||
int val;
|
||||
if (get_user(val,arg))
|
||||
if (get_user(val, arg))
|
||||
return -EFAULT;
|
||||
if (val)
|
||||
set_bit(TTY_PTY_LOCK, &tty->flags);
|
||||
|
|
@ -182,13 +185,13 @@ static void pty_flush_buffer(struct tty_struct *tty)
|
|||
{
|
||||
struct tty_struct *to = tty->link;
|
||||
unsigned long flags;
|
||||
|
||||
|
||||
if (!to)
|
||||
return;
|
||||
|
||||
|
||||
if (to->ldisc.ops->flush_buffer)
|
||||
to->ldisc.ops->flush_buffer(to);
|
||||
|
||||
|
||||
if (to->packet) {
|
||||
spin_lock_irqsave(&tty->ctrl_lock, flags);
|
||||
tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
|
||||
|
|
@ -197,7 +200,7 @@ static void pty_flush_buffer(struct tty_struct *tty)
|
|||
}
|
||||
}
|
||||
|
||||
static int pty_open(struct tty_struct *tty, struct file * filp)
|
||||
static int pty_open(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
int retval = -ENODEV;
|
||||
|
||||
|
|
@ -220,13 +223,65 @@ out:
|
|||
return retval;
|
||||
}
|
||||
|
||||
static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
|
||||
static void pty_set_termios(struct tty_struct *tty,
|
||||
struct ktermios *old_termios)
|
||||
{
|
||||
tty->termios->c_cflag &= ~(CSIZE | PARENB);
|
||||
tty->termios->c_cflag |= (CS8 | CREAD);
|
||||
tty->termios->c_cflag &= ~(CSIZE | PARENB);
|
||||
tty->termios->c_cflag |= (CS8 | CREAD);
|
||||
}
|
||||
|
||||
static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
|
||||
{
|
||||
struct tty_struct *o_tty;
|
||||
int idx = tty->index;
|
||||
int retval;
|
||||
|
||||
o_tty = alloc_tty_struct();
|
||||
if (!o_tty)
|
||||
return -ENOMEM;
|
||||
if (!try_module_get(driver->other->owner)) {
|
||||
/* This cannot in fact currently happen */
|
||||
free_tty_struct(o_tty);
|
||||
return -ENOMEM;
|
||||
}
|
||||
initialize_tty_struct(o_tty, driver->other, idx);
|
||||
|
||||
/* We always use new tty termios data so we can do this
|
||||
the easy way .. */
|
||||
retval = tty_init_termios(tty);
|
||||
if (retval)
|
||||
goto free_mem_out;
|
||||
|
||||
retval = tty_init_termios(o_tty);
|
||||
if (retval) {
|
||||
tty_free_termios(tty);
|
||||
goto free_mem_out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Everything allocated ... set up the o_tty structure.
|
||||
*/
|
||||
driver->other->ttys[idx] = o_tty;
|
||||
tty_driver_kref_get(driver->other);
|
||||
if (driver->subtype == PTY_TYPE_MASTER)
|
||||
o_tty->count++;
|
||||
/* Establish the links in both directions */
|
||||
tty->link = o_tty;
|
||||
o_tty->link = tty;
|
||||
|
||||
tty_driver_kref_get(driver);
|
||||
tty->count++;
|
||||
driver->ttys[idx] = tty;
|
||||
return 0;
|
||||
free_mem_out:
|
||||
module_put(o_tty->driver->owner);
|
||||
free_tty_struct(o_tty);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
static const struct tty_operations pty_ops = {
|
||||
.install = pty_install,
|
||||
.open = pty_open,
|
||||
.close = pty_close,
|
||||
.write = pty_write,
|
||||
|
|
@ -329,8 +384,11 @@ static inline void legacy_pty_init(void) { }
|
|||
* Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly.
|
||||
*/
|
||||
int pty_limit = NR_UNIX98_PTY_DEFAULT;
|
||||
static int pty_limit_min = 0;
|
||||
static int pty_limit_min;
|
||||
static int pty_limit_max = NR_UNIX98_PTY_MAX;
|
||||
static int pty_count;
|
||||
|
||||
static struct cdev ptmx_cdev;
|
||||
|
||||
static struct ctl_table pty_table[] = {
|
||||
{
|
||||
|
|
@ -348,6 +406,7 @@ static struct ctl_table pty_table[] = {
|
|||
.procname = "nr",
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0444,
|
||||
.data = &pty_count,
|
||||
.proc_handler = &proc_dointvec,
|
||||
}, {
|
||||
.ctl_name = 0
|
||||
|
|
@ -388,7 +447,111 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
|
|||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
static const struct tty_operations pty_unix98_ops = {
|
||||
/**
|
||||
* ptm_unix98_lookup - find a pty master
|
||||
* @driver: ptm driver
|
||||
* @idx: tty index
|
||||
*
|
||||
* Look up a pty master device. Called under the tty_mutex for now.
|
||||
* This provides our locking.
|
||||
*/
|
||||
|
||||
static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver,
|
||||
struct inode *ptm_inode, int idx)
|
||||
{
|
||||
struct tty_struct *tty = devpts_get_tty(ptm_inode, idx);
|
||||
if (tty)
|
||||
tty = tty->link;
|
||||
return tty;
|
||||
}
|
||||
|
||||
/**
|
||||
* pts_unix98_lookup - find a pty slave
|
||||
* @driver: pts driver
|
||||
* @idx: tty index
|
||||
*
|
||||
* Look up a pty master device. Called under the tty_mutex for now.
|
||||
* This provides our locking.
|
||||
*/
|
||||
|
||||
static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
|
||||
struct inode *pts_inode, int idx)
|
||||
{
|
||||
struct tty_struct *tty = devpts_get_tty(pts_inode, idx);
|
||||
/* Master must be open before slave */
|
||||
if (!tty)
|
||||
return ERR_PTR(-EIO);
|
||||
return tty;
|
||||
}
|
||||
|
||||
static void pty_unix98_shutdown(struct tty_struct *tty)
|
||||
{
|
||||
/* We have our own method as we don't use the tty index */
|
||||
kfree(tty->termios);
|
||||
}
|
||||
|
||||
/* We have no need to install and remove our tty objects as devpts does all
|
||||
the work for us */
|
||||
|
||||
static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
|
||||
{
|
||||
struct tty_struct *o_tty;
|
||||
int idx = tty->index;
|
||||
|
||||
o_tty = alloc_tty_struct();
|
||||
if (!o_tty)
|
||||
return -ENOMEM;
|
||||
if (!try_module_get(driver->other->owner)) {
|
||||
/* This cannot in fact currently happen */
|
||||
free_tty_struct(o_tty);
|
||||
return -ENOMEM;
|
||||
}
|
||||
initialize_tty_struct(o_tty, driver->other, idx);
|
||||
|
||||
tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
|
||||
if (tty->termios == NULL)
|
||||
goto free_mem_out;
|
||||
*tty->termios = driver->init_termios;
|
||||
tty->termios_locked = tty->termios + 1;
|
||||
|
||||
o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
|
||||
if (o_tty->termios == NULL)
|
||||
goto free_mem_out;
|
||||
*o_tty->termios = driver->other->init_termios;
|
||||
o_tty->termios_locked = o_tty->termios + 1;
|
||||
|
||||
tty_driver_kref_get(driver->other);
|
||||
if (driver->subtype == PTY_TYPE_MASTER)
|
||||
o_tty->count++;
|
||||
/* Establish the links in both directions */
|
||||
tty->link = o_tty;
|
||||
o_tty->link = tty;
|
||||
/*
|
||||
* All structures have been allocated, so now we install them.
|
||||
* Failures after this point use release_tty to clean up, so
|
||||
* there's no need to null out the local pointers.
|
||||
*/
|
||||
tty_driver_kref_get(driver);
|
||||
tty->count++;
|
||||
pty_count++;
|
||||
return 0;
|
||||
free_mem_out:
|
||||
kfree(o_tty->termios);
|
||||
module_put(o_tty->driver->owner);
|
||||
free_tty_struct(o_tty);
|
||||
kfree(tty->termios);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
|
||||
{
|
||||
pty_count--;
|
||||
}
|
||||
|
||||
static const struct tty_operations ptm_unix98_ops = {
|
||||
.lookup = ptm_unix98_lookup,
|
||||
.install = pty_unix98_install,
|
||||
.remove = pty_unix98_remove,
|
||||
.open = pty_open,
|
||||
.close = pty_close,
|
||||
.write = pty_write,
|
||||
|
|
@ -397,9 +560,89 @@ static const struct tty_operations pty_unix98_ops = {
|
|||
.chars_in_buffer = pty_chars_in_buffer,
|
||||
.unthrottle = pty_unthrottle,
|
||||
.set_termios = pty_set_termios,
|
||||
.ioctl = pty_unix98_ioctl
|
||||
.ioctl = pty_unix98_ioctl,
|
||||
.shutdown = pty_unix98_shutdown
|
||||
};
|
||||
|
||||
static const struct tty_operations pty_unix98_ops = {
|
||||
.lookup = pts_unix98_lookup,
|
||||
.install = pty_unix98_install,
|
||||
.remove = pty_unix98_remove,
|
||||
.open = pty_open,
|
||||
.close = pty_close,
|
||||
.write = pty_write,
|
||||
.write_room = pty_write_room,
|
||||
.flush_buffer = pty_flush_buffer,
|
||||
.chars_in_buffer = pty_chars_in_buffer,
|
||||
.unthrottle = pty_unthrottle,
|
||||
.set_termios = pty_set_termios,
|
||||
.shutdown = pty_unix98_shutdown
|
||||
};
|
||||
|
||||
/**
|
||||
* ptmx_open - open a unix 98 pty master
|
||||
* @inode: inode of device file
|
||||
* @filp: file pointer to tty
|
||||
*
|
||||
* Allocate a unix98 pty master device from the ptmx driver.
|
||||
*
|
||||
* Locking: tty_mutex protects the init_dev work. tty->count should
|
||||
* protect the rest.
|
||||
* allocated_ptys_lock handles the list of free pty numbers
|
||||
*/
|
||||
|
||||
static int __ptmx_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct tty_struct *tty;
|
||||
int retval;
|
||||
int index;
|
||||
|
||||
nonseekable_open(inode, filp);
|
||||
|
||||
/* find a device that is not in use. */
|
||||
index = devpts_new_index(inode);
|
||||
if (index < 0)
|
||||
return index;
|
||||
|
||||
mutex_lock(&tty_mutex);
|
||||
tty = tty_init_dev(ptm_driver, index, 1);
|
||||
mutex_unlock(&tty_mutex);
|
||||
|
||||
if (IS_ERR(tty)) {
|
||||
retval = PTR_ERR(tty);
|
||||
goto out;
|
||||
}
|
||||
|
||||
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
|
||||
filp->private_data = tty;
|
||||
file_move(filp, &tty->tty_files);
|
||||
|
||||
retval = devpts_pty_new(inode, tty->link);
|
||||
if (retval)
|
||||
goto out1;
|
||||
|
||||
retval = ptm_driver->ops->open(tty, filp);
|
||||
if (!retval)
|
||||
return 0;
|
||||
out1:
|
||||
tty_release_dev(filp);
|
||||
return retval;
|
||||
out:
|
||||
devpts_kill_index(inode, index);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int ptmx_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lock_kernel();
|
||||
ret = __ptmx_open(inode, filp);
|
||||
unlock_kernel();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct file_operations ptmx_fops;
|
||||
|
||||
static void __init unix98_pty_init(void)
|
||||
{
|
||||
|
|
@ -427,7 +670,7 @@ static void __init unix98_pty_init(void)
|
|||
ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
|
||||
ptm_driver->other = pts_driver;
|
||||
tty_set_operations(ptm_driver, &pty_unix98_ops);
|
||||
tty_set_operations(ptm_driver, &ptm_unix98_ops);
|
||||
|
||||
pts_driver->owner = THIS_MODULE;
|
||||
pts_driver->driver_name = "pty_slave";
|
||||
|
|
@ -443,16 +686,26 @@ static void __init unix98_pty_init(void)
|
|||
pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
|
||||
TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
|
||||
pts_driver->other = ptm_driver;
|
||||
tty_set_operations(pts_driver, &pty_ops);
|
||||
|
||||
tty_set_operations(pts_driver, &pty_unix98_ops);
|
||||
|
||||
if (tty_register_driver(ptm_driver))
|
||||
panic("Couldn't register Unix98 ptm driver");
|
||||
if (tty_register_driver(pts_driver))
|
||||
panic("Couldn't register Unix98 pts driver");
|
||||
|
||||
pty_table[1].data = &ptm_driver->refcount;
|
||||
register_sysctl_table(pty_root_table);
|
||||
|
||||
/* Now create the /dev/ptmx special device */
|
||||
tty_default_fops(&ptmx_fops);
|
||||
ptmx_fops.open = ptmx_open;
|
||||
|
||||
cdev_init(&ptmx_cdev, &ptmx_fops);
|
||||
if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
|
||||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
|
||||
panic("Couldn't register /dev/ptmx driver\n");
|
||||
device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void unix98_pty_init(void) { }
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -661,10 +661,10 @@ void add_disk_randomness(struct gendisk *disk)
|
|||
if (!disk || !disk->random)
|
||||
return;
|
||||
/* first major is 1, so we get >= 0x200 here */
|
||||
DEBUG_ENT("disk event %d:%d\n", disk->major, disk->first_minor);
|
||||
DEBUG_ENT("disk event %d:%d\n",
|
||||
MAJOR(disk_devt(disk)), MINOR(disk_devt(disk)));
|
||||
|
||||
add_timer_randomness(disk->random,
|
||||
0x100 + MKDEV(disk->major, disk->first_minor));
|
||||
add_timer_randomness(disk->random, 0x100 + disk_devt(disk));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -88,12 +88,12 @@
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_SPARC32
|
||||
#include <linux/pci.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <asm/ebus.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static unsigned long rtc_port;
|
||||
static int rtc_irq = PCI_IRQ_NONE;
|
||||
static int rtc_irq;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HPET_RTC_IRQ
|
||||
|
|
@ -973,8 +973,8 @@ static int __init rtc_init(void)
|
|||
char *guess = NULL;
|
||||
#endif
|
||||
#ifdef CONFIG_SPARC32
|
||||
struct linux_ebus *ebus;
|
||||
struct linux_ebus_device *edev;
|
||||
struct device_node *ebus_dp;
|
||||
struct of_device *op;
|
||||
#else
|
||||
void *r;
|
||||
#ifdef RTC_IRQ
|
||||
|
|
@ -983,12 +983,16 @@ static int __init rtc_init(void)
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_SPARC32
|
||||
for_each_ebus(ebus) {
|
||||
for_each_ebusdev(edev, ebus) {
|
||||
if (strcmp(edev->prom_node->name, "rtc") == 0) {
|
||||
rtc_port = edev->resource[0].start;
|
||||
rtc_irq = edev->irqs[0];
|
||||
goto found;
|
||||
for_each_node_by_name(ebus_dp, "ebus") {
|
||||
struct device_node *dp;
|
||||
for (dp = ebus_dp; dp; dp = dp->sibling) {
|
||||
if (!strcmp(dp->name, "rtc")) {
|
||||
op = of_find_device_by_node(dp);
|
||||
if (op) {
|
||||
rtc_port = op->resource[0].start;
|
||||
rtc_irq = op->irqs[0];
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -997,7 +1001,7 @@ static int __init rtc_init(void)
|
|||
return -EIO;
|
||||
|
||||
found:
|
||||
if (rtc_irq == PCI_IRQ_NONE) {
|
||||
if (!rtc_irq) {
|
||||
rtc_has_irq = 0;
|
||||
goto no_irq;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -405,9 +405,9 @@ static unsigned int stl_baudrates[] = {
|
|||
|
||||
static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
|
||||
static int stl_brdinit(struct stlbrd *brdp);
|
||||
static int stl_getportstats(struct stlport *portp, comstats_t __user *cp);
|
||||
static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
|
||||
static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
|
||||
static int stl_waitcarrier(struct stlport *portp, struct file *filp);
|
||||
static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp, struct file *filp);
|
||||
|
||||
/*
|
||||
* CD1400 uart specific handling functions.
|
||||
|
|
@ -612,8 +612,9 @@ static struct class *stallion_class;
|
|||
static void stl_cd_change(struct stlport *portp)
|
||||
{
|
||||
unsigned int oldsigs = portp->sigs;
|
||||
struct tty_struct *tty = tty_port_tty_get(&portp->port);
|
||||
|
||||
if (!portp->port.tty)
|
||||
if (!tty)
|
||||
return;
|
||||
|
||||
portp->sigs = stl_getsignals(portp);
|
||||
|
|
@ -623,7 +624,8 @@ static void stl_cd_change(struct stlport *portp)
|
|||
|
||||
if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
|
||||
if (portp->port.flags & ASYNC_CHECK_CD)
|
||||
tty_hangup(portp->port.tty);
|
||||
tty_hangup(tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -734,7 +736,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
|
|||
* On the first open of the device setup the port hardware, and
|
||||
* initialize the per port data structure.
|
||||
*/
|
||||
portp->port.tty = tty;
|
||||
tty_port_tty_set(&portp->port, tty);
|
||||
tty->driver_data = portp;
|
||||
portp->port.count++;
|
||||
|
||||
|
|
@ -774,7 +776,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
|
|||
* then also we might have to wait for carrier.
|
||||
*/
|
||||
if (!(filp->f_flags & O_NONBLOCK))
|
||||
if ((rc = stl_waitcarrier(portp, filp)) != 0)
|
||||
if ((rc = stl_waitcarrier(tty, portp, filp)) != 0)
|
||||
return rc;
|
||||
|
||||
portp->port.flags |= ASYNC_NORMAL_ACTIVE;
|
||||
|
|
@ -789,7 +791,8 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
|
|||
* maybe because if we are clocal then we don't need to wait...
|
||||
*/
|
||||
|
||||
static int stl_waitcarrier(struct stlport *portp, struct file *filp)
|
||||
static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp,
|
||||
struct file *filp)
|
||||
{
|
||||
unsigned long flags;
|
||||
int rc, doclocal;
|
||||
|
|
@ -801,7 +804,7 @@ static int stl_waitcarrier(struct stlport *portp, struct file *filp)
|
|||
|
||||
spin_lock_irqsave(&stallion_lock, flags);
|
||||
|
||||
if (portp->port.tty->termios->c_cflag & CLOCAL)
|
||||
if (tty->termios->c_cflag & CLOCAL)
|
||||
doclocal++;
|
||||
|
||||
portp->openwaitcnt++;
|
||||
|
|
@ -846,8 +849,6 @@ static void stl_flushbuffer(struct tty_struct *tty)
|
|||
|
||||
pr_debug("stl_flushbuffer(tty=%p)\n", tty);
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return;
|
||||
|
|
@ -865,8 +866,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
|
|||
|
||||
pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return;
|
||||
|
|
@ -949,7 +948,7 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
|
|||
tty_ldisc_flush(tty);
|
||||
|
||||
tty->closing = 0;
|
||||
portp->port.tty = NULL;
|
||||
tty_port_tty_set(&portp->port, NULL);
|
||||
|
||||
if (portp->openwaitcnt) {
|
||||
if (portp->close_delay)
|
||||
|
|
@ -1033,8 +1032,6 @@ static int stl_putchar(struct tty_struct *tty, unsigned char ch)
|
|||
|
||||
pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
|
||||
|
||||
if (tty == NULL)
|
||||
return -EINVAL;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return -EINVAL;
|
||||
|
|
@ -1070,8 +1067,6 @@ static void stl_flushchars(struct tty_struct *tty)
|
|||
|
||||
pr_debug("stl_flushchars(tty=%p)\n", tty);
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return;
|
||||
|
|
@ -1090,8 +1085,6 @@ static int stl_writeroom(struct tty_struct *tty)
|
|||
|
||||
pr_debug("stl_writeroom(tty=%p)\n", tty);
|
||||
|
||||
if (tty == NULL)
|
||||
return 0;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return 0;
|
||||
|
|
@ -1122,8 +1115,6 @@ static int stl_charsinbuffer(struct tty_struct *tty)
|
|||
|
||||
pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
|
||||
|
||||
if (tty == NULL)
|
||||
return 0;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return 0;
|
||||
|
|
@ -1183,8 +1174,9 @@ static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
|
|||
* just quietly ignore any requests to change irq, etc.
|
||||
*/
|
||||
|
||||
static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
|
||||
static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
|
||||
{
|
||||
struct stlport * portp = tty->driver_data;
|
||||
struct serial_struct sio;
|
||||
|
||||
pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
|
||||
|
|
@ -1205,7 +1197,7 @@ static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
|
|||
portp->close_delay = sio.close_delay;
|
||||
portp->closing_wait = sio.closing_wait;
|
||||
portp->custom_divisor = sio.custom_divisor;
|
||||
stl_setport(portp, portp->port.tty->termios);
|
||||
stl_setport(portp, tty->termios);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1215,8 +1207,6 @@ static int stl_tiocmget(struct tty_struct *tty, struct file *file)
|
|||
{
|
||||
struct stlport *portp;
|
||||
|
||||
if (tty == NULL)
|
||||
return -ENODEV;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return -ENODEV;
|
||||
|
|
@ -1232,8 +1222,6 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file,
|
|||
struct stlport *portp;
|
||||
int rts = -1, dtr = -1;
|
||||
|
||||
if (tty == NULL)
|
||||
return -ENODEV;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return -ENODEV;
|
||||
|
|
@ -1262,8 +1250,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
|
|||
pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
|
||||
arg);
|
||||
|
||||
if (tty == NULL)
|
||||
return -ENODEV;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return -ENODEV;
|
||||
|
|
@ -1282,10 +1268,10 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
|
|||
rc = stl_getserial(portp, argp);
|
||||
break;
|
||||
case TIOCSSERIAL:
|
||||
rc = stl_setserial(portp, argp);
|
||||
rc = stl_setserial(tty, argp);
|
||||
break;
|
||||
case COM_GETPORTSTATS:
|
||||
rc = stl_getportstats(portp, argp);
|
||||
rc = stl_getportstats(tty, portp, argp);
|
||||
break;
|
||||
case COM_CLRPORTSTATS:
|
||||
rc = stl_clrportstats(portp, argp);
|
||||
|
|
@ -1317,8 +1303,6 @@ static void stl_start(struct tty_struct *tty)
|
|||
|
||||
pr_debug("stl_start(tty=%p)\n", tty);
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return;
|
||||
|
|
@ -1334,8 +1318,6 @@ static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
|
|||
|
||||
pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return;
|
||||
|
|
@ -1369,8 +1351,6 @@ static void stl_throttle(struct tty_struct *tty)
|
|||
|
||||
pr_debug("stl_throttle(tty=%p)\n", tty);
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return;
|
||||
|
|
@ -1389,8 +1369,6 @@ static void stl_unthrottle(struct tty_struct *tty)
|
|||
|
||||
pr_debug("stl_unthrottle(tty=%p)\n", tty);
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return;
|
||||
|
|
@ -1410,8 +1388,6 @@ static void stl_stop(struct tty_struct *tty)
|
|||
|
||||
pr_debug("stl_stop(tty=%p)\n", tty);
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return;
|
||||
|
|
@ -1432,8 +1408,6 @@ static void stl_hangup(struct tty_struct *tty)
|
|||
|
||||
pr_debug("stl_hangup(tty=%p)\n", tty);
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return;
|
||||
|
|
@ -1452,7 +1426,7 @@ static void stl_hangup(struct tty_struct *tty)
|
|||
portp->tx.head = NULL;
|
||||
portp->tx.tail = NULL;
|
||||
}
|
||||
portp->port.tty = NULL;
|
||||
tty_port_tty_set(&portp->port, NULL);
|
||||
portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
|
||||
portp->port.count = 0;
|
||||
wake_up_interruptible(&portp->port.open_wait);
|
||||
|
|
@ -1466,8 +1440,6 @@ static int stl_breakctl(struct tty_struct *tty, int state)
|
|||
|
||||
pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
|
||||
|
||||
if (tty == NULL)
|
||||
return -EINVAL;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return -EINVAL;
|
||||
|
|
@ -1484,8 +1456,6 @@ static void stl_sendxchar(struct tty_struct *tty, char ch)
|
|||
|
||||
pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
|
||||
|
||||
if (tty == NULL)
|
||||
return;
|
||||
portp = tty->driver_data;
|
||||
if (portp == NULL)
|
||||
return;
|
||||
|
|
@ -1805,7 +1775,7 @@ static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
|
|||
"(size=%Zd)\n", sizeof(struct stlport));
|
||||
break;
|
||||
}
|
||||
|
||||
tty_port_init(&portp->port);
|
||||
portp->magic = STL_PORTMAGIC;
|
||||
portp->portnr = i;
|
||||
portp->brdnr = panelp->brdnr;
|
||||
|
|
@ -1832,6 +1802,7 @@ static void stl_cleanup_panels(struct stlbrd *brdp)
|
|||
struct stlpanel *panelp;
|
||||
struct stlport *portp;
|
||||
unsigned int j, k;
|
||||
struct tty_struct *tty;
|
||||
|
||||
for (j = 0; j < STL_MAXPANELS; j++) {
|
||||
panelp = brdp->panels[j];
|
||||
|
|
@ -1841,8 +1812,11 @@ static void stl_cleanup_panels(struct stlbrd *brdp)
|
|||
portp = panelp->ports[k];
|
||||
if (portp == NULL)
|
||||
continue;
|
||||
if (portp->port.tty != NULL)
|
||||
stl_hangup(portp->port.tty);
|
||||
tty = tty_port_tty_get(&portp->port);
|
||||
if (tty != NULL) {
|
||||
stl_hangup(tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
kfree(portp->tx.buf);
|
||||
kfree(portp);
|
||||
}
|
||||
|
|
@ -2498,7 +2472,7 @@ static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
|
|||
* what port to get stats for (used through board control device).
|
||||
*/
|
||||
|
||||
static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
|
||||
static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
|
||||
{
|
||||
comstats_t stl_comstats;
|
||||
unsigned char *head, *tail;
|
||||
|
|
@ -2525,18 +2499,17 @@ static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
|
|||
portp->stats.rxbuffered = 0;
|
||||
|
||||
spin_lock_irqsave(&stallion_lock, flags);
|
||||
if (portp->port.tty != NULL)
|
||||
if (portp->port.tty->driver_data == portp) {
|
||||
portp->stats.ttystate = portp->port.tty->flags;
|
||||
/* No longer available as a statistic */
|
||||
portp->stats.rxbuffered = 1; /*portp->port.tty->flip.count; */
|
||||
if (portp->port.tty->termios != NULL) {
|
||||
portp->stats.cflags = portp->port.tty->termios->c_cflag;
|
||||
portp->stats.iflags = portp->port.tty->termios->c_iflag;
|
||||
portp->stats.oflags = portp->port.tty->termios->c_oflag;
|
||||
portp->stats.lflags = portp->port.tty->termios->c_lflag;
|
||||
}
|
||||
if (tty != NULL && portp->port.tty == tty) {
|
||||
portp->stats.ttystate = tty->flags;
|
||||
/* No longer available as a statistic */
|
||||
portp->stats.rxbuffered = 1; /*tty->flip.count; */
|
||||
if (tty->termios != NULL) {
|
||||
portp->stats.cflags = tty->termios->c_cflag;
|
||||
portp->stats.iflags = tty->termios->c_iflag;
|
||||
portp->stats.oflags = tty->termios->c_oflag;
|
||||
portp->stats.lflags = tty->termios->c_lflag;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&stallion_lock, flags);
|
||||
|
||||
head = portp->tx.head;
|
||||
|
|
@ -2640,7 +2613,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns
|
|||
|
||||
switch (cmd) {
|
||||
case COM_GETPORTSTATS:
|
||||
rc = stl_getportstats(NULL, argp);
|
||||
rc = stl_getportstats(NULL, NULL, argp);
|
||||
break;
|
||||
case COM_CLRPORTSTATS:
|
||||
rc = stl_clrportstats(NULL, argp);
|
||||
|
|
@ -3243,7 +3216,7 @@ static void stl_cd1400flowctrl(struct stlport *portp, int state)
|
|||
|
||||
if (portp == NULL)
|
||||
return;
|
||||
tty = portp->port.tty;
|
||||
tty = tty_port_tty_get(&portp->port);
|
||||
if (tty == NULL)
|
||||
return;
|
||||
|
||||
|
|
@ -3288,6 +3261,7 @@ static void stl_cd1400flowctrl(struct stlport *portp, int state)
|
|||
|
||||
BRDDISABLE(portp->brdnr);
|
||||
spin_unlock_irqrestore(&brd_lock, flags);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -3305,7 +3279,7 @@ static void stl_cd1400sendflow(struct stlport *portp, int state)
|
|||
|
||||
if (portp == NULL)
|
||||
return;
|
||||
tty = portp->port.tty;
|
||||
tty = tty_port_tty_get(&portp->port);
|
||||
if (tty == NULL)
|
||||
return;
|
||||
|
||||
|
|
@ -3325,6 +3299,7 @@ static void stl_cd1400sendflow(struct stlport *portp, int state)
|
|||
}
|
||||
BRDDISABLE(portp->brdnr);
|
||||
spin_unlock_irqrestore(&brd_lock, flags);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -3478,6 +3453,7 @@ static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
|
|||
int len, stlen;
|
||||
char *head, *tail;
|
||||
unsigned char ioack, srer;
|
||||
struct tty_struct *tty;
|
||||
|
||||
pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
|
||||
|
||||
|
|
@ -3504,8 +3480,11 @@ static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
|
|||
if ((len == 0) || ((len < STL_TXBUFLOW) &&
|
||||
(test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
|
||||
set_bit(ASYI_TXLOW, &portp->istate);
|
||||
if (portp->port.tty)
|
||||
tty_wakeup(portp->port.tty);
|
||||
tty = tty_port_tty_get(&portp->port);
|
||||
if (tty) {
|
||||
tty_wakeup(tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
|
|
@ -3569,7 +3548,7 @@ static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
|
|||
return;
|
||||
}
|
||||
portp = panelp->ports[(ioack >> 3)];
|
||||
tty = portp->port.tty;
|
||||
tty = tty_port_tty_get(&portp->port);
|
||||
|
||||
if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
|
||||
outb((RDCR + portp->uartaddr), ioaddr);
|
||||
|
|
@ -3633,10 +3612,12 @@ static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
|
|||
}
|
||||
} else {
|
||||
printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
|
||||
tty_kref_put(tty);
|
||||
return;
|
||||
}
|
||||
|
||||
stl_rxalldone:
|
||||
tty_kref_put(tty);
|
||||
outb((EOSRR + portp->uartaddr), ioaddr);
|
||||
outb(0, (ioaddr + EREG_DATA));
|
||||
}
|
||||
|
|
@ -4175,7 +4156,7 @@ static void stl_sc26198flowctrl(struct stlport *portp, int state)
|
|||
|
||||
if (portp == NULL)
|
||||
return;
|
||||
tty = portp->port.tty;
|
||||
tty = tty_port_tty_get(&portp->port);
|
||||
if (tty == NULL)
|
||||
return;
|
||||
|
||||
|
|
@ -4226,6 +4207,7 @@ static void stl_sc26198flowctrl(struct stlport *portp, int state)
|
|||
|
||||
BRDDISABLE(portp->brdnr);
|
||||
spin_unlock_irqrestore(&brd_lock, flags);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -4244,7 +4226,7 @@ static void stl_sc26198sendflow(struct stlport *portp, int state)
|
|||
|
||||
if (portp == NULL)
|
||||
return;
|
||||
tty = portp->port.tty;
|
||||
tty = tty_port_tty_get(&portp->port);
|
||||
if (tty == NULL)
|
||||
return;
|
||||
|
||||
|
|
@ -4269,6 +4251,7 @@ static void stl_sc26198sendflow(struct stlport *portp, int state)
|
|||
}
|
||||
BRDDISABLE(portp->brdnr);
|
||||
spin_unlock_irqrestore(&brd_lock, flags);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -4408,6 +4391,7 @@ static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
|
|||
|
||||
static void stl_sc26198txisr(struct stlport *portp)
|
||||
{
|
||||
struct tty_struct *tty;
|
||||
unsigned int ioaddr;
|
||||
unsigned char mr0;
|
||||
int len, stlen;
|
||||
|
|
@ -4422,8 +4406,11 @@ static void stl_sc26198txisr(struct stlport *portp)
|
|||
if ((len == 0) || ((len < STL_TXBUFLOW) &&
|
||||
(test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
|
||||
set_bit(ASYI_TXLOW, &portp->istate);
|
||||
if (portp->port.tty)
|
||||
tty_wakeup(portp->port.tty);
|
||||
tty = tty_port_tty_get(&portp->port);
|
||||
if (tty) {
|
||||
tty_wakeup(tty);
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
|
|
@ -4476,7 +4463,7 @@ static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
|
|||
|
||||
pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
|
||||
|
||||
tty = portp->port.tty;
|
||||
tty = tty_port_tty_get(&portp->port);
|
||||
ioaddr = portp->ioaddr;
|
||||
outb(GIBCR, (ioaddr + XP_ADDR));
|
||||
len = inb(ioaddr + XP_DATA) + 1;
|
||||
|
|
@ -4515,6 +4502,7 @@ static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
|
|||
stl_sc26198txunflow(portp, tty);
|
||||
}
|
||||
}
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -4528,7 +4516,7 @@ static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char
|
|||
struct tty_struct *tty;
|
||||
unsigned int ioaddr;
|
||||
|
||||
tty = portp->port.tty;
|
||||
tty = tty_port_tty_get(&portp->port);
|
||||
ioaddr = portp->ioaddr;
|
||||
|
||||
if (status & SR_RXPARITY)
|
||||
|
|
@ -4566,6 +4554,7 @@ static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char
|
|||
if (status == 0)
|
||||
portp->stats.rxtotal++;
|
||||
}
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -2504,7 +2504,7 @@ static void __devexit sx_remove_card(struct sx_board *board,
|
|||
del_timer(&board->timer);
|
||||
if (pdev) {
|
||||
#ifdef CONFIG_PCI
|
||||
pci_iounmap(pdev, board->base);
|
||||
pci_iounmap(pdev, board->base2);
|
||||
pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
|
||||
#endif
|
||||
} else {
|
||||
|
|
@ -2703,7 +2703,7 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev,
|
|||
|
||||
return 0;
|
||||
err_unmap:
|
||||
pci_iounmap(pdev, board->base);
|
||||
pci_iounmap(pdev, board->base2);
|
||||
err_reg:
|
||||
pci_release_region(pdev, reg);
|
||||
err_flag:
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ menuconfig TCG_TPM
|
|||
tristate "TPM Hardware Support"
|
||||
depends on HAS_IOMEM
|
||||
depends on EXPERIMENTAL
|
||||
select SECURITYFS
|
||||
---help---
|
||||
If you have a TPM security chip in your system, which
|
||||
implements the Trusted Computing Group's specification,
|
||||
|
|
|
|||
|
|
@ -954,72 +954,63 @@ EXPORT_SYMBOL_GPL(tpm_store_cancel);
|
|||
|
||||
/*
|
||||
* Device file system interface to the TPM
|
||||
*
|
||||
* It's assured that the chip will be opened just once,
|
||||
* by the check of is_open variable, which is protected
|
||||
* by driver_lock.
|
||||
*/
|
||||
int tpm_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int rc = 0, minor = iminor(inode);
|
||||
int minor = iminor(inode);
|
||||
struct tpm_chip *chip = NULL, *pos;
|
||||
|
||||
lock_kernel();
|
||||
spin_lock(&driver_lock);
|
||||
|
||||
list_for_each_entry(pos, &tpm_chip_list, list) {
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
|
||||
if (pos->vendor.miscdev.minor == minor) {
|
||||
chip = pos;
|
||||
get_device(chip->dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (chip == NULL) {
|
||||
rc = -ENODEV;
|
||||
goto err_out;
|
||||
}
|
||||
if (!chip)
|
||||
return -ENODEV;
|
||||
|
||||
if (chip->num_opens) {
|
||||
if (test_and_set_bit(0, &chip->is_open)) {
|
||||
dev_dbg(chip->dev, "Another process owns this TPM\n");
|
||||
rc = -EBUSY;
|
||||
goto err_out;
|
||||
put_device(chip->dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
chip->num_opens++;
|
||||
get_device(chip->dev);
|
||||
|
||||
spin_unlock(&driver_lock);
|
||||
|
||||
chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
|
||||
if (chip->data_buffer == NULL) {
|
||||
chip->num_opens--;
|
||||
clear_bit(0, &chip->is_open);
|
||||
put_device(chip->dev);
|
||||
unlock_kernel();
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
atomic_set(&chip->data_pending, 0);
|
||||
|
||||
file->private_data = chip;
|
||||
unlock_kernel();
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
spin_unlock(&driver_lock);
|
||||
unlock_kernel();
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpm_open);
|
||||
|
||||
/*
|
||||
* Called on file close
|
||||
*/
|
||||
int tpm_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct tpm_chip *chip = file->private_data;
|
||||
|
||||
flush_scheduled_work();
|
||||
spin_lock(&driver_lock);
|
||||
file->private_data = NULL;
|
||||
del_singleshot_timer_sync(&chip->user_read_timer);
|
||||
flush_scheduled_work();
|
||||
file->private_data = NULL;
|
||||
atomic_set(&chip->data_pending, 0);
|
||||
chip->num_opens--;
|
||||
put_device(chip->dev);
|
||||
kfree(chip->data_buffer);
|
||||
spin_unlock(&driver_lock);
|
||||
clear_bit(0, &chip->is_open);
|
||||
put_device(chip->dev);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpm_release);
|
||||
|
|
@ -1093,13 +1084,11 @@ void tpm_remove_hardware(struct device *dev)
|
|||
}
|
||||
|
||||
spin_lock(&driver_lock);
|
||||
|
||||
list_del(&chip->list);
|
||||
|
||||
list_del_rcu(&chip->list);
|
||||
spin_unlock(&driver_lock);
|
||||
synchronize_rcu();
|
||||
|
||||
misc_deregister(&chip->vendor.miscdev);
|
||||
|
||||
sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
|
||||
tpm_bios_log_teardown(chip->bios_dir);
|
||||
|
||||
|
|
@ -1144,25 +1133,33 @@ int tpm_pm_resume(struct device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(tpm_pm_resume);
|
||||
|
||||
/* In case vendor provided release function, call it too.*/
|
||||
|
||||
void tpm_dev_vendor_release(struct tpm_chip *chip)
|
||||
{
|
||||
if (chip->vendor.release)
|
||||
chip->vendor.release(chip->dev);
|
||||
|
||||
clear_bit(chip->dev_num, dev_mask);
|
||||
kfree(chip->vendor.miscdev.name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpm_dev_vendor_release);
|
||||
|
||||
|
||||
/*
|
||||
* Once all references to platform device are down to 0,
|
||||
* release all allocated structures.
|
||||
* In case vendor provided release function,
|
||||
* call it too.
|
||||
*/
|
||||
static void tpm_dev_release(struct device *dev)
|
||||
{
|
||||
struct tpm_chip *chip = dev_get_drvdata(dev);
|
||||
|
||||
if (chip->vendor.release)
|
||||
chip->vendor.release(dev);
|
||||
tpm_dev_vendor_release(chip);
|
||||
|
||||
chip->release(dev);
|
||||
|
||||
clear_bit(chip->dev_num, dev_mask);
|
||||
kfree(chip->vendor.miscdev.name);
|
||||
kfree(chip);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpm_dev_release);
|
||||
|
||||
/*
|
||||
* Called from tpm_<specific>.c probe function only for devices
|
||||
|
|
@ -1171,8 +1168,8 @@ static void tpm_dev_release(struct device *dev)
|
|||
* upon errant exit from this function specific probe function should call
|
||||
* pci_disable_device
|
||||
*/
|
||||
struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific
|
||||
*entry)
|
||||
struct tpm_chip *tpm_register_hardware(struct device *dev,
|
||||
const struct tpm_vendor_specific *entry)
|
||||
{
|
||||
#define DEVNAME_SIZE 7
|
||||
|
||||
|
|
@ -1231,21 +1228,20 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
|
|||
return NULL;
|
||||
}
|
||||
|
||||
spin_lock(&driver_lock);
|
||||
|
||||
list_add(&chip->list, &tpm_chip_list);
|
||||
|
||||
spin_unlock(&driver_lock);
|
||||
|
||||
if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) {
|
||||
list_del(&chip->list);
|
||||
misc_deregister(&chip->vendor.miscdev);
|
||||
put_device(chip->dev);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chip->bios_dir = tpm_bios_log_setup(devname);
|
||||
|
||||
/* Make chip available */
|
||||
spin_lock(&driver_lock);
|
||||
list_add_rcu(&chip->list, &tpm_chip_list);
|
||||
spin_unlock(&driver_lock);
|
||||
|
||||
return chip;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpm_register_hardware);
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ struct tpm_chip {
|
|||
struct device *dev; /* Device stuff */
|
||||
|
||||
int dev_num; /* /dev/tpm# */
|
||||
int num_opens; /* only one allowed */
|
||||
unsigned long is_open; /* only one allowed */
|
||||
int time_expired;
|
||||
|
||||
/* Data passed to and from the tpm via the read/write calls */
|
||||
|
|
@ -132,6 +132,7 @@ extern struct tpm_chip* tpm_register_hardware(struct device *,
|
|||
const struct tpm_vendor_specific *);
|
||||
extern int tpm_open(struct inode *, struct file *);
|
||||
extern int tpm_release(struct inode *, struct file *);
|
||||
extern void tpm_dev_vendor_release(struct tpm_chip *);
|
||||
extern ssize_t tpm_write(struct file *, const char __user *, size_t,
|
||||
loff_t *);
|
||||
extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
|
||||
|
|
|
|||
|
|
@ -630,12 +630,23 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
|
|||
{"", 0} /* Terminator */
|
||||
};
|
||||
|
||||
static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev)
|
||||
{
|
||||
struct tpm_chip *chip = pnp_get_drvdata(dev);
|
||||
|
||||
tpm_dev_vendor_release(chip);
|
||||
|
||||
kfree(chip);
|
||||
}
|
||||
|
||||
|
||||
static struct pnp_driver tis_pnp_driver = {
|
||||
.name = "tpm_tis",
|
||||
.id_table = tpm_pnp_tbl,
|
||||
.probe = tpm_tis_pnp_init,
|
||||
.suspend = tpm_tis_pnp_suspend,
|
||||
.resume = tpm_tis_pnp_resume,
|
||||
.remove = tpm_tis_pnp_remove,
|
||||
};
|
||||
|
||||
#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
|
||||
|
|
@ -683,6 +694,7 @@ static void __exit cleanup_tis(void)
|
|||
spin_lock(&tis_lock);
|
||||
list_for_each_entry_safe(i, j, &tis_chips, list) {
|
||||
chip = to_tpm_chip(i);
|
||||
tpm_remove_hardware(chip->dev);
|
||||
iowrite32(~TPM_GLOBAL_INT_ENABLE &
|
||||
ioread32(chip->vendor.iobase +
|
||||
TPM_INT_ENABLE(chip->vendor.
|
||||
|
|
@ -694,9 +706,9 @@ static void __exit cleanup_tis(void)
|
|||
free_irq(chip->vendor.irq, chip);
|
||||
iounmap(i->iobase);
|
||||
list_del(&i->list);
|
||||
tpm_remove_hardware(chip->dev);
|
||||
}
|
||||
spin_unlock(&tis_lock);
|
||||
|
||||
if (force) {
|
||||
platform_device_unregister(pdev);
|
||||
driver_unregister(&tis_drv);
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
|
|||
get_task_comm(name, tsk);
|
||||
audit_log_untrustedstring(ab, name);
|
||||
audit_log_format(ab, " data=");
|
||||
audit_log_n_untrustedstring(ab, buf->data, buf->valid);
|
||||
audit_log_n_hex(ab, buf->data, buf->valid);
|
||||
audit_log_end(ab);
|
||||
}
|
||||
buf->valid = 0;
|
||||
|
|
|
|||
511
drivers/char/tty_buffer.c
Normal file
511
drivers/char/tty_buffer.c
Normal file
|
|
@ -0,0 +1,511 @@
|
|||
/*
|
||||
* Tty buffer allocation management
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_driver.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
/**
|
||||
* tty_buffer_free_all - free buffers used by a tty
|
||||
* @tty: tty to free from
|
||||
*
|
||||
* Remove all the buffers pending on a tty whether queued with data
|
||||
* or in the free ring. Must be called when the tty is no longer in use
|
||||
*
|
||||
* Locking: none
|
||||
*/
|
||||
|
||||
void tty_buffer_free_all(struct tty_struct *tty)
|
||||
{
|
||||
struct tty_buffer *thead;
|
||||
while ((thead = tty->buf.head) != NULL) {
|
||||
tty->buf.head = thead->next;
|
||||
kfree(thead);
|
||||
}
|
||||
while ((thead = tty->buf.free) != NULL) {
|
||||
tty->buf.free = thead->next;
|
||||
kfree(thead);
|
||||
}
|
||||
tty->buf.tail = NULL;
|
||||
tty->buf.memory_used = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tty_buffer_alloc - allocate a tty buffer
|
||||
* @tty: tty device
|
||||
* @size: desired size (characters)
|
||||
*
|
||||
* Allocate a new tty buffer to hold the desired number of characters.
|
||||
* Return NULL if out of memory or the allocation would exceed the
|
||||
* per device queue
|
||||
*
|
||||
* Locking: Caller must hold tty->buf.lock
|
||||
*/
|
||||
|
||||
static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
|
||||
{
|
||||
struct tty_buffer *p;
|
||||
|
||||
if (tty->buf.memory_used + size > 65536)
|
||||
return NULL;
|
||||
p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
p->used = 0;
|
||||
p->size = size;
|
||||
p->next = NULL;
|
||||
p->commit = 0;
|
||||
p->read = 0;
|
||||
p->char_buf_ptr = (char *)(p->data);
|
||||
p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
|
||||
tty->buf.memory_used += size;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* tty_buffer_free - free a tty buffer
|
||||
* @tty: tty owning the buffer
|
||||
* @b: the buffer to free
|
||||
*
|
||||
* Free a tty buffer, or add it to the free list according to our
|
||||
* internal strategy
|
||||
*
|
||||
* Locking: Caller must hold tty->buf.lock
|
||||
*/
|
||||
|
||||
static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
|
||||
{
|
||||
/* Dumb strategy for now - should keep some stats */
|
||||
tty->buf.memory_used -= b->size;
|
||||
WARN_ON(tty->buf.memory_used < 0);
|
||||
|
||||
if (b->size >= 512)
|
||||
kfree(b);
|
||||
else {
|
||||
b->next = tty->buf.free;
|
||||
tty->buf.free = b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* __tty_buffer_flush - flush full tty buffers
|
||||
* @tty: tty to flush
|
||||
*
|
||||
* flush all the buffers containing receive data. Caller must
|
||||
* hold the buffer lock and must have ensured no parallel flush to
|
||||
* ldisc is running.
|
||||
*
|
||||
* Locking: Caller must hold tty->buf.lock
|
||||
*/
|
||||
|
||||
static void __tty_buffer_flush(struct tty_struct *tty)
|
||||
{
|
||||
struct tty_buffer *thead;
|
||||
|
||||
while ((thead = tty->buf.head) != NULL) {
|
||||
tty->buf.head = thead->next;
|
||||
tty_buffer_free(tty, thead);
|
||||
}
|
||||
tty->buf.tail = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* tty_buffer_flush - flush full tty buffers
|
||||
* @tty: tty to flush
|
||||
*
|
||||
* flush all the buffers containing receive data. If the buffer is
|
||||
* being processed by flush_to_ldisc then we defer the processing
|
||||
* to that function
|
||||
*
|
||||
* Locking: none
|
||||
*/
|
||||
|
||||
void tty_buffer_flush(struct tty_struct *tty)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
|
||||
/* If the data is being pushed to the tty layer then we can't
|
||||
process it here. Instead set a flag and the flush_to_ldisc
|
||||
path will process the flush request before it exits */
|
||||
if (test_bit(TTY_FLUSHING, &tty->flags)) {
|
||||
set_bit(TTY_FLUSHPENDING, &tty->flags);
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
wait_event(tty->read_wait,
|
||||
test_bit(TTY_FLUSHPENDING, &tty->flags) == 0);
|
||||
return;
|
||||
} else
|
||||
__tty_buffer_flush(tty);
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* tty_buffer_find - find a free tty buffer
|
||||
* @tty: tty owning the buffer
|
||||
* @size: characters wanted
|
||||
*
|
||||
* Locate an existing suitable tty buffer or if we are lacking one then
|
||||
* allocate a new one. We round our buffers off in 256 character chunks
|
||||
* to get better allocation behaviour.
|
||||
*
|
||||
* Locking: Caller must hold tty->buf.lock
|
||||
*/
|
||||
|
||||
static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
|
||||
{
|
||||
struct tty_buffer **tbh = &tty->buf.free;
|
||||
while ((*tbh) != NULL) {
|
||||
struct tty_buffer *t = *tbh;
|
||||
if (t->size >= size) {
|
||||
*tbh = t->next;
|
||||
t->next = NULL;
|
||||
t->used = 0;
|
||||
t->commit = 0;
|
||||
t->read = 0;
|
||||
tty->buf.memory_used += t->size;
|
||||
return t;
|
||||
}
|
||||
tbh = &((*tbh)->next);
|
||||
}
|
||||
/* Round the buffer size out */
|
||||
size = (size + 0xFF) & ~0xFF;
|
||||
return tty_buffer_alloc(tty, size);
|
||||
/* Should possibly check if this fails for the largest buffer we
|
||||
have queued and recycle that ? */
|
||||
}
|
||||
|
||||
/**
|
||||
* tty_buffer_request_room - grow tty buffer if needed
|
||||
* @tty: tty structure
|
||||
* @size: size desired
|
||||
*
|
||||
* Make at least size bytes of linear space available for the tty
|
||||
* buffer. If we fail return the size we managed to find.
|
||||
*
|
||||
* Locking: Takes tty->buf.lock
|
||||
*/
|
||||
int tty_buffer_request_room(struct tty_struct *tty, size_t size)
|
||||
{
|
||||
struct tty_buffer *b, *n;
|
||||
int left;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
|
||||
/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
|
||||
remove this conditional if its worth it. This would be invisible
|
||||
to the callers */
|
||||
if ((b = tty->buf.tail) != NULL)
|
||||
left = b->size - b->used;
|
||||
else
|
||||
left = 0;
|
||||
|
||||
if (left < size) {
|
||||
/* This is the slow path - looking for new buffers to use */
|
||||
if ((n = tty_buffer_find(tty, size)) != NULL) {
|
||||
if (b != NULL) {
|
||||
b->next = n;
|
||||
b->commit = b->used;
|
||||
} else
|
||||
tty->buf.head = n;
|
||||
tty->buf.tail = n;
|
||||
} else
|
||||
size = left;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
return size;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tty_buffer_request_room);
|
||||
|
||||
/**
|
||||
* tty_insert_flip_string - Add characters to the tty buffer
|
||||
* @tty: tty structure
|
||||
* @chars: characters
|
||||
* @size: size
|
||||
*
|
||||
* Queue a series of bytes to the tty buffering. All the characters
|
||||
* passed are marked as without error. Returns the number added.
|
||||
*
|
||||
* Locking: Called functions may take tty->buf.lock
|
||||
*/
|
||||
|
||||
int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
|
||||
size_t size)
|
||||
{
|
||||
int copied = 0;
|
||||
do {
|
||||
int space = tty_buffer_request_room(tty, size - copied);
|
||||
struct tty_buffer *tb = tty->buf.tail;
|
||||
/* If there is no space then tb may be NULL */
|
||||
if (unlikely(space == 0))
|
||||
break;
|
||||
memcpy(tb->char_buf_ptr + tb->used, chars, space);
|
||||
memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
|
||||
tb->used += space;
|
||||
copied += space;
|
||||
chars += space;
|
||||
/* There is a small chance that we need to split the data over
|
||||
several buffers. If this is the case we must loop */
|
||||
} while (unlikely(size > copied));
|
||||
return copied;
|
||||
}
|
||||
EXPORT_SYMBOL(tty_insert_flip_string);
|
||||
|
||||
/**
|
||||
* tty_insert_flip_string_flags - Add characters to the tty buffer
|
||||
* @tty: tty structure
|
||||
* @chars: characters
|
||||
* @flags: flag bytes
|
||||
* @size: size
|
||||
*
|
||||
* Queue a series of bytes to the tty buffering. For each character
|
||||
* the flags array indicates the status of the character. Returns the
|
||||
* number added.
|
||||
*
|
||||
* Locking: Called functions may take tty->buf.lock
|
||||
*/
|
||||
|
||||
int tty_insert_flip_string_flags(struct tty_struct *tty,
|
||||
const unsigned char *chars, const char *flags, size_t size)
|
||||
{
|
||||
int copied = 0;
|
||||
do {
|
||||
int space = tty_buffer_request_room(tty, size - copied);
|
||||
struct tty_buffer *tb = tty->buf.tail;
|
||||
/* If there is no space then tb may be NULL */
|
||||
if (unlikely(space == 0))
|
||||
break;
|
||||
memcpy(tb->char_buf_ptr + tb->used, chars, space);
|
||||
memcpy(tb->flag_buf_ptr + tb->used, flags, space);
|
||||
tb->used += space;
|
||||
copied += space;
|
||||
chars += space;
|
||||
flags += space;
|
||||
/* There is a small chance that we need to split the data over
|
||||
several buffers. If this is the case we must loop */
|
||||
} while (unlikely(size > copied));
|
||||
return copied;
|
||||
}
|
||||
EXPORT_SYMBOL(tty_insert_flip_string_flags);
|
||||
|
||||
/**
|
||||
* tty_schedule_flip - push characters to ldisc
|
||||
* @tty: tty to push from
|
||||
*
|
||||
* Takes any pending buffers and transfers their ownership to the
|
||||
* ldisc side of the queue. It then schedules those characters for
|
||||
* processing by the line discipline.
|
||||
*
|
||||
* Locking: Takes tty->buf.lock
|
||||
*/
|
||||
|
||||
void tty_schedule_flip(struct tty_struct *tty)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
if (tty->buf.tail != NULL)
|
||||
tty->buf.tail->commit = tty->buf.tail->used;
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
schedule_delayed_work(&tty->buf.work, 1);
|
||||
}
|
||||
EXPORT_SYMBOL(tty_schedule_flip);
|
||||
|
||||
/**
|
||||
* tty_prepare_flip_string - make room for characters
|
||||
* @tty: tty
|
||||
* @chars: return pointer for character write area
|
||||
* @size: desired size
|
||||
*
|
||||
* Prepare a block of space in the buffer for data. Returns the length
|
||||
* available and buffer pointer to the space which is now allocated and
|
||||
* accounted for as ready for normal characters. This is used for drivers
|
||||
* that need their own block copy routines into the buffer. There is no
|
||||
* guarantee the buffer is a DMA target!
|
||||
*
|
||||
* Locking: May call functions taking tty->buf.lock
|
||||
*/
|
||||
|
||||
int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars,
|
||||
size_t size)
|
||||
{
|
||||
int space = tty_buffer_request_room(tty, size);
|
||||
if (likely(space)) {
|
||||
struct tty_buffer *tb = tty->buf.tail;
|
||||
*chars = tb->char_buf_ptr + tb->used;
|
||||
memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
|
||||
tb->used += space;
|
||||
}
|
||||
return space;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
|
||||
|
||||
/**
|
||||
* tty_prepare_flip_string_flags - make room for characters
|
||||
* @tty: tty
|
||||
* @chars: return pointer for character write area
|
||||
* @flags: return pointer for status flag write area
|
||||
* @size: desired size
|
||||
*
|
||||
* Prepare a block of space in the buffer for data. Returns the length
|
||||
* available and buffer pointer to the space which is now allocated and
|
||||
* accounted for as ready for characters. This is used for drivers
|
||||
* that need their own block copy routines into the buffer. There is no
|
||||
* guarantee the buffer is a DMA target!
|
||||
*
|
||||
* Locking: May call functions taking tty->buf.lock
|
||||
*/
|
||||
|
||||
int tty_prepare_flip_string_flags(struct tty_struct *tty,
|
||||
unsigned char **chars, char **flags, size_t size)
|
||||
{
|
||||
int space = tty_buffer_request_room(tty, size);
|
||||
if (likely(space)) {
|
||||
struct tty_buffer *tb = tty->buf.tail;
|
||||
*chars = tb->char_buf_ptr + tb->used;
|
||||
*flags = tb->flag_buf_ptr + tb->used;
|
||||
tb->used += space;
|
||||
}
|
||||
return space;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* flush_to_ldisc
|
||||
* @work: tty structure passed from work queue.
|
||||
*
|
||||
* This routine is called out of the software interrupt to flush data
|
||||
* from the buffer chain to the line discipline.
|
||||
*
|
||||
* Locking: holds tty->buf.lock to guard buffer list. Drops the lock
|
||||
* while invoking the line discipline receive_buf method. The
|
||||
* receive_buf method is single threaded for each tty instance.
|
||||
*/
|
||||
|
||||
static void flush_to_ldisc(struct work_struct *work)
|
||||
{
|
||||
struct tty_struct *tty =
|
||||
container_of(work, struct tty_struct, buf.work.work);
|
||||
unsigned long flags;
|
||||
struct tty_ldisc *disc;
|
||||
struct tty_buffer *tbuf, *head;
|
||||
char *char_buf;
|
||||
unsigned char *flag_buf;
|
||||
|
||||
disc = tty_ldisc_ref(tty);
|
||||
if (disc == NULL) /* !TTY_LDISC */
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
/* So we know a flush is running */
|
||||
set_bit(TTY_FLUSHING, &tty->flags);
|
||||
head = tty->buf.head;
|
||||
if (head != NULL) {
|
||||
tty->buf.head = NULL;
|
||||
for (;;) {
|
||||
int count = head->commit - head->read;
|
||||
if (!count) {
|
||||
if (head->next == NULL)
|
||||
break;
|
||||
tbuf = head;
|
||||
head = head->next;
|
||||
tty_buffer_free(tty, tbuf);
|
||||
continue;
|
||||
}
|
||||
/* Ldisc or user is trying to flush the buffers
|
||||
we are feeding to the ldisc, stop feeding the
|
||||
line discipline as we want to empty the queue */
|
||||
if (test_bit(TTY_FLUSHPENDING, &tty->flags))
|
||||
break;
|
||||
if (!tty->receive_room) {
|
||||
schedule_delayed_work(&tty->buf.work, 1);
|
||||
break;
|
||||
}
|
||||
if (count > tty->receive_room)
|
||||
count = tty->receive_room;
|
||||
char_buf = head->char_buf_ptr + head->read;
|
||||
flag_buf = head->flag_buf_ptr + head->read;
|
||||
head->read += count;
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
disc->ops->receive_buf(tty, char_buf,
|
||||
flag_buf, count);
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
}
|
||||
/* Restore the queue head */
|
||||
tty->buf.head = head;
|
||||
}
|
||||
/* We may have a deferred request to flush the input buffer,
|
||||
if so pull the chain under the lock and empty the queue */
|
||||
if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
|
||||
__tty_buffer_flush(tty);
|
||||
clear_bit(TTY_FLUSHPENDING, &tty->flags);
|
||||
wake_up(&tty->read_wait);
|
||||
}
|
||||
clear_bit(TTY_FLUSHING, &tty->flags);
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
|
||||
tty_ldisc_deref(disc);
|
||||
}
|
||||
|
||||
/**
|
||||
* tty_flip_buffer_push - terminal
|
||||
* @tty: tty to push
|
||||
*
|
||||
* Queue a push of the terminal flip buffers to the line discipline. This
|
||||
* function must not be called from IRQ context if tty->low_latency is set.
|
||||
*
|
||||
* In the event of the queue being busy for flipping the work will be
|
||||
* held off and retried later.
|
||||
*
|
||||
* Locking: tty buffer lock. Driver locks in low latency mode.
|
||||
*/
|
||||
|
||||
void tty_flip_buffer_push(struct tty_struct *tty)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&tty->buf.lock, flags);
|
||||
if (tty->buf.tail != NULL)
|
||||
tty->buf.tail->commit = tty->buf.tail->used;
|
||||
spin_unlock_irqrestore(&tty->buf.lock, flags);
|
||||
|
||||
if (tty->low_latency)
|
||||
flush_to_ldisc(&tty->buf.work.work);
|
||||
else
|
||||
schedule_delayed_work(&tty->buf.work, 1);
|
||||
}
|
||||
EXPORT_SYMBOL(tty_flip_buffer_push);
|
||||
|
||||
/**
|
||||
* tty_buffer_init - prepare a tty buffer structure
|
||||
* @tty: tty to initialise
|
||||
*
|
||||
* Set up the initial state of the buffer management for a tty device.
|
||||
* Must be called before the other tty buffer functions are used.
|
||||
*
|
||||
* Locking: none
|
||||
*/
|
||||
|
||||
void tty_buffer_init(struct tty_struct *tty)
|
||||
{
|
||||
spin_lock_init(&tty->buf.lock);
|
||||
tty->buf.head = NULL;
|
||||
tty->buf.tail = NULL;
|
||||
tty->buf.free = NULL;
|
||||
tty->buf.memory_used = 0;
|
||||
INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -40,6 +40,15 @@
|
|||
#define TERMIOS_OLD 8
|
||||
|
||||
|
||||
/**
|
||||
* tty_chars_in_buffer - characters pending
|
||||
* @tty: terminal
|
||||
*
|
||||
* Return the number of bytes of data in the device private
|
||||
* output queue. If no private method is supplied there is assumed
|
||||
* to be no queue on the device.
|
||||
*/
|
||||
|
||||
int tty_chars_in_buffer(struct tty_struct *tty)
|
||||
{
|
||||
if (tty->ops->chars_in_buffer)
|
||||
|
|
@ -47,26 +56,49 @@ int tty_chars_in_buffer(struct tty_struct *tty)
|
|||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(tty_chars_in_buffer);
|
||||
|
||||
/**
|
||||
* tty_write_room - write queue space
|
||||
* @tty: terminal
|
||||
*
|
||||
* Return the number of bytes that can be queued to this device
|
||||
* at the present time. The result should be treated as a guarantee
|
||||
* and the driver cannot offer a value it later shrinks by more than
|
||||
* the number of bytes written. If no method is provided 2K is always
|
||||
* returned and data may be lost as there will be no flow control.
|
||||
*/
|
||||
|
||||
int tty_write_room(struct tty_struct *tty)
|
||||
{
|
||||
if (tty->ops->write_room)
|
||||
return tty->ops->write_room(tty);
|
||||
return 2048;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(tty_write_room);
|
||||
|
||||
/**
|
||||
* tty_driver_flush_buffer - discard internal buffer
|
||||
* @tty: terminal
|
||||
*
|
||||
* Discard the internal output buffer for this device. If no method
|
||||
* is provided then either the buffer cannot be hardware flushed or
|
||||
* there is no buffer driver side.
|
||||
*/
|
||||
void tty_driver_flush_buffer(struct tty_struct *tty)
|
||||
{
|
||||
if (tty->ops->flush_buffer)
|
||||
tty->ops->flush_buffer(tty);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(tty_driver_flush_buffer);
|
||||
|
||||
/**
|
||||
* tty_throttle - flow control
|
||||
* @tty: terminal
|
||||
*
|
||||
* Indicate that a tty should stop transmitting data down the stack.
|
||||
*/
|
||||
|
||||
void tty_throttle(struct tty_struct *tty)
|
||||
{
|
||||
/* check TTY_THROTTLED first so it indicates our state */
|
||||
|
|
@ -76,6 +108,13 @@ void tty_throttle(struct tty_struct *tty)
|
|||
}
|
||||
EXPORT_SYMBOL(tty_throttle);
|
||||
|
||||
/**
|
||||
* tty_unthrottle - flow control
|
||||
* @tty: terminal
|
||||
*
|
||||
* Indicate that a tty may continue transmitting data down the stack.
|
||||
*/
|
||||
|
||||
void tty_unthrottle(struct tty_struct *tty)
|
||||
{
|
||||
if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
|
||||
|
|
@ -112,6 +151,11 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout)
|
|||
}
|
||||
EXPORT_SYMBOL(tty_wait_until_sent);
|
||||
|
||||
|
||||
/*
|
||||
* Termios Helper Methods
|
||||
*/
|
||||
|
||||
static void unset_locked_termios(struct ktermios *termios,
|
||||
struct ktermios *old,
|
||||
struct ktermios *locked)
|
||||
|
|
@ -346,6 +390,16 @@ void tty_termios_encode_baud_rate(struct ktermios *termios,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
|
||||
|
||||
/**
|
||||
* tty_encode_baud_rate - set baud rate of the tty
|
||||
* @ibaud: input baud rate
|
||||
* @obad: output baud rate
|
||||
*
|
||||
* Update the current termios data for the tty with the new speed
|
||||
* settings. The caller must hold the termios_mutex for the tty in
|
||||
* question.
|
||||
*/
|
||||
|
||||
void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
|
||||
{
|
||||
tty_termios_encode_baud_rate(tty->termios, ibaud, obaud);
|
||||
|
|
@ -430,12 +484,11 @@ EXPORT_SYMBOL(tty_termios_hw_change);
|
|||
* is a bit of layering violation here with n_tty in terms of the
|
||||
* internal knowledge of this function.
|
||||
*
|
||||
* Locking: termios_sem
|
||||
* Locking: termios_mutex
|
||||
*/
|
||||
|
||||
static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
|
||||
{
|
||||
int canon_change;
|
||||
struct ktermios old_termios;
|
||||
struct tty_ldisc *ld;
|
||||
unsigned long flags;
|
||||
|
|
@ -451,18 +504,6 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
|
|||
old_termios = *tty->termios;
|
||||
*tty->termios = *new_termios;
|
||||
unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
|
||||
canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
|
||||
if (canon_change) {
|
||||
memset(&tty->read_flags, 0, sizeof tty->read_flags);
|
||||
tty->canon_head = tty->read_tail;
|
||||
tty->canon_data = 0;
|
||||
tty->erasing = 0;
|
||||
}
|
||||
|
||||
/* This bit should be in the ldisc code */
|
||||
if (canon_change && !L_ICANON(tty) && tty->read_cnt)
|
||||
/* Get characters left over from canonical mode. */
|
||||
wake_up_interruptible(&tty->read_wait);
|
||||
|
||||
/* See if packet mode change of state. */
|
||||
if (tty->link && tty->link->packet) {
|
||||
|
|
@ -508,7 +549,7 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
|
|||
* functions before using change_termios to do the actual changes.
|
||||
*
|
||||
* Locking:
|
||||
* Called functions take ldisc and termios_sem locks
|
||||
* Called functions take ldisc and termios_mutex locks
|
||||
*/
|
||||
|
||||
static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
|
||||
|
|
@ -579,25 +620,51 @@ static int get_termio(struct tty_struct *tty, struct termio __user *termio)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long inq_canon(struct tty_struct *tty)
|
||||
{
|
||||
int nr, head, tail;
|
||||
|
||||
if (!tty->canon_data || !tty->read_buf)
|
||||
return 0;
|
||||
head = tty->canon_head;
|
||||
tail = tty->read_tail;
|
||||
nr = (head - tail) & (N_TTY_BUF_SIZE-1);
|
||||
/* Skip EOF-chars.. */
|
||||
while (head != tail) {
|
||||
if (test_bit(tail, tty->read_flags) &&
|
||||
tty->read_buf[tail] == __DISABLED_CHAR)
|
||||
nr--;
|
||||
tail = (tail+1) & (N_TTY_BUF_SIZE-1);
|
||||
#ifdef TCGETX
|
||||
|
||||
/**
|
||||
* set_termiox - set termiox fields if possible
|
||||
* @tty: terminal
|
||||
* @arg: termiox structure from user
|
||||
* @opt: option flags for ioctl type
|
||||
*
|
||||
* Implement the device calling points for the SYS5 termiox ioctl
|
||||
* interface in Linux
|
||||
*/
|
||||
|
||||
static int set_termiox(struct tty_struct *tty, void __user *arg, int opt)
|
||||
{
|
||||
struct termiox tnew;
|
||||
struct tty_ldisc *ld;
|
||||
|
||||
if (tty->termiox == NULL)
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&tnew, arg, sizeof(struct termiox)))
|
||||
return -EFAULT;
|
||||
|
||||
ld = tty_ldisc_ref(tty);
|
||||
if (ld != NULL) {
|
||||
if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
|
||||
ld->ops->flush_buffer(tty);
|
||||
tty_ldisc_deref(ld);
|
||||
}
|
||||
return nr;
|
||||
if (opt & TERMIOS_WAIT) {
|
||||
tty_wait_until_sent(tty, 0);
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
mutex_lock(&tty->termios_mutex);
|
||||
if (tty->ops->set_termiox)
|
||||
tty->ops->set_termiox(tty, &tnew);
|
||||
mutex_unlock(&tty->termios_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TIOCGETP
|
||||
/*
|
||||
* These are deprecated, but there is limited support..
|
||||
|
|
@ -671,7 +738,7 @@ static void set_sgflags(struct ktermios *termios, int flags)
|
|||
* Updates a terminal from the legacy BSD style terminal information
|
||||
* structure.
|
||||
*
|
||||
* Locking: termios_sem
|
||||
* Locking: termios_mutex
|
||||
*/
|
||||
|
||||
static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
|
||||
|
|
@ -849,6 +916,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
|
|||
{
|
||||
struct tty_struct *real_tty;
|
||||
void __user *p = (void __user *)arg;
|
||||
int ret = 0;
|
||||
|
||||
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
|
||||
tty->driver->subtype == PTY_TYPE_MASTER)
|
||||
|
|
@ -884,18 +952,24 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
|
|||
return set_termios(real_tty, p, TERMIOS_OLD);
|
||||
#ifndef TCGETS2
|
||||
case TCGETS:
|
||||
mutex_lock(&real_tty->termios_mutex);
|
||||
if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
ret = -EFAULT;
|
||||
mutex_unlock(&real_tty->termios_mutex);
|
||||
return ret;
|
||||
#else
|
||||
case TCGETS:
|
||||
mutex_lock(&real_tty->termios_mutex);
|
||||
if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
ret = -EFAULT;
|
||||
mutex_unlock(&real_tty->termios_mutex);
|
||||
return ret;
|
||||
case TCGETS2:
|
||||
mutex_lock(&real_tty->termios_mutex);
|
||||
if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
ret = -EFAULT;
|
||||
mutex_unlock(&real_tty->termios_mutex);
|
||||
return ret;
|
||||
case TCSETSF2:
|
||||
return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
|
||||
case TCSETSW2:
|
||||
|
|
@ -913,34 +987,59 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
|
|||
return set_termios(real_tty, p, TERMIOS_TERMIO);
|
||||
#ifndef TCGETS2
|
||||
case TIOCGLCKTRMIOS:
|
||||
mutex_lock(&real_tty->termios_mutex);
|
||||
if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
ret = -EFAULT;
|
||||
mutex_unlock(&real_tty->termios_mutex);
|
||||
return ret;
|
||||
case TIOCSLCKTRMIOS:
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
mutex_lock(&real_tty->termios_mutex);
|
||||
if (user_termios_to_kernel_termios(real_tty->termios_locked,
|
||||
(struct termios __user *) arg))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
ret = -EFAULT;
|
||||
mutex_unlock(&real_tty->termios_mutex);
|
||||
return ret;
|
||||
#else
|
||||
case TIOCGLCKTRMIOS:
|
||||
mutex_lock(&real_tty->termios_mutex);
|
||||
if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
ret = -EFAULT;
|
||||
mutex_unlock(&real_tty->termios_mutex);
|
||||
return ret;
|
||||
case TIOCSLCKTRMIOS:
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
ret = -EPERM;
|
||||
mutex_lock(&real_tty->termios_mutex);
|
||||
if (user_termios_to_kernel_termios_1(real_tty->termios_locked,
|
||||
(struct termios __user *) arg))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
ret = -EFAULT;
|
||||
mutex_unlock(&real_tty->termios_mutex);
|
||||
return ret;
|
||||
#endif
|
||||
#ifdef TCGETX
|
||||
case TCGETX:
|
||||
if (real_tty->termiox == NULL)
|
||||
return -EINVAL;
|
||||
mutex_lock(&real_tty->termios_mutex);
|
||||
if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox)))
|
||||
ret = -EFAULT;
|
||||
mutex_unlock(&real_tty->termios_mutex);
|
||||
return ret;
|
||||
case TCSETX:
|
||||
return set_termiox(real_tty, p, 0);
|
||||
case TCSETXW:
|
||||
return set_termiox(real_tty, p, TERMIOS_WAIT);
|
||||
case TCSETXF:
|
||||
return set_termiox(real_tty, p, TERMIOS_FLUSH);
|
||||
#endif
|
||||
case TIOCGSOFTCAR:
|
||||
/* FIXME: for correctness we may need to take the termios
|
||||
lock here - review */
|
||||
return put_user(C_CLOCAL(real_tty) ? 1 : 0,
|
||||
mutex_lock(&real_tty->termios_mutex);
|
||||
ret = put_user(C_CLOCAL(real_tty) ? 1 : 0,
|
||||
(int __user *)arg);
|
||||
mutex_unlock(&real_tty->termios_mutex);
|
||||
return ret;
|
||||
case TIOCSSOFTCAR:
|
||||
if (get_user(arg, (unsigned int __user *) arg))
|
||||
return -EFAULT;
|
||||
|
|
@ -980,7 +1079,7 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(tty_perform_flush);
|
||||
|
||||
int n_tty_ioctl(struct tty_struct *tty, struct file *file,
|
||||
int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
|
@ -1018,13 +1117,6 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
|
|||
return 0;
|
||||
case TCFLSH:
|
||||
return tty_perform_flush(tty, arg);
|
||||
case TIOCOUTQ:
|
||||
return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
|
||||
case TIOCINQ:
|
||||
retval = tty->read_cnt;
|
||||
if (L_ICANON(tty))
|
||||
retval = inq_canon(tty);
|
||||
return put_user(retval, (unsigned int __user *) arg);
|
||||
case TIOCPKT:
|
||||
{
|
||||
int pktmode;
|
||||
|
|
@ -1050,4 +1142,4 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
|
|||
return tty_mode_ioctl(tty, file, cmd, arg);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(n_tty_ioctl);
|
||||
EXPORT_SYMBOL(n_tty_ioctl_helper);
|
||||
|
|
|
|||
96
drivers/char/tty_port.c
Normal file
96
drivers/char/tty_port.c
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Tty port functions
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_driver.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
void tty_port_init(struct tty_port *port)
|
||||
{
|
||||
memset(port, 0, sizeof(*port));
|
||||
init_waitqueue_head(&port->open_wait);
|
||||
init_waitqueue_head(&port->close_wait);
|
||||
mutex_init(&port->mutex);
|
||||
spin_lock_init(&port->lock);
|
||||
port->close_delay = (50 * HZ) / 100;
|
||||
port->closing_wait = (3000 * HZ) / 100;
|
||||
}
|
||||
EXPORT_SYMBOL(tty_port_init);
|
||||
|
||||
int tty_port_alloc_xmit_buf(struct tty_port *port)
|
||||
{
|
||||
/* We may sleep in get_zeroed_page() */
|
||||
mutex_lock(&port->mutex);
|
||||
if (port->xmit_buf == NULL)
|
||||
port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
|
||||
mutex_unlock(&port->mutex);
|
||||
if (port->xmit_buf == NULL)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
|
||||
|
||||
void tty_port_free_xmit_buf(struct tty_port *port)
|
||||
{
|
||||
mutex_lock(&port->mutex);
|
||||
if (port->xmit_buf != NULL) {
|
||||
free_page((unsigned long)port->xmit_buf);
|
||||
port->xmit_buf = NULL;
|
||||
}
|
||||
mutex_unlock(&port->mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(tty_port_free_xmit_buf);
|
||||
|
||||
|
||||
/**
|
||||
* tty_port_tty_get - get a tty reference
|
||||
* @port: tty port
|
||||
*
|
||||
* Return a refcount protected tty instance or NULL if the port is not
|
||||
* associated with a tty (eg due to close or hangup)
|
||||
*/
|
||||
|
||||
struct tty_struct *tty_port_tty_get(struct tty_port *port)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct tty_struct *tty;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
tty = tty_kref_get(port->tty);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
return tty;
|
||||
}
|
||||
EXPORT_SYMBOL(tty_port_tty_get);
|
||||
|
||||
/**
|
||||
* tty_port_tty_set - set the tty of a port
|
||||
* @port: tty port
|
||||
* @tty: the tty
|
||||
*
|
||||
* Associate the port and tty pair. Manages any internal refcounts.
|
||||
* Pass NULL to deassociate a port
|
||||
*/
|
||||
|
||||
void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
if (port->tty)
|
||||
tty_kref_put(port->tty);
|
||||
port->tty = tty;
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(tty_port_tty_set);
|
||||
|
|
@ -100,10 +100,10 @@
|
|||
#include <linux/font.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/notifier.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#define MAX_NR_CON_DRIVER 16
|
||||
|
||||
|
|
@ -2136,27 +2136,9 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
|
|||
release_console_sem();
|
||||
return 0;
|
||||
}
|
||||
release_console_sem();
|
||||
|
||||
orig_buf = buf;
|
||||
orig_count = count;
|
||||
|
||||
/* At this point 'buf' is guaranteed to be a kernel buffer
|
||||
* and therefore no access to userspace (and therefore sleeping)
|
||||
* will be needed. The con_buf_mtx serializes all tty based
|
||||
* console rendering and vcs write/read operations. We hold
|
||||
* the console spinlock during the entire write.
|
||||
*/
|
||||
|
||||
acquire_console_sem();
|
||||
|
||||
vc = tty->driver_data;
|
||||
if (vc == NULL) {
|
||||
printk(KERN_ERR "vt: argh, driver_data _became_ NULL !\n");
|
||||
release_console_sem();
|
||||
goto out;
|
||||
}
|
||||
|
||||
himask = vc->vc_hi_font_mask;
|
||||
charmask = himask ? 0x1ff : 0xff;
|
||||
|
||||
|
|
@ -2370,8 +2352,6 @@ rescan_last_byte:
|
|||
FLUSH
|
||||
console_conditional_schedule();
|
||||
release_console_sem();
|
||||
|
||||
out:
|
||||
notify_update(vc);
|
||||
return n;
|
||||
#undef FLUSH
|
||||
|
|
@ -2583,8 +2563,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
|
|||
int lines;
|
||||
int ret;
|
||||
|
||||
if (tty->driver->type != TTY_DRIVER_TYPE_CONSOLE)
|
||||
return -EINVAL;
|
||||
if (current->signal->tty != tty && !capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
if (get_user(type, p))
|
||||
|
|
@ -2778,6 +2756,12 @@ static int con_open(struct tty_struct *tty, struct file *filp)
|
|||
ret = vc_allocate(currcons);
|
||||
if (ret == 0) {
|
||||
struct vc_data *vc = vc_cons[currcons].d;
|
||||
|
||||
/* Still being freed */
|
||||
if (vc->vc_tty) {
|
||||
release_console_sem();
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
tty->driver_data = vc;
|
||||
vc->vc_tty = tty;
|
||||
|
||||
|
|
@ -2798,34 +2782,20 @@ static int con_open(struct tty_struct *tty, struct file *filp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* We take tty_mutex in here to prevent another thread from coming in via init_dev
|
||||
* and taking a ref against the tty while we're in the process of forgetting
|
||||
* about it and cleaning things up.
|
||||
*
|
||||
* This is because vcs_remove_sysfs() can sleep and will drop the BKL.
|
||||
*/
|
||||
static void con_close(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
mutex_lock(&tty_mutex);
|
||||
acquire_console_sem();
|
||||
if (tty && tty->count == 1) {
|
||||
struct vc_data *vc = tty->driver_data;
|
||||
/* Nothing to do - we defer to shutdown */
|
||||
}
|
||||
|
||||
if (vc)
|
||||
vc->vc_tty = NULL;
|
||||
tty->driver_data = NULL;
|
||||
vcs_remove_sysfs(tty);
|
||||
release_console_sem();
|
||||
mutex_unlock(&tty_mutex);
|
||||
/*
|
||||
* tty_mutex is released, but we still hold BKL, so there is
|
||||
* still exclusion against init_dev()
|
||||
*/
|
||||
return;
|
||||
}
|
||||
static void con_shutdown(struct tty_struct *tty)
|
||||
{
|
||||
struct vc_data *vc = tty->driver_data;
|
||||
BUG_ON(vc == NULL);
|
||||
acquire_console_sem();
|
||||
vc->vc_tty = NULL;
|
||||
vcs_remove_sysfs(tty);
|
||||
release_console_sem();
|
||||
mutex_unlock(&tty_mutex);
|
||||
tty_shutdown(tty);
|
||||
}
|
||||
|
||||
static int default_italic_color = 2; // green (ASCII)
|
||||
|
|
@ -2950,10 +2920,19 @@ static const struct tty_operations con_ops = {
|
|||
.throttle = con_throttle,
|
||||
.unthrottle = con_unthrottle,
|
||||
.resize = vt_resize,
|
||||
.shutdown = con_shutdown
|
||||
};
|
||||
|
||||
int __init vty_init(void)
|
||||
static struct cdev vc0_cdev;
|
||||
|
||||
int __init vty_init(const struct file_operations *console_fops)
|
||||
{
|
||||
cdev_init(&vc0_cdev, console_fops);
|
||||
if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
|
||||
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
|
||||
panic("Couldn't register /dev/tty0 driver\n");
|
||||
device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
|
||||
|
||||
vcs_init();
|
||||
|
||||
console_driver = alloc_tty_driver(MAX_NR_CONSOLES);
|
||||
|
|
@ -2972,7 +2951,6 @@ int __init vty_init(void)
|
|||
tty_set_operations(console_driver, &con_ops);
|
||||
if (tty_register_driver(console_driver))
|
||||
panic("Couldn't register console driver\n");
|
||||
|
||||
kbd_init();
|
||||
console_map_init();
|
||||
#ifdef CONFIG_PROM_CONSOLE
|
||||
|
|
@ -3466,7 +3444,7 @@ int register_con_driver(const struct consw *csw, int first, int last)
|
|||
if (retval)
|
||||
goto err;
|
||||
|
||||
con_driver->dev = device_create_drvdata(vtconsole_class, NULL,
|
||||
con_driver->dev = device_create(vtconsole_class, NULL,
|
||||
MKDEV(0, con_driver->node),
|
||||
NULL, "vtcon%i",
|
||||
con_driver->node);
|
||||
|
|
@ -3577,7 +3555,7 @@ static int __init vtconsole_class_init(void)
|
|||
struct con_driver *con = ®istered_con_driver[i];
|
||||
|
||||
if (con->con && !con->dev) {
|
||||
con->dev = device_create_drvdata(vtconsole_class, NULL,
|
||||
con->dev = device_create(vtconsole_class, NULL,
|
||||
MKDEV(0, con->node),
|
||||
NULL, "vtcon%i",
|
||||
con->node);
|
||||
|
|
|
|||
|
|
@ -395,6 +395,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
|
|||
|
||||
kbd = kbd_table + console;
|
||||
switch (cmd) {
|
||||
case TIOCLINUX:
|
||||
return tioclinux(tty, arg);
|
||||
case KIOCSOUND:
|
||||
if (!perm)
|
||||
goto eperm;
|
||||
|
|
|
|||
Loading…
Reference in a new issue