From 5b35aa5cd29bb111d847b2a2ed18110acbfb1f44 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Thu, 27 Jan 2000 23:45:22 +0000 Subject: Merge with Linux 2.3.24. --- drivers/block/Config.in | 3 + drivers/block/DAC960.c | 12 +- drivers/block/cpqarray.c | 23 + drivers/block/ll_rw_blk.c | 66 +- drivers/block/rd.c | 7 +- drivers/char/bttv.c | 3 +- drivers/char/drm/proc.c | 2 +- drivers/char/serial.c | 1 + drivers/i2o/i2o_block.c | 28 +- drivers/i2o/i2o_config.c | 24 +- drivers/i2o/i2o_core.c | 1351 ++++++++++++------- drivers/i2o/i2o_lan.c | 102 +- drivers/i2o/i2o_pci.c | 143 +- drivers/i2o/i2o_proc.c | 138 +- drivers/i2o/i2o_scsi.c | 29 +- drivers/macintosh/macserial.c | 6 +- drivers/misc/acpi.c | 697 ++++++---- drivers/net/Config.in | 2 + drivers/net/Makefile | 18 + drivers/net/arcnet.c | 2827 +++++++++++++++++++--------------------- drivers/net/irda/actisys.c | 179 +-- drivers/net/irda/airport.c | 60 +- drivers/net/irda/esi.c | 111 +- drivers/net/irda/girbil.c | 209 +-- drivers/net/irda/irport.c | 416 +++--- drivers/net/irda/irtty.c | 623 ++++++--- drivers/net/irda/litelink.c | 85 +- drivers/net/irda/pc87108.c | 785 +++++------ drivers/net/irda/smc-ircc.c | 114 +- drivers/net/irda/tekram.c | 192 +-- drivers/net/irda/toshoboe.c | 310 ++--- drivers/net/irda/uircc.c | 62 +- drivers/net/irda/w83977af_ir.c | 522 ++++---- drivers/net/pcmcia/ray_cs.c | 612 +++++++-- drivers/net/pcmcia/ray_cs.h | 11 + drivers/net/ppp_generic.c | 4 + drivers/net/ppp_synctty.c | 768 +++++++++++ drivers/net/strip.c | 1 + drivers/pci/pcisyms.c | 1 + drivers/pcmcia/rsrc_mgr.c | 20 +- drivers/scsi/script_asm.pl | 16 +- drivers/sound/ac97.c | 86 +- drivers/sound/ac97.h | 6 +- drivers/sound/nm256.h | 124 +- drivers/sound/nm256_audio.c | 721 +++++++--- drivers/sound/nm256_coeff.h | 14 +- drivers/usb/acm.c | 6 +- drivers/usb/cpia.c | 2 +- drivers/usb/ezusb.c | 3 - drivers/usb/hub.c | 46 +- drivers/usb/hub.h | 26 +- drivers/usb/ohci-hcd.c | 93 +- drivers/usb/ohci-hcd.h | 7 +- drivers/usb/uhci.c | 5 +- drivers/usb/usb-serial.c | 5 +- 55 files changed, 7153 insertions(+), 4574 deletions(-) create mode 100644 drivers/net/ppp_synctty.c (limited to 'drivers') diff --git a/drivers/block/Config.in b/drivers/block/Config.in index 7f70e32ee..897aaa634 100644 --- a/drivers/block/Config.in +++ b/drivers/block/Config.in @@ -200,6 +200,9 @@ if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD fi tristate 'XT hard disk support' CONFIG_BLK_DEV_XD +if [ "$CONFIG_PCI" = "y" ]; then + tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 +fi # PARIDE doesn't need PARPORT, but if PARPORT is configured as a module, # PARIDE must also be a module. The bogus CONFIG_PARIDE_PARPORT option diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 06eed2279..9f26a4b5e 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -19,8 +19,8 @@ */ -#define DAC960_DriverVersion "2.2.4" -#define DAC960_DriverDate "23 August 1999" +#define DAC960_DriverVersion "2.3.4" +#define DAC960_DriverDate "23 September 1999" #include @@ -256,7 +256,7 @@ static void DAC960_QueueCommand(DAC960_Command_T *Command) static boolean DAC960_ExecuteCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; - Semaphore_T Semaphore = MUTEX_LOCKED; + DECLARE_MUTEX_LOCKED(Semaphore); unsigned long ProcessorFlags; Command->Semaphore = &Semaphore; DAC960_AcquireControllerLock(Controller, &ProcessorFlags); @@ -475,8 +475,8 @@ static void DAC960_DetectControllers(DAC960_ControllerType_T ControllerType) unsigned char Device = DeviceFunction >> 3; unsigned char Function = DeviceFunction & 0x7; unsigned int IRQ_Channel = PCI_Device->irq; - unsigned long BaseAddress0 = PCI_Device->base_address[0]; - unsigned long BaseAddress1 = PCI_Device->base_address[1]; + unsigned long BaseAddress0 = PCI_Device->resource[0].start; + unsigned long BaseAddress1 = PCI_Device->resource[1].start; unsigned short SubsystemVendorID, SubsystemDeviceID; int CommandIdentifier; pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_VENDOR_ID, @@ -825,7 +825,7 @@ static boolean DAC960_ReadDeviceConfiguration(DAC960_Controller_T *Controller) &Controller->InquiryStandardData[Channel][TargetID]; InquiryStandardData->PeripheralDeviceType = 0x1F; Semaphore = &Semaphores[Channel]; - *Semaphore = MUTEX_LOCKED; + init_MUTEX_LOCKED(Semaphore); DCDB = &DCDBs[Channel]; DAC960_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 579fbc13a..92b1c7d4d 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -703,6 +704,26 @@ static ulong remap_pci_mem(ulong base, ulong size) return (ulong) (page_remapped ? (page_remapped + page_offs) : 0UL); } +#ifndef MODULE +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13) +/* + * Config string is a comma seperated set of i/o addresses of EISA cards. + */ +static int cpqarray_setup(char *str) +{ + int i, ints[9]; + + (void)get_options(str, ARRAY_SIZE(ints), ints); + + for(i=0; irq_dev); - int minor = MINOR(req->rq_dev); struct request * tmp, **current_request; - short disk_index; unsigned long flags; int queue_new_request = 0; - switch (major) { - case DAC960_MAJOR+0: - disk_index = (minor & 0x00f8) >> 3; - if (disk_index < 4) - drive_stat_acct(req->cmd, req->nr_sectors, disk_index); - break; - case SCSI_DISK0_MAJOR: - disk_index = (minor & 0x00f0) >> 4; - if (disk_index < 4) - drive_stat_acct(req->cmd, req->nr_sectors, disk_index); - break; - case IDE0_MAJOR: /* same as HD_MAJOR */ - case XT_DISK_MAJOR: - disk_index = (minor & 0x0040) >> 6; - drive_stat_acct(req->cmd, req->nr_sectors, disk_index); - break; - case IDE1_MAJOR: - disk_index = ((minor & 0x0040) >> 6) + 2; - drive_stat_acct(req->cmd, req->nr_sectors, disk_index); - default: - break; - } - + drive_stat_acct(req, req->nr_sectors, 1); req->next = NULL; /* @@ -575,6 +575,7 @@ void make_request(int major,int rw, struct buffer_head * bh) req->bhtail->b_reqnext = bh; req->bhtail = bh; req->nr_sectors += count; + drive_stat_acct(req, count, 0); /* Can we now merge this req with the next? */ attempt_merge(req, max_sectors); /* or to the beginning? */ @@ -585,6 +586,7 @@ void make_request(int major,int rw, struct buffer_head * bh) req->current_nr_sectors = count; req->sector = sector; req->nr_sectors += count; + drive_stat_acct(req, count, 0); } else continue; diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 7c2b23dab..9fec26361 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -276,12 +276,9 @@ static ssize_t initrd_read(struct file *file, char *buf, static int initrd_release(struct inode *inode,struct file *file) { - unsigned long i; - - if (--initrd_users) return 0; - for (i = initrd_start; i < initrd_end; i += PAGE_SIZE) - free_page(i); initrd_start = 0; + /* No need to actually release the pages, because that is + done later by free_all_bootmem. */ return 0; } diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c index ac21c68f0..17e87e7f8 100644 --- a/drivers/char/bttv.c +++ b/drivers/char/bttv.c @@ -121,8 +121,9 @@ static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) if (!pmd_none(*pmd)) { ptep = pte_offset(pmd, adr); pte = *ptep; + /* Note; page_address will panic for us if the page is high */ if(pte_present(pte)) - ret = (pte_page(pte)|(adr&(PAGE_SIZE-1))); + ret = page_address(pte_page(pte))|(adr&(PAGE_SIZE-1)); } } MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); diff --git a/drivers/char/drm/proc.c b/drivers/char/drm/proc.c index 7db90aea8..666b6e5ac 100644 --- a/drivers/char/drm/proc.c +++ b/drivers/char/drm/proc.c @@ -393,7 +393,7 @@ static int _drm_vma_info(char *buf, char **start, off_t offset, int len, pgprot & _PAGE_PCD ? 'u' : 'c', pgprot & _PAGE_ACCESSED ? 'a' : '-', pgprot & _PAGE_DIRTY ? 'd' : '-', - pgprot & _PAGE_4M ? 'm' : 'k', + pgprot & _PAGE_PSE ? 'm' : 'k', pgprot & _PAGE_GLOBAL ? 'g' : 'l' ); #endif DRM_PROC_PRINT("\n"); diff --git a/drivers/char/serial.c b/drivers/char/serial.c index 38bbf438b..45193f9ce 100644 --- a/drivers/char/serial.c +++ b/drivers/char/serial.c @@ -158,6 +158,7 @@ #ifdef LOCAL_HEADERS #include "serial_local.h" #else +#include #include #include #include diff --git a/drivers/i2o/i2o_block.c b/drivers/i2o/i2o_block.c index 5042f4e97..c06b61d2d 100644 --- a/drivers/i2o/i2o_block.c +++ b/drivers/i2o/i2o_block.c @@ -703,7 +703,7 @@ static int i2ob_release(struct inode *inode, struct file *file) msg[2] = i2ob_context|0x80000000; msg[3] = (u32)query_done; msg[4] = 60<<16; - i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2); + i2o_post_wait(dev->controller, msg, 20, 2); /* * Unlock the media */ @@ -712,7 +712,7 @@ static int i2ob_release(struct inode *inode, struct file *file) msg[2] = i2ob_context|0x80000000; msg[3] = (u32)query_done; msg[4] = -1; - i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2); + i2o_post_wait(dev->controller, msg, 20, 2); /* * Now unclaim the device. @@ -766,7 +766,7 @@ static int i2ob_open(struct inode *inode, struct file *file) msg[3] = (u32)query_done; msg[4] = -1; msg[5] = 0; - i2o_post_wait(dev->controller, dev->tid, msg, 24, query_done,2); + i2o_post_wait(dev->controller, msg, 24, 2); /* * Lock the media */ @@ -775,7 +775,7 @@ static int i2ob_open(struct inode *inode, struct file *file) msg[2] = i2ob_context|0x80000000; msg[3] = (u32)query_done; msg[4] = -1; - i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2); + i2o_post_wait(dev->controller, msg, 20, 2); } MOD_INC_USE_COUNT; return 0; @@ -788,8 +788,8 @@ static int i2ob_open(struct inode *inode, struct file *file) static int i2ob_query_device(struct i2ob_device *dev, int table, int field, void *buf, int buflen) { - return i2o_query_scalar(dev->controller, dev->tid, i2ob_context, - table, field, buf, buflen, &dev->done_flag); + return i2o_query_scalar(dev->controller, dev->tid, + table, field, buf, buflen); } @@ -891,7 +891,10 @@ static void i2ob_probe(void) for(d=c->devices;d!=NULL;d=d->next) { - if(d->class!=I2O_CLASS_RANDOM_BLOCK_STORAGE) + if(d->lct_data->class_id!=I2O_CLASS_RANDOM_BLOCK_STORAGE) + continue; + + if(d->lct_data->user_tid != 0xFFF) continue; if(uniti2odev = d; dev->controller = c; - dev->tid = d->id; + dev->tid = d->lct_data->tid; /* * Insure the device can be claimed @@ -930,9 +933,10 @@ static void i2ob_probe(void) else { if(!warned++) - printk("i2o_block: too many controllers, registering only %d.\n", unit>>4); + printk("i2o_block: too many device, registering only %d.\n", unit>>4); } } + i2o_unlock_controller(c); } i2ob_devices = unit; } @@ -981,7 +985,7 @@ static int i2ob_reboot_event(struct notifier_block *n, unsigned long code, void msg[2] = i2ob_context|0x80000000; msg[3] = (u32)query_done; msg[4] = 60<<16; - i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2); + i2o_post_wait(dev->controller, msg, 20, 2); /* * Unlock the media */ @@ -990,7 +994,7 @@ static int i2ob_reboot_event(struct notifier_block *n, unsigned long code, void msg[2] = i2ob_context|0x80000000; msg[3] = (u32)query_done; msg[4] = -1; - i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2); + i2o_post_wait(dev->controller, msg, 20, 2); } } return NOTIFY_DONE; @@ -1058,7 +1062,7 @@ int i2o_block_init(void) { int i; - printk(KERN_INFO "I2O block device OSM v0.07. (C) 1999 Red Hat Software.\n"); + printk(KERN_INFO "I2O Block Storage OSM v0.07. (C) 1999 Red Hat Software.\n"); /* * Register the block device interfaces diff --git a/drivers/i2o/i2o_config.c b/drivers/i2o/i2o_config.c index 518093ea0..c8682f077 100644 --- a/drivers/i2o/i2o_config.c +++ b/drivers/i2o/i2o_config.c @@ -317,14 +317,14 @@ static int ioctl_parms(unsigned long arg, unsigned int type) return -ENOMEM; } - len = i2o_issue_params(i2o_cmd, c, kcmd.tid, cfg_handler.context, - ops, kcmd.oplen, res, 65536, &i2o_cfg_token); + len = i2o_issue_params(i2o_cmd, c, kcmd.tid, + ops, kcmd.oplen, res, 65536); i2o_unlock_controller(c); kfree(ops); - if (len < 0) { + if (len) { kfree(res); - return len; /* -DetailedStatus */ + return len; /* -DetailedStatus || -ETIMEDOUT */ } put_user(len, kcmd.reslen); @@ -413,8 +413,8 @@ int ioctl_html(unsigned long arg) msg[8] = virt_to_phys(query); } - token = i2o_post_wait(c, cmd->tid, msg, 9*4, &i2o_cfg_token, 10); - if(token != I2O_POST_WAIT_OK) + token = i2o_post_wait(c, msg, 9*4, 10); + if(token) { i2o_unlock_controller(c); kfree(res); @@ -531,8 +531,8 @@ int ioctl_swdl(unsigned long arg) // Yes...that's one minute, but the spec states that // transfers take a long time, and I've seen just how // long they can take. - token = i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &i2o_cfg_token,60); - if (token != I2O_POST_WAIT_OK ) // Something very wrong + token = i2o_post_wait(c, msg, sizeof(msg), 60); + if (token) // Something very wrong { i2o_unlock_controller(c); printk("Timeout downloading software"); @@ -547,8 +547,8 @@ int ioctl_swdl(unsigned long arg) msg[4] |= (u32)maxfrag; msg[7] = (0xD0000000 | diff); __copy_from_user(buffer, kxfer.buf, 8192); - token = i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &i2o_cfg_token,60); - if( token != I2O_POST_WAIT_OK ) // Something very wrong + token = i2o_post_wait(c, msg, sizeof(msg), 60); + if(token) // Something very wrong { i2o_unlock_controller(c); printk("Timeout downloading software"); @@ -588,10 +588,10 @@ int ioctl_validate(unsigned long arg) msg[2] = (u32)i2o_cfg_context; msg[3] = 0; - token = i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg),&i2o_cfg_token, 10); + token = i2o_post_wait(c, msg, sizeof(msg), 10); i2o_unlock_controller(c); - if (token != I2O_POST_WAIT_OK) + if (token) { printk("Can't validate configuration, ErrorStatus = %d\n", token); diff --git a/drivers/i2o/i2o_core.c b/drivers/i2o/i2o_core.c index fe8a86483..c2ade9ded 100644 --- a/drivers/i2o/i2o_core.c +++ b/drivers/i2o/i2o_core.c @@ -1,22 +1,24 @@ -/* - * Core I2O structure managment - * - * (C) Copyright 1999 Red Hat Software +/* + * Core I2O structure managment + * + * (C) Copyright 1999 Red Hat Software * - * Written by Alan Cox, Building Number Three Ltd - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. + * Written by Alan Cox, Building Number Three Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * A lot of the I2O message side code from this is taken from the + * Red Creek RCPCI45 adapter driver by Red Creek Communications * - * A lot of the I2O message side code from this is taken from the - * Red Creek RCPCI45 adapter driver by Red Creek Communications - * - * Fixes by Philipp Rumpf - * Juha Sievänen - * Auvo Häkkinen - * Deepak Saxena + * Fixes by: + * Philipp Rumpf + * Juha Sievänen + * Auvo Häkkinen + * Deepak Saxena + * */ #include @@ -31,11 +33,16 @@ #include #include +#include +#include +#include + #include #include "i2o_lan.h" #define DRIVERDEBUG +// #define DEBUG_IRQ /* * Size of the I2O module table @@ -48,12 +55,36 @@ static int core_context = 0; static int reply_flag = 0; extern int i2o_online_controller(struct i2o_controller *c); +static int i2o_init_outbound_q(struct i2o_controller *c); static void i2o_core_reply(struct i2o_handler *, struct i2o_controller *, struct i2o_message *); static int i2o_add_management_user(struct i2o_device *, struct i2o_handler *); static int i2o_remove_management_user(struct i2o_device *, struct i2o_handler *); +static int i2o_quiesce_system(void); +static int i2o_enable_system(void); static void i2o_dump_message(u32 *); +static int i2o_lct_get(struct i2o_controller *); +static int i2o_hrt_get(struct i2o_controller *); + +static void i2o_sys_init(void); +static void i2o_sys_shutdown(void); + +static int i2o_build_sys_table(void); +static int i2o_systab_send(struct i2o_controller *c); + +/* + * I2O System Table. Contains information about + * all the IOPs in the system. Used to inform IOPs + * about each other's existence. + * + * sys_tbl_ver is the CurrentChangeIndicator that is + * used by IOPs to track changes. + */ +static struct i2o_sys_tbl *sys_tbl = NULL; +static int sys_tbl_ind = 0; +static int sys_tbl_len = 0; + #ifdef MODULE /* * Function table to send to bus specific layers @@ -76,6 +107,21 @@ extern void i2o_pci_core_detach(void); #endif /* MODULE */ +/* + * Structures and definitions for synchronous message posting. + * See i2o_post_wait() for description. + */ +struct i2o_post_wait_data +{ + int status; + u32 id; + wait_queue_head_t *wq; + struct i2o_post_wait_data *next; +}; +static struct i2o_post_wait_data *post_wait_queue = NULL; +static u32 post_wait_id = 0; // Unique ID for each post_wait +static spinlock_t post_wait_lock = SPIN_LOCK_UNLOCKED; +static void i2o_post_wait_complete(u32, int); /* Message handler */ static struct i2o_handler i2o_core_handler = @@ -85,6 +131,7 @@ static struct i2o_handler i2o_core_handler = 0 }; + /* * I2O configuration spinlock. This isnt a big deal for contention * so we have one only @@ -92,11 +139,17 @@ static struct i2o_handler i2o_core_handler = static spinlock_t i2o_configuration_lock = SPIN_LOCK_UNLOCKED; +/* + * I2O Core reply handler + * + * Only messages this should see are i2o_post_wait() replies + */ void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *m) { u32 *msg=(u32 *)m; - u32 *flag = (u32 *)msg[3]; + u32 status; + u32 context = msg[3]; #if 0 i2o_report_status(KERN_INFO, "i2o_core", msg); @@ -117,13 +170,18 @@ void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c, return; } - if (msg[4] >> 24) + if(msg[2]&0x80000000) // Post wait message { - i2o_report_status(KERN_WARNING, "i2o_core", msg); - *flag = -(msg[4] & 0xFFFF); + if (msg[4] >> 24) + { + i2o_report_status(KERN_WARNING, "i2o_core: post_wait reply", msg); + status = -(msg[4] & 0xFFFF); + } + else + status = I2O_POST_WAIT_OK; + + i2o_post_wait_complete(context, status); } - else - *flag = I2O_POST_WAIT_OK; } /* @@ -245,6 +303,12 @@ int i2o_install_controller(struct i2o_controller *c) c->next=i2o_controller_chain; i2o_controller_chain=c; c->unit = i; + c->page_frame = NULL; + c->hrt = NULL; + c->lct = NULL; + c->status_block = NULL; + printk(KERN_INFO "lct @ %p hrt @ %p status @ %p", + c->lct, c->hrt, c->status_block); sprintf(c->name, "i2o/iop%d", i); i2o_num_controllers++; spin_unlock(&i2o_configuration_lock); @@ -261,10 +325,14 @@ int i2o_delete_controller(struct i2o_controller *c) struct i2o_controller **p; int users; +#ifdef DRIVERDEBUG + printk(KERN_INFO "Deleting controller iop%d\n", c->unit); +#endif + spin_lock(&i2o_configuration_lock); if((users=atomic_read(&c->users))) { - printk("I2O: %d users for controller iop%d\n", users, c->unit); + printk(KERN_INFO "I2O: %d users for controller iop%d\n", users, c->unit); spin_unlock(&i2o_configuration_lock); return -EBUSY; } @@ -280,21 +348,6 @@ int i2o_delete_controller(struct i2o_controller *c) p=&i2o_controller_chain; - /* Send first SysQuiesce to other IOPs */ - while(*p) - { - if(*p!=c) - { - printk("Quiescing controller %p != %p\n", c, *p); - if(i2o_quiesce_controller(*p)<0) - printk(KERN_INFO "Unable to quiesce iop%d\n", - (*p)->unit); - } - p=&((*p)->next); - } - - p=&i2o_controller_chain; - while(*p) { if(*p==c) @@ -308,15 +361,26 @@ int i2o_delete_controller(struct i2o_controller *c) *p=c->next; spin_unlock(&i2o_configuration_lock); + + printk(KERN_INFO "hrt %p lct %p page_frame %p status_block %p\n", + c->hrt, c->lct, c->page_frame, c->status_block); if(c->page_frame) kfree(c->page_frame); if(c->hrt) kfree(c->hrt); if(c->lct) kfree(c->lct); - i2o_controllers[c->unit]=NULL; + if(c->status_block) + kfree(c->status_block); + kfree(c); + + i2o_controllers[c->unit]=NULL; + i2o_num_controllers--; +#ifdef DRIVERDEBUG + printk(KERN_INFO "iop deleted\n"); +#endif return 0; } p=&((*p)->next); @@ -360,7 +424,7 @@ int i2o_claim_device(struct i2o_device *d, struct i2o_handler *h, u32 type) return -EBUSY; } - if(i2o_issue_claim(d->controller,d->id, h->context, 1, &reply_flag, type) < 0) + if(i2o_issue_claim(d->controller,d->lct_data->tid, h->context, 1, &reply_flag, type)) { return -EBUSY; } @@ -395,8 +459,8 @@ int i2o_release_device(struct i2o_device *d, struct i2o_handler *h, u32 type) err = -ENOENT; else { - if(i2o_issue_claim(d->controller, d->id, h->context, 0, - &reply_flag, type) < 0) + if(i2o_issue_claim(d->controller, d->lct_data->tid, h->context, 0, + &reply_flag, type)) { err = -ENXIO; } @@ -418,8 +482,8 @@ int i2o_release_device(struct i2o_device *d, struct i2o_handler *h, u32 type) { atomic_dec(&d->controller->users); - if(i2o_issue_claim(d->controller,d->id, h->context, 0, - &reply_flag, type) < 0) + if(i2o_issue_claim(d->controller,d->lct_data->tid, h->context, 0, + &reply_flag, type)) err = -ENXIO; } @@ -468,7 +532,11 @@ void i2o_run_queue(struct i2o_controller *c) { struct i2o_message *m; u32 mv; - + +#ifdef DEBUG_IRQ + printk(KERN_INFO "iop%d interrupt\n", c->unit); +#endif + while((mv=I2O_REPLY_READ32(c))!=0xFFFFFFFF) { struct i2o_handler *i; @@ -478,7 +546,11 @@ void i2o_run_queue(struct i2o_controller *c) */ if(((m->function_addr>>24)&0xFF)==0x15) printk("UTFR!\n"); -// printk("dispatching.\n"); + +#ifdef DEBUG_IRQ + i2o_dump_message((u32*)m); +#endif + i=i2o_handlers[m->initiator_context&(MAX_I2O_MODULES-1)]; if(i) i->reply(i,c,m); @@ -572,8 +644,10 @@ u32 i2o_wait_message(struct i2o_controller *c, char *why) { if((jiffies-time)>=5*HZ) { +#ifdef DRIVERDEBUG printk(KERN_ERR "%s: Timeout waiting for message frame to send %s.\n", c->name, why); +#endif return 0xFFFFFFFF; } schedule(); @@ -596,8 +670,10 @@ u32 i2o_wait_reply(struct i2o_controller *c, char *why, int timeout) { if(jiffies-time >= timeout*HZ ) { +#ifdef DRIVERDEBUG printk(KERN_ERR "%s: timeout waiting for %s reply.\n", c->name, why); +#endif return 0xFFFFFFFF; } schedule(); @@ -686,8 +762,10 @@ static int i2o_query_scalar_polled(struct i2o_controller *c, int tid, void *buf, /* Do we have an error block ? */ if(p[1]&0xFF000000) { +#ifdef DRIVERDEBUG printk(KERN_ERR "%s: error in field read.\n", c->name); +#endif kfree(rbuf); return -EBADR; } @@ -711,25 +789,27 @@ static int i2o_query_scalar_polled(struct i2o_controller *c, int tid, void *buf, void i2o_report_controller_unit(struct i2o_controller *c, int unit) { char buf[64]; + return; - if(i2o_query_scalar_polled(c, unit, buf, 16, 0xF100, 3)>=0) + if(i2o_query_scalar(c, unit, 0xF100, 3, buf, 16)) { buf[16]=0; printk(KERN_INFO " Vendor: %s\n", buf); } - if(i2o_query_scalar_polled(c, unit, buf, 16, 0xF100, 4)>=0) + if(i2o_query_scalar(c, unit, 0xF100, 4, buf, 16)) { + buf[16]=0; printk(KERN_INFO " Device: %s\n", buf); } #if 0 - if(i2o_query_scalar_polled(c, unit, buf, 16, 0xF100, 5)>=0) + if(i2o_query_scalar(c, unit, 0xF100, 5, buf, 16)) { buf[16]=0; printk(KERN_INFO "Description: %s\n", buf); } #endif - if(i2o_query_scalar_polled(c, unit, buf, 8, 0xF100, 6)>=0) + if(i2o_query_scalar(c, unit, 0xF100, 6, buf, 8)) { buf[8]=0; printk(KERN_INFO " Rev: %s\n", buf); @@ -749,6 +829,7 @@ void i2o_report_controller_unit(struct i2o_controller *c, int unit) static int i2o_parse_hrt(struct i2o_controller *c) { +#ifdef DRIVERDEBUG u32 *rows=c->hrt; u8 *p=(u8 *)c->hrt; u8 *d; @@ -766,8 +847,8 @@ static int i2o_parse_hrt(struct i2o_controller *c) count=p[0]|(p[1]<<8); length = p[2]; - printk(KERN_INFO "HRT has %d entries of %d bytes each.\n", - count, length<<2); + printk(KERN_INFO "iop%d: HRT has %d entries of %d bytes each.\n", + c->unit, count, length<<2); rows+=2; @@ -829,6 +910,7 @@ static int i2o_parse_hrt(struct i2o_controller *c) printk("\n"); rows+=length; } +#endif return 0; } @@ -845,12 +927,12 @@ static int i2o_parse_lct(struct i2o_controller *c) u32 *p; struct i2o_device *d; char str[22]; - u32 *lct=(u32 *)c->lct; + pi2o_lct lct = c->lct; - max=lct[0]&0xFFFF; + max = lct->table_size; - max-=3; - max/=9; + max -= 3; + max /= 9; if(max==0) { @@ -866,28 +948,25 @@ static int i2o_parse_lct(struct i2o_controller *c) max=128; } - if(lct[1]&(1<<0)) - printk(KERN_WARNING "Configuration dialog desired.\n"); + if(lct->iop_flags&(1<<0)) + printk(KERN_WARNING "I2O: Configuration dialog desired by iop%d.\n", c->unit); - p=lct+3; - for(i=0;icontroller = c; d->next = NULL; - - d->id = tid = (p[0]>>16)&0xFFF; - d->class = p[3]&0xFFF; - d->subclass = p[4]&0xFFF; - d->parent = (p[5]>>12)&0xFFF; + + d->lct_data = &lct->lct_entry[i]; + d->flags = 0; + tid = d->lct_data->tid; printk(KERN_INFO "TID %d.\n", tid); @@ -897,19 +976,19 @@ static int i2o_parse_lct(struct i2o_controller *c) printk(KERN_INFO " Class: "); - sprintf(str, "%-21s", i2o_get_class_name(d->class)); + sprintf(str, "%-21s", i2o_get_class_name(d->lct_data->class_id)); printk("%s", str); printk(" Subclass: 0x%03X Flags: ", - d->subclass); + d->lct_data->sub_class); - if(p[2]&(1<<0)) + if(d->lct_data->device_flags&(1<<0)) printk("C"); // ConfigDialog requested - if(p[2]&(1<<1)) + if(d->lct_data->device_flags&(1<<1)) printk("M"); // Multi-user capable - if(!(p[2]&(1<<4))) + if(!(d->lct_data->device_flags&(1<<4))) printk("P"); // Peer service enabled! - if(!(p[2]&(1<<5))) + if(!(d->lct_data->device_flags&(1<<5))) printk("m"); // Mgmt service enabled! printk("\n"); p+=9; @@ -917,30 +996,120 @@ static int i2o_parse_lct(struct i2o_controller *c) return 0; } + /* Quiesce IOP */ int i2o_quiesce_controller(struct i2o_controller *c) { u32 msg[4]; + if(c->status_block->iop_state != ADAPTER_STATE_OPERATIONAL) + return -EINVAL; + msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; msg[1]=I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID; - msg[2]=core_context; + msg[2]=(u32)core_context; msg[3]=(u32)&reply_flag; /* Long timeout needed for quiesce if lots of devices */ - return i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &reply_flag, 120); +#ifdef DRIVERDEBUG + printk(KERN_INFO "Posting quiesce message to iop%d\n", c->unit); +#endif + if(i2o_post_wait(c, msg, sizeof(msg), 120)) + return -1; + else + return 0; +} + +/* Enable IOP */ +int i2o_enable_controller(struct i2o_controller *c) +{ + u32 msg[4]; + + msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; + msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID; + msg[2]=core_context; + msg[3]=(u32)&reply_flag; + + /* How long of a timeout do we need? */ + return i2o_post_wait(c, msg, sizeof(msg), 240); +} + +/* + * Quiesce _all_ IOPs in OP state. + * Used during init/shutdown time. + */ +int i2o_quiesce_system(void) +{ + struct i2o_controller *iop; + int ret = 0; + + for(iop=i2o_controller_chain; iop != NULL; iop=iop->next) + { + /* + * Quiesce only needed on operational IOPs + */ + i2o_status_get(iop); + + if(iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL) + { +#ifdef DRIVERDEBUG + printk(KERN_INFO "Attempting to quiesce iop%d\n", iop->unit); +#endif + if(i2o_quiesce_controller(iop)) + { + printk(KERN_INFO "Unable to quiesce iop%d\n", iop->unit); + ret = -ENXIO; + } +#ifdef DRIVERDEBUG + else + printk(KERN_INFO "%s quiesced\n", iop->name); +#endif + + i2o_status_get(iop); // Update IOP state information + } + } + + return ret; +} + +/* + * (re)Enable _all_ IOPs in READY state. + */ +int i2o_enable_system(void) +{ + struct i2o_controller *iop; + int ret = 0; + + for(iop=i2o_controller_chain; iop != NULL; iop=iop->next) + { + /* + * Enable only valid for IOPs in READY state + */ + i2o_status_get(iop); + + if(iop->status_block->iop_state == ADAPTER_STATE_READY) + { + if(i2o_enable_controller(iop)<0) + printk(KERN_INFO "Unable to (re)enable iop%d\n", + iop->unit); + + i2o_status_get(iop); // Update IOP state information + } + } + + return ret; } +/* Reset an IOP, but keep message queues alive */ int i2o_clear_controller(struct i2o_controller *c) { u32 msg[4]; + int ret; - /* First stop external operations for this IOP */ - if(i2o_quiesce_controller(c)<0) - printk(KERN_INFO "Unable to quiesce iop%d\n", c->unit); - else - printk(KERN_INFO "Iop%d quiesced\n", c->unit); +#ifdef DRIVERDEBUG + printk(KERN_INFO "Clearing iop%d\n", c->unit); +#endif /* Then clear the IOP */ msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; @@ -948,7 +1117,14 @@ int i2o_clear_controller(struct i2o_controller *c) msg[2]=core_context; msg[3]=(u32)&reply_flag; - return i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &reply_flag, 10); + if((ret=i2o_post_wait(c, msg, sizeof(msg), 30))) + printk(KERN_INFO "ExecIopClear failed: %#10x\n", ret); +#ifdef DRIVERDEBUG + else + printk(KERN_INFO "ExecIopClear success!\n"); +#endif + + return ret; } @@ -959,27 +1135,15 @@ static int i2o_reset_controller(struct i2o_controller *c) u8 *work8; u32 *msg; long time; - struct i2o_controller *iop; - /* First stop external operations */ - for(iop=i2o_controller_chain; iop != NULL; iop=iop->next) - { - /* Quiesce is rejected on hold state */ - if(iop->status != ADAPTER_STATE_HOLD) - { - if(i2o_quiesce_controller(iop)<0) - printk(KERN_INFO "Unable to quiesce iop%d\n", - iop->unit); - else - printk(KERN_DEBUG "%s quiesced\n", iop->name); - } - } +#ifdef DRIVERDEBUG + printk(KERN_INFO "Reseting iop%d\n", c->unit); +#endif - /* Then reset the IOP */ + /* Get a message */ m=i2o_wait_message(c, "AdapterReset"); - if(m==0xFFFFFFFF) + if(m==0xFFFFFFFF) return -ETIMEDOUT; - msg=(u32 *)(c->mem_offset+m); work8=(void *)kmalloc(4, GFP_KERNEL); @@ -999,12 +1163,16 @@ static int i2o_reset_controller(struct i2o_controller *c) msg[6]=virt_to_phys(work8); msg[7]=0; /* 64bit host FIXME */ + /* Then reset the IOP */ i2o_post_message(c,m); /* Wait for a reply */ time=jiffies; - while(work8[0]==0x01) +#ifdef DRIVERDEBUG + printk(KERN_INFO "Reset posted, waiting...\n"); +#endif + while(work8[0]==0) { if((jiffies-time)>=5*HZ) { @@ -1016,8 +1184,41 @@ static int i2o_reset_controller(struct i2o_controller *c) barrier(); } - if (work8[0]==0x02) - printk(KERN_WARNING "IOP Reset rejected\n"); + if (work8[0]==0x02) + { + printk(KERN_WARNING "IOP Reset rejected\n"); + } + else + { + /* + * Once the reset is sent, the IOP goes into the INIT state + * which is inditerminate. We need to wait until the IOP + * has rebooted before we can let the system talk to + * it. We read the inbound Free_List until a message is + * available. If we can't read one in the given ammount of + * time, we assume the IOP could not reboot properly. + */ +#ifdef DRIVERDEBUG + printk(KERN_INFO "Reset succeeded...waiting for reboot\n"); +#endif + time = jiffies; + m = I2O_POST_READ32(c); + while(m == 0XFFFFFFFF) + { + if((jiffies-time) >= 30*HZ) + { + printk(KERN_ERR "i2o/iop%d: Timeout waiting for IOP reset.\n", + c->unit); + return -ETIMEDOUT; + } + schedule(); + barrier(); + m = I2O_POST_READ32(c); + } +#ifdef DRIVERDEBUG + printk(KERN_INFO "Reboot completed\n"); +#endif + } return 0; } @@ -1030,13 +1231,24 @@ int i2o_status_get(struct i2o_controller *c) u32 *msg; u8 *status_block; - status_block=(void *)kmalloc(88, GFP_KERNEL); - if(status_block==NULL) +#ifdef DRIVERDEBUG + printk(KERN_INFO "Getting status block for iop%d\n", c->unit); +#endif + if(c->status_block) + kfree(c->status_block); + + c->status_block = + (pi2o_status_block)kmalloc(sizeof(i2o_status_block),GFP_KERNEL); + if(c->status_block == NULL) { - printk(KERN_ERR "StatusGet failed - no free memory.\n"); +#ifdef DRIVERDEBUG + printk(KERN_ERR "No memory in status get!\n"); +#endif return -ENOMEM; } + status_block = (u8*)c->status_block; + m=i2o_wait_message(c, "StatusGet"); if(m==0xFFFFFFFF) return -ETIMEDOUT; @@ -1049,7 +1261,7 @@ int i2o_status_get(struct i2o_controller *c) msg[3]=0; msg[4]=0; msg[5]=0; - msg[6]=virt_to_phys(status_block); + msg[6]=virt_to_phys(c->status_block); msg[7]=0; /* 64bit host FIXME */ msg[8]=88; @@ -1062,7 +1274,9 @@ int i2o_status_get(struct i2o_controller *c) { if((jiffies-time)>=5*HZ) { +#ifdef DRIVERDEBUG printk(KERN_ERR "IOP get status timeout.\n"); +#endif return -ETIMEDOUT; } schedule(); @@ -1070,8 +1284,6 @@ int i2o_status_get(struct i2o_controller *c) } /* Ok the reply has arrived. Fill in the important stuff */ - c->status = status_block[10]; - c->i2oversion = (status_block[9]>>4)&0xFF; c->inbound_size = (status_block[12]|(status_block[13]<<8))*4; return 0; @@ -1080,8 +1292,10 @@ int i2o_status_get(struct i2o_controller *c) int i2o_hrt_get(struct i2o_controller *c) { - u32 m; - u32 *msg; + u32 msg[6]; + + if(c->hrt) + kfree(c->hrt); c->hrt=kmalloc(2048, GFP_KERNEL); if(c->hrt==NULL) @@ -1090,12 +1304,6 @@ int i2o_hrt_get(struct i2o_controller *c) return -ENOMEM; } - m=i2o_wait_message(c, "HRTGet"); - if(m==0xFFFFFFFF) - return -ETIMEDOUT; - - msg=(u32 *)(c->mem_offset+m); - msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4; msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID; msg[2]= core_context; @@ -1103,134 +1311,271 @@ int i2o_hrt_get(struct i2o_controller *c) msg[4]= (0xD0000000 | 2048); /* Simple transaction , 2K */ msg[5]= virt_to_phys(c->hrt); /* Dump it here */ - i2o_post_message(c,m); - - barrier(); - - /* Now wait for a reply */ - m=i2o_wait_reply(c, "HRTGet", 5); + return i2o_post_wait(c, msg, sizeof(msg), 20); +} - if(m==0xFFFFFFFF) - return -ETIMEDOUT; +static int i2o_systab_send(struct i2o_controller* iop) +{ + u32 msg[10]; + u32 privmem[2]; + u32 privio[2]; + int ret; - msg=(u32 *)bus_to_virt(m); + privmem[0]=iop->priv_mem; /* Private memory space base address */ + privmem[1]=iop->priv_mem_size; + privio[0]=iop->priv_io; /* Private I/O address */ + privio[1]=iop->priv_io_size; - if(msg[4]>>24) - i2o_report_status(KERN_WARNING, "i2o_core", msg); + msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_6; + msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID; + msg[2] = 0; /* Context not needed */ + msg[3] = 0; + msg[4] = (0<<16)|((iop->unit+2)<<12); /* Host 0 IOP ID (unit + 2) */ + msg[5] = 0; /* Segment 0 */ + + /* + * Scatter Gather List + */ + msg[6] = 0x54000000|sys_tbl_len; + msg[7] = virt_to_phys(sys_tbl); + msg[8] = 0xD4000000|48; /* One table for now */ + msg[9] = virt_to_phys(privmem); +/* msg[10] = virt_to_phys(privio); */ - I2O_REPLY_WRITE32(c,m); + ret=i2o_post_wait(iop, msg, sizeof(msg), 120); + if(ret) + return ret; return 0; } - /* - * Bring an I2O controller into HOLD state. See the 1.5 - * spec. Basically we go - * - * Wait for the message queue to initialise. - * If it didnt -> controller is dead - * - * Send a get status using the message queue - * Poll for a reply block 88 bytes long - * - * Send an initialise outbound queue - * Poll for a reply - * - * Post our blank messages to the queue FIFO - * - * Send GetHRT, Parse it + * Initialize I2O subsystem. */ - -int i2o_activate_controller(struct i2o_controller *c) +static void __init i2o_sys_init() { - long time; - u32 m; - u8 *workspace; - u32 *msg; - int i; + struct i2o_controller *iop; int ret; + u32 m; - printk(KERN_INFO "Configuring I2O controller at 0x%08X.\n", - (u32)c->mem_phys); - - if((ret=i2o_status_get(c))) - return ret; + printk(KERN_INFO "Activating I2O controllers\n"); + printk(KERN_INFO "This may take a few minutes if there are many devices\n"); - if(c->status == ADAPTER_STATE_FAULTED) /* not likely to be seen */ + /* Get the status for each IOP */ + for(iop = i2o_controller_chain; iop; iop = iop->next) { - printk(KERN_CRIT "i2o: iop%d has hardware fault\n", - c->unit); - return -1; +#ifdef DRIVERDEBUG + printk(KERN_INFO "Getting initial status for iop%d\n", iop->unit); +#endif + i2o_status_get(iop); + + if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED) + { + printk(KERN_CRIT "i2o: iop%d has hardware fault\n", + iop->unit); + i2o_delete_controller(iop); + } + + if(iop->status_block->iop_state == ADAPTER_STATE_HOLD || + iop->status_block->iop_state == ADAPTER_STATE_READY || + iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL || + iop->status_block->iop_state == ADAPTER_STATE_FAILED) + { + int msg[256]; + +#ifdef DRIVERDEBUG + printk(KERN_INFO "iop%d already running...trying to reboot", + iop->unit); +#endif + i2o_init_outbound_q(iop); + I2O_REPLY_WRITE32(iop,virt_to_phys(msg)); + i2o_quiesce_controller(iop); + i2o_reset_controller(iop); + i2o_status_get(iop); + } } /* - * If the board is running, reset it - we have no idea - * what kind of a mess the previous owner left it in. + * Now init the outbound queue for each one. */ - if(c->status == ADAPTER_STATE_HOLD || - c->status == ADAPTER_STATE_READY || - c->status == ADAPTER_STATE_OPERATIONAL || - c->status == ADAPTER_STATE_FAILED) + for(iop = i2o_controller_chain; iop; iop = iop->next) { - if((ret=i2o_reset_controller(c))) - return ret; + int i; - if((ret=i2o_status_get(c))) - return ret; - } + if((ret=i2o_init_outbound_q(iop))) + { + printk(KERN_ERR + "IOP%d initialization failed: Could not initialize outbound q\n", + iop->unit); + i2o_delete_controller(iop); + } + iop->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL); - workspace = (void *)kmalloc(88, GFP_KERNEL); - if(workspace==NULL) - { - printk(KERN_ERR "IOP initialisation failed - no free memory.\n"); - return -ENOMEM; + if(iop->page_frame==NULL) + { + printk(KERN_ERR "IOP init failed: no memory for message page.\n"); + i2o_delete_controller(iop); + continue; + } + + m=virt_to_phys(iop->page_frame); + + for(i=0; i< NMBR_MSG_FRAMES; i++) + { + I2O_REPLY_WRITE32(iop,m); + mb(); + m+=MSG_FRAME_SIZE; + mb(); + } } - memset(workspace, 0, 88); - - m=i2o_wait_message(c, "OutboundInit"); - if(m==0xFFFFFFFF) - { - kfree(workspace); - return -ETIMEDOUT; + /* + * OK..parse the HRT + */ + for(iop = i2o_controller_chain; iop; iop = iop->next) + { + if(i2o_hrt_get(iop)) + { + i2o_delete_controller(iop); + break; + } + if(i2o_parse_hrt(iop)) + i2o_delete_controller(iop); } - msg=(u32 *)(c->mem_offset+m); - - msg[0]= EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6; - msg[1]= I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID; - msg[2]= core_context; - msg[3]= 0x0106; /* Transaction context */ - msg[4]= 4096; /* Host page frame size */ - msg[5]= MSG_FRAME_SIZE<<16|0x80; /* Outbound msg frame size and Initcode */ - msg[6]= 0xD0000004; /* Simple SG LE, EOB */ - msg[7]= virt_to_phys(workspace); - *((u32 *)workspace)=0; + /* + * Build and send the system table + */ + i2o_build_sys_table(); + for(iop = i2o_controller_chain; iop; iop = iop->next) +#ifdef DRIVERDEBUG + { + printk(KERN_INFO "Sending system table to iop%d\n", iop->unit); +#endif + i2o_systab_send(iop); +#ifdef DRIVERDEBUG + } +#endif /* - * Post it + * Enable */ + for(iop = i2o_controller_chain; iop; iop = iop->next) + { +#ifdef DRIVERDEBUG + printk(KERN_INFO "Enableing iop%d\n", iop->unit); +#endif + if(i2o_enable_controller(iop)) + { + printk(KERN_ERR "Could not enable iop%d\n", iop->unit); + i2o_delete_controller(iop); + } + } - i2o_post_message(c,m); - - barrier(); - - time=jiffies; - - while(workspace[0]!=I2O_CMD_OUTBOUND_INIT_COMPLETE) + /* + * OK..one last thing and we're ready to go! + */ + for(iop = i2o_controller_chain; iop; iop = iop->next) { - if((jiffies-time)>=5*HZ) +#ifdef DRIVERDEBUG + printk(KERN_INFO "Getting LCT for iop%d\n", iop->unit); +#endif + if(i2o_lct_get(iop)) { - printk(KERN_ERR "IOP outbound initialise failed.\n"); - kfree(workspace); - return -ETIMEDOUT; + printk(KERN_ERR "Could not get LCT from iop%d\n", iop->unit); + i2o_delete_controller(iop); } - schedule(); - barrier(); + else + i2o_parse_lct(iop); + } +} + +/* + * Shutdown I2O system + * + * 1. Quiesce all controllers + * 2. Delete all controllers + * + */ +static void i2o_sys_shutdown(void) +{ + struct i2o_controller *iop = NULL; + + i2o_quiesce_system(); + for(iop = i2o_controller_chain; iop; iop = iop->next) + i2o_delete_controller(iop); +} + +/* + * Bring an I2O controller into HOLD state. See the 1.5 + * spec. Basically we go + * + * Wait for the message queue to initialise. + * If it didnt -> controller is dead + * + * Send a get status using the message queue + * Poll for a reply block 88 bytes long + * + * Send an initialise outbound queue + * Poll for a reply + * + * Post our blank messages to the queue FIFO + * + * Send GetHRT, Parse it + */ +int i2o_activate_controller(struct i2o_controller *c) +{ + return 0; +#ifdef I2O_HOTPLUG_SUPPORT + u32 m; + int i; + int ret; + + printk(KERN_INFO "Configuring I2O controller at 0x%08X.\n", + (u32)c->mem_phys); + + if((ret=i2o_status_get(c))) + return ret; + + /* not likely to be seen */ + if(c->status_block->iop_state == ADAPTER_STATE_FAULTED) + { + printk(KERN_CRIT "i2o: iop%d has hardware fault\n", + c->unit); + return -1; } - kfree(workspace); + /* + * If the board is running, reset it - we have no idea + * what kind of a mess the previous owner left it in. + * We need to feed the IOP a single outbound message + * so that it can reply back to the ExecSysQuiesce. + */ + if(c->status_block->iop_state == ADAPTER_STATE_HOLD || + c->status_block->iop_state == ADAPTER_STATE_READY || + c->status_block->iop_state == ADAPTER_STATE_OPERATIONAL || + c->status_block->iop_state == ADAPTER_STATE_FAILED) + { + int msg[256]; + printk(KERN_INFO "i2o/iop%d already running, reseting\n", c->unit); + + if(i2o_init_outbound_q(c)); + I2O_REPLY_WRITE32(c,virt_to_phys(msg)); + + if((ret=i2o_reset_controller(c))) + return ret; + + if((ret=i2o_status_get(c))) + return ret; + } + + if((ret=i2o_init_outbound_q(c))) + { + printk(KERN_ERR + "IOP%d initialization failed: Could not initialize outbound queue\n", + c->unit); + return ret; + } /* TODO: v2.0: Set Executive class group 000Bh - OS Operating Info */ @@ -1248,46 +1593,101 @@ int i2o_activate_controller(struct i2o_controller *c) I2O_REPLY_WRITE32(c,m); mb(); m+=MSG_FRAME_SIZE; + mb(); } - /* - * The outbound queue is initialised and loaded, - * - * Now we need the Hardware Resource Table. We must ask for - * this next we can't issue random messages yet. - */ - ret=i2o_hrt_get(c); - if(ret) - return ret; + /* + * The outbound queue is initialised and loaded, + * + * Now we need the Hardware Resource Table. We must ask for + * this next we can't issue random messages yet. + */ + ret=i2o_hrt_get(c); if(ret) return ret; ret=i2o_parse_hrt(c); if(ret) return ret; return i2o_online_controller(c); -// i2o_report_controller_unit(c, ADAPTER_TID); +#endif } - -int i2o_lct_get(struct i2o_controller *c) +/* + * Clear and (re)initialize IOP's outbound queue + */ +int i2o_init_outbound_q(struct i2o_controller *c) { + u8 workspace[88]; u32 m; u32 *msg; + u32 time; - m=i2o_wait_message(c, "LCTNotify"); + memset(workspace, 0, 88); + printk(KERN_INFO "i2o/iop%d: Initializing Outbound Queue\n", c->unit); + m=i2o_wait_message(c, "OutboundInit"); if(m==0xFFFFFFFF) + { + kfree(workspace); return -ETIMEDOUT; + } msg=(u32 *)(c->mem_offset+m); + msg[0]= EIGHT_WORD_MSG_SIZE| TRL_OFFSET_6; + msg[1]= I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID; + msg[2]= core_context; + msg[3]= 0x0106; /* Transaction context */ + msg[4]= 4096; /* Host page frame size */ + msg[5]= MSG_FRAME_SIZE<<16|0x80; /* Outbound msg frame size and Initcode */ + msg[6]= 0xD0000004; /* Simple SG LE, EOB */ + msg[7]= virt_to_phys(workspace); + *((u32 *)workspace)=0; + + /* + * Post it + */ + i2o_post_message(c,m); + + barrier(); + + time=jiffies; + + while(workspace[0]!=I2O_CMD_OUTBOUND_INIT_COMPLETE) + { + if((jiffies-time)>=5*HZ) + { + printk(KERN_ERR "i2o/iop%d: IOP outbound initialise failed.\n", + c->unit); + kfree(workspace); + return -ETIMEDOUT; + } + schedule(); + barrier(); + } + + return 0; +} + +/* + * Get the IOP's Logical Configuration Table + */ +int i2o_lct_get(struct i2o_controller *c) +{ + u32 msg[8]; + +#ifdef DRIVERDEBUG + printk(KERN_INFO "Getting lct for iop%d\n", c->unit); +#endif + + if(c->lct) + kfree(c->lct); + c->lct = kmalloc(8192, GFP_KERNEL); if(c->lct==NULL) { - msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1]= HOST_TID<<12|ADAPTER_TID; /* NOP */ - i2o_post_message(c,m); - printk(KERN_ERR "No free memory for i2o controller buffer.\n"); + printk(KERN_ERR "i2o/iop%d: No free memory for i2o controller buffer.\n", + c->unit); return -ENOMEM; } @@ -1302,25 +1702,8 @@ int i2o_lct_get(struct i2o_controller *c) msg[6] = 0xD0000000|8192; msg[7] = virt_to_bus(c->lct); - i2o_post_message(c,m); - - barrier(); - - /* Now wait for a reply */ - m=i2o_wait_reply(c, "LCTNotify", 5); - - if(m==0xFFFFFFFF) - return -ETIMEDOUT; - - msg=(u32 *)bus_to_virt(m); - - /* TODO: Check TableSize for big LCTs and send new ExecLctNotify - * with bigger workspace */ - - if(msg[4]>>24) - i2o_report_status(KERN_ERR, "i2o_core", msg); - - return 0; + + return(i2o_post_wait(c, msg, sizeof(msg), 120)); } @@ -1330,13 +1713,14 @@ int i2o_lct_get(struct i2o_controller *c) int i2o_online_controller(struct i2o_controller *c) { - u32 m; - u32 *msg; - u32 systab[32]; + return 0; +#ifdef I2O_HOTPLUG_SUPPORT + u32 msg[10]; u32 privmem[2]; u32 privio[2]; + u32 systab[32]; int ret; - + systab[0]=1; systab[1]=0; systab[2]=0; @@ -1350,103 +1734,45 @@ int i2o_online_controller(struct i2o_controller *c) systab[10]=virt_to_phys(c->post_port); systab[11]=0; + i2o_build_sys_table(); + privmem[0]=c->priv_mem; /* Private memory space base address */ privmem[1]=c->priv_mem_size; privio[0]=c->priv_io; /* Private I/O address */ privio[1]=c->priv_io_size; - - m=i2o_wait_message(c, "SysTabSet"); - if(m==0xFFFFFFFF) - return -ETIMEDOUT; - - /* Now we build the systab */ - msg=(u32 *)(c->mem_offset+m); - + msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_6; msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID; msg[2] = 0; /* Context not needed */ msg[3] = 0; - msg[4] = (1<<16)|(2<<12); /* Host 1 I2O 2 */ - msg[5] = 1; /* Segment 1 */ + msg[4] = (0<<16)|(2<<12); /* Host 1 I2O 2 */ + msg[5] = 0; /* Segment 1 */ /* * Scatter Gather List */ - - msg[6] = 0x54000000|48; /* One table for now */ - msg[7] = virt_to_phys(systab); + msg[6] = 0x54000000|sys_tbl_len; /* One table for now */ + msg[7] = virt_to_phys(sys_tbl); msg[8] = 0xD4000000|48; /* One table for now */ msg[9] = virt_to_phys(privmem); -/* msg[10] = virt_to_phys(privio); */ - - i2o_post_message(c,m); +/* msg[10] = virt_to_phys(privio); */ - barrier(); - - /* - * Now wait for a reply - */ - - - m=i2o_wait_reply(c, "SysTabSet", 5); - - if(m==0xFFFFFFFF) - return -ETIMEDOUT; - - msg=(u32 *)bus_to_virt(m); - - if(msg[4]>>24) - { - i2o_report_status(KERN_ERR, "i2o_core", msg); - } - I2O_REPLY_WRITE32(c,m); + return(i2o_post_wait(c, msg, sizeof(msg), 120)); /* * Finally we go online */ - - m=i2o_wait_message(c, "SysEnable"); - - if(m==0xFFFFFFFF) - return -ETIMEDOUT; - - msg=(u32 *)(c->mem_offset+m); - - msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1] = I2O_CMD_SYS_ENABLE<<24 | HOST_TID<<12 | ADAPTER_TID; - msg[2] = 0; /* Context not needed */ - msg[3] = 0; - - i2o_post_message(c,m); - - barrier(); - - /* - * Now wait for a reply - */ - - - m=i2o_wait_reply(c, "SysEnable", 240); - - if(m==0xFFFFFFFF) - return -ETIMEDOUT; - - msg=(u32 *)bus_to_virt(m); - - if(msg[4]>>24) - { - i2o_report_status(KERN_ERR, "i2o_core", msg); - } - I2O_REPLY_WRITE32(c,m); + ret = i2o_enable_controller(c); + if(ret) + return ret; /* * Grab the LCT, see what is attached */ - ret=i2o_lct_get(c); if(ret) { - /* Maybe we should do also sthg else */ + /* Maybe we should do also do something else */ return ret; } @@ -1454,11 +1780,73 @@ int i2o_online_controller(struct i2o_controller *c) if(ret) return ret; - I2O_REPLY_WRITE32(c,m); - + return 0; +#endif +} + +static int i2o_build_sys_table(void) +{ + struct i2o_controller *iop = NULL; + int count = 0; +#ifdef DRIVERDEBUG + u32 *table; +#endif + + sys_tbl_len = sizeof(struct i2o_sys_tbl) + // Header + IOPs + (i2o_num_controllers) * + sizeof(struct i2o_sys_tbl_entry); + +#ifdef DRIVERDEBUG + printk(KERN_INFO "Building system table len = %d\n", sys_tbl_len); +#endif + if(sys_tbl) + kfree(sys_tbl); + + sys_tbl = kmalloc(sys_tbl_len, GFP_KERNEL); + if(!sys_tbl) + return -ENOMEM; + memset((void*)sys_tbl, 0, sys_tbl_len); + + sys_tbl->num_entries = i2o_num_controllers; + sys_tbl->version = I2OVERSION; /* TODO: Version 2.0 */ + sys_tbl->change_ind = sys_tbl_ind++; + + for(iop = i2o_controller_chain; iop; iop = iop->next) + { + // Get updated IOP state so we have the latest information + i2o_status_get(iop); + + sys_tbl->iops[count].org_id = iop->status_block->org_id; + sys_tbl->iops[count].iop_id = iop->unit + 2; + sys_tbl->iops[count].seg_num = 0; + sys_tbl->iops[count].i2o_version = + iop->status_block->i2o_version; + sys_tbl->iops[count].iop_state = + iop->status_block->iop_state; + sys_tbl->iops[count].msg_type = + iop->status_block->msg_type; + sys_tbl->iops[count].frame_size = + iop->status_block->inbound_frame_size; + sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ?? + sys_tbl->iops[count].iop_capabilities = + iop->status_block->iop_capabilities; + sys_tbl->iops[count].inbound_low = + (u32)virt_to_phys(iop->post_port); + sys_tbl->iops[count].inbound_high = 0; // TODO: 64-bit support + + count++; + } + +#ifdef DRIVERDEBUG + table = (u32*)sys_tbl; + for(count = 0; count < (sys_tbl_len >>2); count++) + printk(KERN_INFO "sys_tbl[%d] = %0#10x\n", count, table[count]); +#endif + return 0; } + /* * Run time support routines */ @@ -1469,11 +1857,11 @@ int i2o_online_controller(struct i2o_controller *c) * this is simply not worth optimising */ -int i2o_post_this(struct i2o_controller *c, int tid, u32 *data, int len) +int i2o_post_this(struct i2o_controller *c, u32 *data, int len) { u32 m; u32 *msg; - unsigned long t=jiffies; + unsigned long t=jiffies; do { @@ -1485,8 +1873,9 @@ int i2o_post_this(struct i2o_controller *c, int tid, u32 *data, int len) if(m==0xFFFFFFFF) { - printk(KERN_ERR "i2o: controller not responding.\n"); - return -1; + printk(KERN_ERR "i2o/iop%d: Timeout waiting for message frame!\n", + c->unit); + return -ETIMEDOUT; } msg = bus_to_virt(c->mem_offset + m); memcpy(msg, data, len); @@ -1495,32 +1884,114 @@ int i2o_post_this(struct i2o_controller *c, int tid, u32 *data, int len) } /* - * Post a message and wait for a response flag to be set. This API will - * change to use wait_queue's one day + * Post a message and wait for a response flag to be set. */ - -int i2o_post_wait(struct i2o_controller *c, int tid, u32 *data, int len, int *flag, int timeout) +int i2o_post_wait(struct i2o_controller *c, u32 *msg, int len, int timeout) { - unsigned long t=jiffies; + DECLARE_WAIT_QUEUE_HEAD(wq_i2o_post); + int status = 0; + int flags = 0; + int ret = 0; + struct i2o_post_wait_data *p1, *p2; + struct i2o_post_wait_data *wait_data = + kmalloc(sizeof(struct i2o_post_wait_data), GFP_KERNEL); + + if(!wait_data) + return -ETIMEDOUT; + + p1 = p2 = NULL; - *flag = 0; - - if(i2o_post_this(c, tid, data, len)) - return I2O_POST_WAIT_TIMEOUT; - - while(!*flag && (jiffies-t)next = post_wait_queue; + post_wait_queue = wait_data; + wait_data->id = ++post_wait_id; + spin_unlock_irqrestore(&post_wait_lock, flags); + + wait_data->wq = &wq_i2o_post; + wait_data->status = -ETIMEDOUT; + + msg[3] = (u32)wait_data->id; + msg[2] = 0x80000000|(u32)core_context; + + if((ret=i2o_post_this(c, msg, len))) + return ret; + /* + * Go to sleep and wait for timeout or wake_up call + */ + interruptible_sleep_on_timeout(&wq_i2o_post, HZ * timeout); + + /* + * Grab transaction status + */ + status = wait_data->status; + + /* + * Remove the entry from the queue. + * Since i2o_post_wait() may have been called again by + * a different thread while we were waiting for this + * instance to complete, we're not guaranteed that + * this entry is at the head of the queue anymore, so + * we need to search for it, find it, and delete it. + */ + spin_lock_irqsave(&post_wait_lock, flags); + for(p1 = post_wait_queue; p1; ) { - schedule(); - mb(); + if(p1 == wait_data) + { + if(p2) + p2->next = p1->next; + else + post_wait_queue = p1->next; + + break; + } + p1 = p1->next; } + spin_unlock_irqrestore(&post_wait_lock, flags); + + kfree(wait_data); - if (*flag < 0) - return *flag; /* DetailedStatus */ + return status; +} - if (*flag == 0) - return I2O_POST_WAIT_TIMEOUT; - - return I2O_POST_WAIT_OK; +/* + * i2o_post_wait is completed and we want to wake up the + * sleeping proccess. Called by core's reply handler. + */ +static void i2o_post_wait_complete(u32 context, int status) +{ + struct i2o_post_wait_data *p1 = NULL; + + /* + * We need to search through the post_wait + * queue to see if the given message is still + * outstanding. If not, it means that the IOP + * took longer to respond to the message than we + * had allowed and timer has already expired. + * Not much we can do about that except log + * it for debug purposes, increase timeout, and recompile + * + * Lock needed to keep anyone from moving queue pointers + * around while we're looking through them. + */ + spin_lock(&post_wait_lock); + for(p1 = post_wait_queue; p1; p1 = p1->next) + { + if(p1->id == context) + { + p1->status = status; + wake_up_interruptible(p1->wq); + spin_unlock(&post_wait_lock); + return; + } + } + spin_unlock(&post_wait_lock); + + printk(KERN_DEBUG "i2o_post_wait reply after timeout!"); } /* @@ -1543,7 +2014,7 @@ int i2o_issue_claim(struct i2o_controller *c, int tid, int context, int onoff, i msg[3] = (u32)flag; msg[4] = type; - return i2o_post_wait(c, tid, msg, 20, flag,2); + return i2o_post_wait(c, msg, 20, 2); } /* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET @@ -1554,60 +2025,56 @@ int i2o_issue_claim(struct i2o_controller *c, int tid, int context, int onoff, i * Note that the minimum sized resblk is 8 bytes and contains * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. */ -int i2o_issue_params(int cmd, - struct i2o_controller *iop, int tid, int context, - void *opblk, int oplen, void *resblk, int reslen, - int *flag) +int i2o_issue_params(int cmd, struct i2o_controller *iop, int tid, + void *opblk, int oplen, void *resblk, int reslen) { - u32 msg[9]; +u32 msg[9]; u8 *res = (u8 *)resblk; int res_count; int blk_size; int bytes; int wait_status; - msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5; - msg[1] = cmd << 24 | HOST_TID << 12 | tid; - msg[2] = context | 0x80000000; - msg[3] = (u32)flag; - msg[4] = 0; - msg[5] = 0x54000000 | oplen; /* OperationBlock */ - msg[6] = virt_to_bus(opblk); - msg[7] = 0xD0000000 | reslen; /* ResultBlock */ - msg[8] = virt_to_bus(resblk); - - wait_status = i2o_post_wait(iop, tid, msg, sizeof(msg), flag, 10); - if (wait_status < 0) - return wait_status; /* -DetailedStatus */ - - if (res[1]&0x00FF0000) /* BlockStatus != SUCCESS */ - { - printk(KERN_WARNING "%s - Error:\n ErrorInfoSize = 0x%02x, " - "BlockStatus = 0x%02x, BlockSize = 0x%04x\n", - (cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET" - : "PARAMS_GET", - res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF); - return -((res[1] >> 16) & 0xFF); /* -BlockStatus */ - } + msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5; + msg[1] = cmd << 24 | HOST_TID << 12 | tid; + msg[4] = 0; + msg[5] = 0x54000000 | oplen; /* OperationBlock */ + msg[6] = virt_to_bus(opblk); + msg[7] = 0xD0000000 | reslen; /* ResultBlock */ + msg[8] = virt_to_bus(resblk); - res_count = res[0] & 0xFFFF; /* # of resultblocks */ - bytes = 4; - res += 4; - while (res_count--) + wait_status = i2o_post_wait(iop, msg, sizeof(msg), 10); + if (wait_status) + return wait_status; /* -DetailedStatus */ + + if (res[1]&0x00FF0000) /* BlockStatus != SUCCESS */ + { + printk(KERN_WARNING "%s - Error:\n ErrorInfoSize = 0x%02x, " + "BlockStatus = 0x%02x, BlockSize = 0x%04x\n", + (cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET" + : "PARAMS_GET", + res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF); + return -((res[1] >> 16) & 0xFF); /* -BlockStatus */ + } + + res_count = res[0] & 0xFFFF; /* # of resultblocks */ + bytes = 4; + res += 4; + while (res_count--) { blk_size = (res[0] & 0xFFFF) << 2; bytes += blk_size; res += blk_size; } - - return bytes; /* total sizeof Result List in bytes */ + + return bytes; /* total sizeof Result List in bytes */ } /* * Query one scalar group value or a whole scalar group. */ -int i2o_query_scalar(struct i2o_controller *iop, int tid, int context, - int group, int field, void *buf, int buflen, int *flag) +int i2o_query_scalar(struct i2o_controller *iop, int tid, + int group, int field, void *buf, int buflen) { u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; u8 resblk[8+buflen]; /* 8 bytes for header */ @@ -1616,8 +2083,8 @@ int i2o_query_scalar(struct i2o_controller *iop, int tid, int context, if (field == -1) /* whole group */ opblk[4] = -1; - size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, iop, tid, context, - opblk, sizeof(opblk), resblk, sizeof(resblk), flag); + size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, iop, tid, + opblk, sizeof(opblk), resblk, sizeof(resblk)); if (size < 0) return size; @@ -1629,38 +2096,38 @@ int i2o_query_scalar(struct i2o_controller *iop, int tid, int context, /* * Set a scalar group value or a whole group. */ -int i2o_set_scalar(struct i2o_controller *iop, int tid, int context, - int group, int field, void *buf, int buflen, int *flag) +int i2o_set_scalar(struct i2o_controller *iop, int tid, + int group, int field, void *buf, int buflen) { u16 *opblk; u8 resblk[8+buflen]; /* 8 bytes for header */ int size; - opblk = kmalloc(buflen+64, GFP_KERNEL); - if (opblk == NULL) - { - printk(KERN_ERR "i2o: no memory for operation buffer.\n"); - return -ENOMEM; - } + opblk = kmalloc(buflen+64, GFP_KERNEL); + if (opblk == NULL) + { + printk(KERN_ERR "i2o: no memory for operation buffer.\n"); + return -ENOMEM; + } - opblk[0] = 1; /* operation count */ - opblk[1] = 0; /* pad */ - opblk[2] = I2O_PARAMS_FIELD_SET; - opblk[3] = group; + opblk[0] = 1; /* operation count */ + opblk[1] = 0; /* pad */ + opblk[2] = I2O_PARAMS_FIELD_SET; + opblk[3] = group; - if(field == -1) { /* whole group */ - opblk[4] = -1; - memcpy(opblk+5, buf, buflen); - } - else /* single field */ - { - opblk[4] = 1; - opblk[5] = field; - memcpy(opblk+6, buf, buflen); - } + if(field == -1) { /* whole group */ + opblk[4] = -1; + memcpy(opblk+5, buf, buflen); + } + else /* single field */ + { + opblk[4] = 1; + opblk[5] = field; + memcpy(opblk+6, buf, buflen); + } - size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context, - opblk, 12+buflen, resblk, sizeof(resblk), flag); + size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, + opblk, 12+buflen, resblk, sizeof(resblk)); kfree(opblk); return size; @@ -1687,10 +2154,9 @@ int i2o_set_scalar(struct i2o_controller *iop, int tid, int context, * * You could also use directly function i2o_issue_params(). */ -int i2o_query_table(int oper, - struct i2o_controller *iop, int tid, int context, int group, +int i2o_query_table(int oper, struct i2o_controller *iop, int tid, int group, int fieldcount, void *ibuf, int ibuflen, - void *resblk, int reslen, int *flag) + void *resblk, int reslen) { u16 *opblk; int size; @@ -1709,8 +2175,8 @@ int i2o_query_table(int oper, opblk[4] = fieldcount; memcpy(opblk+5, ibuf, ibuflen); /* other params */ - size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET,iop, tid, context, - opblk, 10+ibuflen, resblk, reslen, flag); + size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET,iop, tid, + opblk, 10+ibuflen, resblk, reslen); kfree(opblk); return size; @@ -1720,14 +2186,13 @@ int i2o_query_table(int oper, * Clear table group, i.e. delete all rows. */ -int i2o_clear_table(struct i2o_controller *iop, int tid, int context, - int group, int *flag) +int i2o_clear_table(struct i2o_controller *iop, int tid, int group) { u16 opblk[] = { 1, 0, I2O_PARAMS_TABLE_CLEAR, group }; u8 resblk[32]; /* min 8 bytes for result header */ - return i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context, - opblk, sizeof(opblk), resblk, sizeof(resblk), flag); + return i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, + opblk, sizeof(opblk), resblk, sizeof(resblk)); } /* @@ -1739,9 +2204,8 @@ int i2o_clear_table(struct i2o_controller *iop, int tid, int context, * buf contains fieldindexes, rowcount, keyvalues */ -int i2o_row_add_table(struct i2o_controller *iop, int tid, int context, - int group, int fieldcount, void *buf, int buflen, - int *flag) +int i2o_row_add_table(struct i2o_controller *iop, int tid, + int group, int fieldcount, void *buf, int buflen) { u16 *opblk; u8 resblk[32]; /* min 8 bytes for header */ @@ -1761,8 +2225,8 @@ int i2o_row_add_table(struct i2o_controller *iop, int tid, int context, opblk[4] = fieldcount; memcpy(opblk+5, buf, buflen); - size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context, - opblk, 10+buflen, resblk, sizeof(resblk), flag); + size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, + opblk, 10+buflen, resblk, sizeof(resblk)); kfree(opblk); return size; @@ -1772,9 +2236,8 @@ int i2o_row_add_table(struct i2o_controller *iop, int tid, int context, * Delete rows from a table group. */ -int i2o_row_delete_table(struct i2o_controller *iop, int tid, int context, - int group, int keycount, void *keys, int keyslen, - int *flag) +int i2o_row_delete_table(struct i2o_controller *iop, int tid, + int group, int keycount, void *keys, int keyslen) { u16 *opblk; u8 resblk[32]; /* min 8 bytes for header */ @@ -1794,8 +2257,8 @@ int i2o_row_delete_table(struct i2o_controller *iop, int tid, int context, opblk[4] = keycount; memcpy(opblk+5, keys, keyslen); - size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context, - opblk, 10+keyslen, resblk, sizeof(resblk), flag); + size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, + opblk, 10+keyslen, resblk, sizeof(resblk)); kfree(opblk); return size; @@ -2134,9 +2597,10 @@ static void i2o_dump_message(u32 *msg) #ifdef DRIVERDEBUG int i; - printk(KERN_INFO "Dumping I2O message @ %p\n", msg); + printk(KERN_INFO "Dumping I2O message size %d @ %p\n", + msg[0]>>16&0xffff, msg); for(i = 0; i < ((msg[0]>>16)&0xffff); i++) - printk(KERN_INFO "\tmsg[%d] = %#10x\n", i, msg[i]); + printk(KERN_INFO " msg[%d] = %0#10x\n", i, msg[i]); #endif } @@ -2181,27 +2645,35 @@ MODULE_DESCRIPTION("I2O Core"); int init_module(void) { + printk(KERN_INFO "I2O Core - (C) Copyright 1999 Red Hat Software\n"); if (i2o_install_handler(&i2o_core_handler) < 0) { - printk(KERN_ERR "i2o_core: Unable to install core handler.\n"); + printk(KERN_ERR + "i2o_core: Unable to install core handler.\nI2O stack not loaded!"); return 0; } core_context = i2o_core_handler.context; /* - * Attach core to I2O PCI subsystem + * Attach core to I2O PCI transport (and others as they are developed) */ #ifdef CONFIG_I2O_PCI_MODULE if(i2o_pci_core_attach(&i2o_core_functions) < 0) printk(KERN_INFO "No PCI I2O controllers found\n"); #endif + if(i2o_num_controllers) + i2o_sys_init(); + return 0; } void cleanup_module(void) { + if(i2o_num_controllers) + i2o_sys_shutdown(); + #ifdef CONFIG_I2O_PCI_MODULE i2o_pci_core_detach(); #endif @@ -2220,16 +2692,23 @@ extern int i2o_scsi_init(void); int __init i2o_init(void) { - if (i2o_install_handler(&i2o_core_handler) < 0) - { - printk(KERN_ERR "i2o_core: Unable to install core handler.\n"); - return 0; - } + printk(KERN_INFO "Loading I2O Core - (c) Copyright 1999 Red Hat Software\n"); + if (i2o_install_handler(&i2o_core_handler) < 0) + { + printk(KERN_ERR + "i2o_core: Unable to install core handler.\nI2O stack not loaded!"); + return 0; + } + + core_context = i2o_core_handler.context; - core_context = i2o_core_handler.context; #ifdef CONFIG_I2O_PCI i2o_pci_init(); #endif + + if(i2o_num_controllers) + i2o_init(); + i2o_config_init(); #ifdef CONFIG_I2O_BLOCK i2o_block_init(); diff --git a/drivers/i2o/i2o_lan.c b/drivers/i2o/i2o_lan.c index 087ee84bd..60798606a 100644 --- a/drivers/i2o/i2o_lan.c +++ b/drivers/i2o/i2o_lan.c @@ -302,7 +302,7 @@ static int i2o_lan_receive_post(struct net_device *dev, u32 count) : count - total; msg[0] = I2O_MESSAGE_SIZE(4 + 3 * bucket_count) | SGL_OFFSET_4; - msg[1] = LAN_RECEIVE_POST<<24 | HOST_TID<<12 | i2o_dev->id; + msg[1] = LAN_RECEIVE_POST<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid; msg[2] = priv->unit << 16 | lan_context; // InitiatorContext msg[3] = bucket_count; // BucketCount @@ -343,12 +343,12 @@ static int i2o_lan_reset(struct net_device *dev) u32 msg[5]; msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0; - msg[1] = LAN_RESET<<24 | HOST_TID<<12 | i2o_dev->id; + msg[1] = LAN_RESET<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid; msg[2] = priv->unit << 16 | lan_context; // InitiatorContext msg[3] = 0; // TransactionContext msg[4] = 1 << 16; // return posted buckets - if (i2o_post_this(iop, i2o_dev->id, msg, sizeof(msg)) < 0) + if (i2o_post_this(iop, msg, sizeof(msg)) < 0) return -ETIMEDOUT; return 0; @@ -368,12 +368,12 @@ static int i2o_lan_suspend(struct net_device *dev) dprintk( "%s: LAN SUSPEND MESSAGE\n", dev->name ); msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0; - msg[1] = LAN_SUSPEND<<24 | HOST_TID<<12 | i2o_dev->id; + msg[1] = LAN_SUSPEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid; msg[2] = priv->unit << 16 | lan_context; // InitiatorContext msg[3] = 0; // TransactionContext msg[4] = 1 << 16; // return posted buckets - if (i2o_post_this(iop, i2o_dev->id, msg, sizeof(msg)) < 0) + if (i2o_post_this(iop, msg, sizeof(msg))< 0) return -ETIMEDOUT; return 0; @@ -400,8 +400,7 @@ static void i2o_set_batch_mode(struct net_device *dev) // enable batch mode, toggle automatically val = 0x00000000; // val = 0x00000001; // turn off batch mode - if (i2o_set_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0003, 0, - &val, 4, &priv->reply_flag) <0) + if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0003, 0, &val, 4) < 0) printk(KERN_WARNING "Unable to enter I2O LAN batch mode.\n"); else dprintk(KERN_INFO "%s: I2O LAN batch mode enabled.\n",dev->name); @@ -414,8 +413,7 @@ static void i2o_set_batch_mode(struct net_device *dev) /* set LAN_OPERATION attributes */ val = dev->mtu + dev->hard_header_len; // PacketOrphanLimit - if (i2o_set_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0004, 2, - &val, 4, &priv->reply_flag) < 0) + if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0004, 2, &val, 4)) printk(KERN_WARNING "i2o_lan: Unable to set PacketOrphanLimit.\n"); else dprintk(KERN_INFO "%s: PacketOrphanLimit set to %d\n", @@ -438,7 +436,7 @@ static int i2o_lan_open(struct net_device *dev) printk(KERN_WARNING "%s: Unable to claim the I2O LAN device.\n", dev->name); return -EAGAIN; } - dprintk(KERN_INFO "%s: I2O LAN device claimed (tid=%d).\n", dev->name, i2o_dev->id); + dprintk(KERN_INFO "%s: I2O LAN device claimed (tid=%d).\n", dev->name, i2o_dev->lct_data->tid); i2o_lan_reset(dev); @@ -467,7 +465,7 @@ static int i2o_lan_close(struct net_device *dev) if(i2o_release_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY)) printk(KERN_WARNING "%s: Unable to unclaim I2O LAN device " - "(tid=%d)\n", dev->name, i2o_dev->id); + "(tid=%d)\n", dev->name, i2o_dev->lct_data->tid); MOD_DEC_USE_COUNT; @@ -521,7 +519,7 @@ static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev) msg = bus_to_virt(iop->mem_offset + m); msg[0] = SEVEN_WORD_MSG_SIZE | 1<<12 | SGL_OFFSET_4; - msg[1] = LAN_PACKET_SEND<<24 | HOST_TID<<12 | i2o_dev->id; + msg[1] = LAN_PACKET_SEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid; msg[2] = priv->unit << 16 | lan_context; // IntiatorContext msg[3] = 1 << 4; // TransmitControlWord @@ -554,8 +552,8 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev) u64 val64[16]; u64 supported_group[4] = { 0, 0, 0, 0 }; - if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0100, -1, - val64, sizeof(val64), &priv->reply_flag) < 0) + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0100, -1, + val64, sizeof(val64)) < 0) printk("%s: Unable to query LAN_HISTORICAL_STATS.\n",dev->name); else { dprintk("%s: LAN_HISTORICAL_STATS queried.\n",dev->name); @@ -568,13 +566,13 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev) priv->stats.rx_dropped = val64[6]; } - if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0180, -1, - &supported_group, sizeof(supported_group), &priv->reply_flag) < 0) + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0180, -1, + &supported_group, sizeof(supported_group)) < 0) printk("%s: Unable to query LAN_SUPPORTED_OPTIONAL_HISTORICAL_STATS.\n",dev->name); if (supported_group[2]) { - if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0183, -1, - val64, sizeof(val64), &priv->reply_flag) < 0) + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0183, -1, + val64, sizeof(val64) ) < 0) printk("%s: Unable to query LAN_OPTIONAL_RX_HISTORICAL_STATS.\n",dev->name); else { dprintk("%s: LAN_OPTIONAL_RX_HISTORICAL_STATS queried.\n",dev->name); @@ -584,12 +582,12 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev) } } - if (i2o_dev->subclass == I2O_LAN_ETHERNET) + if (i2o_dev->lct_data->sub_class == I2O_LAN_ETHERNET) { u64 supported_stats = 0; - if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0200, -1, - val64, sizeof(val64), &priv->reply_flag) < 0) + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0200, -1, + val64, sizeof(val64)) < 0) printk("%s: Unable to query LAN_802_3_HISTORICAL_STATS.\n",dev->name); else { dprintk("%s: LAN_802_3_HISTORICAL_STATS queried.\n",dev->name); @@ -598,13 +596,13 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev) priv->stats.tx_carrier_errors = val64[6]; } - if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0280, -1, - &supported_stats, 8, &priv->reply_flag) < 0) + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0280, -1, + &supported_stats, 8) < 0) printk("%s: Unable to query LAN_SUPPORTED_802_3_HISTORICAL_STATS\n", dev->name); if (supported_stats != 0) { - if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0281, -1, - val64, sizeof(val64), &priv->reply_flag) < 0) + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0281, -1, + val64, sizeof(val64)) < 0) printk("%s: Unable to query LAN_OPTIONAL_802_3_HISTORICAL_STATS.\n",dev->name); else { dprintk("%s: LAN_OPTIONAL_802_3_HISTORICAL_STATS queried.\n",dev->name); @@ -618,10 +616,10 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev) } #ifdef CONFIG_TR - if (i2o_dev->subclass == I2O_LAN_TR) + if (i2o_dev->lct_data->sub_class == I2O_LAN_TR) { - if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0300, -1, - val64, sizeof(val64), &priv->reply_flag) < 0) + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0300, -1, + val64, sizeof(val64)) < 0) printk("%s: Unable to query LAN_802_5_HISTORICAL_STATS.\n",dev->name); else { struct tr_statistics *stats = @@ -644,10 +642,10 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev) #endif #ifdef CONFIG_FDDI - if (i2o_dev->subclass == I2O_LAN_FDDI) + if (i2o_dev->lct_data->sub_class == I2O_LAN_FDDI) { - if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0400, -1, - val64, sizeof(val64), &priv->reply_flag) < 0) + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0400, -1, + val64, sizeof(val64)) < 0) printk("%s: Unable to query LAN_FDDI_HISTORICAL_STATS.\n",dev->name); else { // dprintk("%s: LAN_FDDI_HISTORICAL_STATS queried.\n",dev->name); @@ -691,8 +689,8 @@ return; * *because its trying to sleep in an irq - this must be async - Alan */ - if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0001, -1, - &work32, sizeof(work32), &priv->reply_flag) < 0 ) + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0001, -1, + &work32, sizeof(work32)) < 0) { printk(KERN_WARNING "i2o_lan: Unable to query " " LAN_MAC_ADDRESS table.\n"); @@ -734,12 +732,11 @@ return; mclist = mclist->next; } - if (i2o_clear_table(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0002, - &priv->reply_flag) < 0 ) + if (i2o_clear_table(iop, i2o_dev->lct_data->tid, 0x0002) < 0) dprintk("%s: Unable to clear LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name); - if (i2o_row_add_table(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0002, -1, - work32, dev->mc_count*8, &priv->reply_flag) < 0) + if (i2o_row_add_table(iop, i2o_dev->lct_data->tid, 0x0002, -1, + work32, dev->mc_count*8) < 0) dprintk("%s: Unable to set LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name); } @@ -748,8 +745,8 @@ return; dprintk(KERN_INFO "i2o_lan: Enabling unicast mode...\n"); } - if (i2o_set_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0001, 3, - &filter_mask, 4, &priv->reply_flag) <0) + if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0001, 3, + &filter_mask, 4) < 0) printk(KERN_WARNING "i2o_lan: Unable to set MAC FilterMask.\n"); return; @@ -764,10 +761,10 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev) unsigned short (*type_trans)(struct sk_buff *, struct net_device *); void (*unregister_dev)(struct net_device *dev); - switch (i2o_dev->subclass) + switch (i2o_dev->lct_data->sub_class) { case I2O_LAN_ETHERNET: - dev = init_etherdev(NULL, sizeof(struct i2o_lan_local)); + dev = init_etherdev(NULL, sizeof(struct i2o_lan_local)); if (dev == NULL) return NULL; type_trans = eth_type_trans; @@ -827,7 +824,7 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev) case I2O_LAN_UNKNOWN: default: printk(KERN_ERR "i2o_lan: LAN type 0x%08X not supported\n", - i2o_dev->subclass); + i2o_dev->lct_data->sub_class); return NULL; } @@ -840,9 +837,8 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev) i2o_landevs[unit] = dev; priv->unit = unit; - if (i2o_query_scalar(i2o_dev->controller, i2o_dev->id, - priv->unit << 16 | lan_context, - 0x0001, 0, &hw_addr, 8, &priv->reply_flag) < 0) + if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data->tid, + 0x0001, 0, &hw_addr, 8) < 0) { printk(KERN_ERR "%s: Unable to query hardware address.\n", dev->name); unit--; @@ -858,9 +854,8 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev) dev->addr_len = 6; memcpy(dev->dev_addr, hw_addr, 6); - if (i2o_query_scalar(i2o_dev->controller, i2o_dev->id, - priv->unit << 16 | lan_context, - 0x0007, 2, &max_tx, 4, &priv->reply_flag) < 0) + if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data->tid, + 0x0007, 2, &max_tx, 4) < 0) { printk(KERN_ERR "%s: Unable to query max TX queue.\n", dev->name); unit--; @@ -912,7 +907,10 @@ int __init i2o_lan_init(void) for (i2o_dev=iop->devices;i2o_dev != NULL;i2o_dev=i2o_dev->next) { - if (i2o_dev->class != I2O_CLASS_LAN) + if (i2o_dev->lct_data->class_id != I2O_CLASS_LAN) + continue; + + if(i2o_dev->lct_data->user_tid != 0xFFF) continue; if (unit == MAX_LAN_CARDS) @@ -931,7 +929,7 @@ int __init i2o_lan_init(void) printk(KERN_INFO "%s: I2O LAN device registered, tid = %d," " subclass = 0x%08X, unit = %d.\n", - dev->name, i2o_dev->id, i2o_dev->subclass, + dev->name, i2o_dev->lct_data->tid, i2o_dev->lct_data->sub_class, ((struct i2o_lan_local *)dev->priv)->unit); } @@ -955,7 +953,7 @@ void cleanup_module(void) struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; struct i2o_device *i2o_dev = priv->i2o_dev; - switch (i2o_dev->subclass) + switch (i2o_dev->lct_data->sub_class) { case I2O_LAN_ETHERNET: unregister_netdev(dev); @@ -975,7 +973,7 @@ void cleanup_module(void) #endif default: printk(KERN_WARNING "i2o_lan: Spurious I2O LAN subclass 0x%08X.\n", - i2o_dev->subclass); + i2o_dev->lct_data->sub_class); } dprintk(KERN_INFO "%s: I2O LAN device unregistered.\n", diff --git a/drivers/i2o/i2o_pci.c b/drivers/i2o/i2o_pci.c index f7afa9a46..122c488a9 100644 --- a/drivers/i2o/i2o_pci.c +++ b/drivers/i2o/i2o_pci.c @@ -25,6 +25,10 @@ #include #include +#ifdef CONFIG_MTRR +#include +#endif // CONFIG_MTRR + #ifdef MODULE /* * Core function table @@ -46,6 +50,11 @@ static void i2o_pci_dispose(struct i2o_controller *c) if(c->bus.pci.irq > 0) free_irq(c->bus.pci.irq, c); iounmap(((u8 *)c->post_port)-0x40); + +#ifdef CONFIG_MTRR + if(c->bus.pci.mtrr_reg > 0) + mtrr_del(c->bus.pci.mtrr_reg, 0, 0); +#endif } /* @@ -65,6 +74,19 @@ static int i2o_pci_unbind(struct i2o_controller *c, struct i2o_device *dev) return 0; } +/* + * Bus specific enable/disable functions + */ +static void i2o_pci_enable(struct i2o_controller *c) +{ + I2O_IRQ_WRITE32(c, 0); +} + +static void i2o_pci_disable(struct i2o_controller *c) +{ + I2O_IRQ_WRITE32(c, 0xFFFFFFFF); +} + /* * Bus specific interrupt handler */ @@ -81,8 +103,9 @@ static void i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r) /* * Install a PCI (or in theory AGP) i2o controller + * + * TODO: Add support for polled controllers */ - int __init i2o_pci_install(struct pci_dev *dev) { struct i2o_controller *c=kmalloc(sizeof(struct i2o_controller), @@ -128,7 +151,7 @@ int __init i2o_pci_install(struct pci_dev *dev) kfree(c); return -EINVAL; } - + c->bus.pci.irq = -1; c->irq_mask = (volatile u32 *)(mem+0x34); @@ -141,9 +164,19 @@ int __init i2o_pci_install(struct pci_dev *dev) c->bind = i2o_pci_bind; c->unbind = i2o_pci_unbind; + c->bus_enable = i2o_pci_enable; + c->bus_disable = i2o_pci_disable; c->type = I2O_TYPE_PCI; + /* + * Enable Write Combining MTRR for IOP's memory region + */ +#ifdef CONFIG_MTRR + c->bus.pci.mtrr_reg = + mtrr_add(c->mem_phys, size, MTRR_TYPE_WRCOMB, 1); +#endif + I2O_IRQ_WRITE32(c,0xFFFFFFFF); #ifdef MODULE @@ -180,6 +213,9 @@ int __init i2o_pci_install(struct pci_dev *dev) return -EBUSY; } } + + printk(KERN_INFO "Installed iop%d at IRQ%d\n", c->unit, dev->irq); + I2O_IRQ_WRITE32(c,0x0); return 0; } @@ -211,102 +247,54 @@ int __init i2o_pci_scan(void) return count?count:-ENODEV; } -static void i2o_pci_unload(void) +#ifdef I2O_HOTPLUG_SUPPORT +/* + * Activate a newly found PCI I2O controller + * Not used now, but will be needed in future for + * hot plug PCI support + */ +static void i2o_pci_activate(i2o_controller * c) { int i=0; struct i2o_controller *c; - for(i = 0; i < MAX_I2O_CONTROLLERS; i++) + if(c->type == I2O_TYPE_PCI) { + I2O_IRQ_WRITE32(c,0); #ifdef MODULE - c=core->find(i); + if(core->activate(c)) #else - c=i2o_find_controller(i); + if(i2o_activate_controller(c)) #endif /* MODULE */ - - if(c==NULL) - continue; - -#ifdef MODULE - core->unlock(c); -#else - i2o_unlock_controller(c); -#endif /* MODULE */ - - if(c->type == I2O_TYPE_PCI) + { + printk("I2O: Failed to initialize iop%d\n", c->unit); #ifdef MODULE + core->unlock(c); core->delete(c); #else + i2o_unlock_controller(c); i2o_delete_controller(c); -#endif /* MODULE */ - } -} - -static void i2o_pci_activate(void) -{ - int i=0; - struct i2o_controller *c; - - for(i = 0; i < MAX_I2O_CONTROLLERS; i++) - { -#ifdef MODULE - c=core->find(i); -#else - c=i2o_find_controller(i); -#endif /* MODULE */ - - if(c==NULL) - continue; - - if(c->type == I2O_TYPE_PCI) - { -#ifdef MODULE - if(core->activate(c)) -#else - if(i2o_activate_controller(c)) -#endif /* MODULE */ - { - printk("I2O: Failed to initialize iop%d\n", c->unit); -#ifdef MODULE - core->unlock(c); - core->delete(c); -#else - i2o_unlock_controller(c); - i2o_delete_controller(c); #endif - continue; - } - I2O_IRQ_WRITE32(c,0); + continue; } -#ifdef MODULE - core->unlock(c); -#else - i2o_unlock_controller(c); -#endif } } - +#endif // I2O_HOTPLUG_SUPPORT #ifdef MODULE int i2o_pci_core_attach(struct i2o_core_func_table *table) { - int i; - MOD_INC_USE_COUNT; core = table; - - if((i = i2o_pci_scan())<0) - return -ENODEV; - i2o_pci_activate(); - return i; + return i2o_pci_scan(); } void i2o_pci_core_detach(void) { - i2o_pci_unload(); + core = NULL; MOD_DEC_USE_COUNT; } @@ -314,16 +302,8 @@ void i2o_pci_core_detach(void) int init_module(void) { printk(KERN_INFO "Linux I2O PCI support (c) 1999 Red Hat Software.\n"); - -/* - * Let the core call the scan function for module dependency - * reasons. See include/linux/i2o.h for the reason why this - * is done. - * - * if(i2o_pci_scan()<0) - * return -ENODEV; - * i2o_pci_activate(); - */ + + core = NULL; return 0; @@ -343,9 +323,6 @@ MODULE_DESCRIPTION("I2O PCI Interface"); void __init i2o_pci_init(void) { printk(KERN_INFO "Linux I2O PCI support (c) 1999 Red Hat Software.\n"); - if(i2o_pci_scan()>=0) - { - i2o_pci_activate(); - } + i2o_pci_scan(); } #endif diff --git a/drivers/i2o/i2o_proc.c b/drivers/i2o/i2o_proc.c index cbb29bc5b..4059a5189 100644 --- a/drivers/i2o/i2o_proc.c +++ b/drivers/i2o/i2o_proc.c @@ -1,7 +1,7 @@ /* * procfs handler for Linux I2O subsystem * - * Copyright (c) 1999 Deepak Saxena + * (c) Copyright 1999 Deepak Saxena * * Originally written by Deepak Saxena(deepak@plexity.net) * @@ -790,16 +790,15 @@ int i2o_proc_read_hw(char *buf, char **start, off_t offset, int len, len = 0; - token = i2o_query_scalar(c, ADAPTER_TID, proc_context, + token = i2o_query_scalar(c, ADAPTER_TID, 0, // ParamGroup 0x0000h -1, // all fields &work32, - sizeof(work32), - &i2o_proc_token); + sizeof(work32)); if(token < 0) { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + len += sprintf(buf, "Error waiting for reply from IOP\n"); spin_unlock(&i2o_proc_lock); return len; } @@ -875,10 +874,10 @@ int i2o_proc_read_ddm_table(char *buf, char **start, off_t offset, int len, len = 0; token = i2o_query_table(I2O_PARAMS_TABLE_GET, - c, ADAPTER_TID, proc_context, + c, ADAPTER_TID, 0x0003, -1, NULL, 0, - &result, sizeof(result), &i2o_proc_token); + &result, sizeof(result)); if (token<0) switch (token) @@ -941,16 +940,13 @@ int i2o_proc_read_ds(char *buf, char **start, off_t offset, int len, { struct i2o_controller *c = (struct i2o_controller*)data; u32 work32[8]; - int token; spin_lock(&i2o_proc_lock); len = 0; - token = i2o_query_scalar(c, ADAPTER_TID, proc_context, 0x0004, -1, - &work32, sizeof(work32), &i2o_proc_token); - - if (token<0) + if(i2o_query_scalar(c, ADAPTER_TID, 0x0004, -1, &work32, + sizeof(work32)) < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); spin_unlock(&i2o_proc_lock); @@ -1009,10 +1005,10 @@ int i2o_proc_read_dst(char *buf, char **start, off_t offset, int len, len = 0; token = i2o_query_table(I2O_PARAMS_TABLE_GET, - c, ADAPTER_TID, proc_context, + c, ADAPTER_TID, 0x0005, -1, NULL, 0, - &result, sizeof(result), &i2o_proc_token); + &result, sizeof(result)); if (token<0) switch (token) @@ -1094,10 +1090,10 @@ int i2o_proc_read_groups(char *buf, char **start, off_t offset, int len, len = 0; token = i2o_query_table(I2O_PARAMS_TABLE_GET, - c, ADAPTER_TID, proc_context, + c, ADAPTER_TID, 0xF000, -1, NULL, 0, - &work16, sizeof(work16), &i2o_proc_token); + &work16, sizeof(work16)); if (token<0) switch (token) @@ -1181,10 +1177,10 @@ int i2o_proc_read_priv_msgs(char *buf, char **start, off_t offset, int len, len = 0; token = i2o_query_table(I2O_PARAMS_TABLE_GET, - c, ADAPTER_TID, proc_context, + c, ADAPTER_TID, 0xF000, -1, NULL, 0, - &work16, sizeof(work16), &i2o_proc_token); + &work16, sizeof(work16)); if (token<0) switch (token) @@ -1243,12 +1239,11 @@ int i2o_proc_read_dev(char *buf, char **start, off_t offset, int len, len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, + token = i2o_query_scalar(d->controller, d->lct_data->tid, 0xF100, // ParamGroup F100h (Device Identity) -1, // all fields &work32, - sizeof(work32), - &i2o_proc_token); + sizeof(work32)); if(token < 0) { @@ -1308,12 +1303,11 @@ int i2o_proc_read_ddm(char *buf, char **start, off_t offset, int len, len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, + token = i2o_query_scalar(d->controller, d->lct_data->tid, 0xF101, // ParamGroup F101h (DDM Identity) -1, // all fields &work32, - sizeof(work32), - &i2o_proc_token); + sizeof(work32)); if(token < 0) { @@ -1352,12 +1346,11 @@ int i2o_proc_read_uinfo(char *buf, char **start, off_t offset, int len, len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, + token = i2o_query_scalar(d->controller, d->lct_data->tid, 0xF102, // ParamGroup F102h (User Information) -1, // all fields &work32, - sizeof(work32), - &i2o_proc_token); + sizeof(work32)); if(token < 0) { @@ -1390,12 +1383,11 @@ int i2o_proc_read_sgl_limits(char *buf, char **start, off_t offset, int len, len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, + token = i2o_query_scalar(d->controller, d->lct_data->tid, 0xF103, // ParamGroup F103h (SGL Operating Limits) -1, // all fields &work32, - sizeof(work32), - &i2o_proc_token); + sizeof(work32)); if(token < 0) { @@ -1760,8 +1752,8 @@ int i2o_proc_read_lan_dev_info(char *buf, char **start, off_t offset, int len, len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0000, -1, &work32, 56*4, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0000, -1, &work32, 56*4); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -1883,8 +1875,8 @@ int i2o_proc_read_lan_mac_addr(char *buf, char **start, off_t offset, int len, spin_lock(&i2o_proc_lock); len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0001, -1, &work32, 48*4, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0001, -1, &work32, 48*4); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -1973,9 +1965,8 @@ int i2o_proc_read_lan_mcast_addr(char *buf, char **start, off_t offset, len = 0; token = i2o_query_table(I2O_PARAMS_TABLE_GET, - d->controller, d->id, proc_context, 0x0002, -1, - NULL, 0, &field32, sizeof(field32), - &i2o_proc_token); + d->controller, d->lct_data->tid, 0x0002, -1, + NULL, 0, &field32, sizeof(field32)); if (token<0) switch (token) { @@ -2026,8 +2017,8 @@ int i2o_proc_read_lan_batch_control(char *buf, char **start, off_t offset, spin_lock(&i2o_proc_lock); len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0003, -1, &work32, 9*4, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0003, -1, &work32, 9*4); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -2086,8 +2077,8 @@ int i2o_proc_read_lan_operation(char *buf, char **start, off_t offset, int len, spin_lock(&i2o_proc_lock); len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0004, -1, &work32, 20, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0004, -1, &work32, 20); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -2151,8 +2142,8 @@ int i2o_proc_read_lan_media_operation(char *buf, char **start, off_t offset, spin_lock(&i2o_proc_lock); len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0005, -1, &work32, 36, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0005, -1, &work32, 36); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -2225,9 +2216,8 @@ int i2o_proc_read_lan_alt_addr(char *buf, char **start, off_t offset, int len, len = 0; token = i2o_query_table(I2O_PARAMS_TABLE_GET, - d->controller, d->id, proc_context, 0x0006, -1, - NULL, 0, &field32, sizeof(field32), - &i2o_proc_token); + d->controller, d->lct_data->tid, 0x0006, -1, + NULL, 0, &field32, sizeof(field32)); if (token<0) switch (token) { @@ -2279,8 +2269,8 @@ int i2o_proc_read_lan_tx_info(char *buf, char **start, off_t offset, int len, spin_lock(&i2o_proc_lock); len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0007, -1, &work32, 8*4, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0007, -1, &work32, 8*4); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -2341,8 +2331,8 @@ int i2o_proc_read_lan_rx_info(char *buf, char **start, off_t offset, int len, spin_lock(&i2o_proc_lock); len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0008, -1, &work32, 8*4, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0008, -1, &work32, 8*4); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -2376,8 +2366,8 @@ int i2o_proc_read_lan_hist_stats(char *buf, char **start, off_t offset, int len, spin_lock(&i2o_proc_lock); len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0100, -1, &work64, 9*8, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0100, -1, &work64, 9*8); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -2421,8 +2411,8 @@ int i2o_proc_read_lan_supp_opt_stats(char *buf, char **start, off_t offset, len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0180, -1, &work64, 4*8, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0180, -1, &work64, 4*8); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -2461,8 +2451,8 @@ int i2o_proc_read_lan_opt_tx_hist_stats(char *buf, char **start, off_t offset, len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0182, -1, &work64, 9*8, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0182, -1, &work64, 9*8); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -2506,8 +2496,8 @@ int i2o_proc_read_lan_opt_rx_hist_stats(char *buf, char **start, off_t offset, len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0183, -1, &work64, 11*8, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0183, -1, &work64, 11*8); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -2555,8 +2545,8 @@ int i2o_proc_read_lan_eth_stats(char *buf, char **start, off_t offset, len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0200, -1, &work64, 8*8, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0200, -1, &work64, 8*8); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -2597,8 +2587,8 @@ int i2o_proc_read_lan_supp_eth_stats(char *buf, char **start, off_t offset, len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0280, -1, &work64, 8, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0280, -1, &work64, 8); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -2625,8 +2615,8 @@ int i2o_proc_read_lan_opt_eth_stats(char *buf, char **start, off_t offset, len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0281, -1, &work64, 3*8, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0281, -1, &work64, 3*8); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -2677,8 +2667,8 @@ int i2o_proc_read_lan_tr_stats(char *buf, char **start, off_t offset, len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0300, -1, &work64, 13*8, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0300, -1, &work64, 13*8); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -2771,8 +2761,8 @@ int i2o_proc_read_lan_fddi_stats(char *buf, char **start, off_t offset, len = 0; - token = i2o_query_scalar(d->controller, d->id, proc_context, - 0x0400, -1, &work64, 11*8, &i2o_proc_token); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0400, -1, &work64, 11*8); if(token < 0) { len += sprintf(buf, "Timeout waiting for reply from IOP\n"); @@ -2853,7 +2843,7 @@ static int i2o_proc_add_controller(struct i2o_controller *pctrl, for(dev = pctrl->devices; dev; dev = dev->next) { - sprintf(buff, "%0#5x", dev->id); + sprintf(buff, "%0#5x", dev->lct_data->tid); dir1 = create_proc_entry(buff, S_IFDIR, dir); dev->proc_entry = dir1; @@ -2863,7 +2853,7 @@ static int i2o_proc_add_controller(struct i2o_controller *pctrl, i2o_proc_create_entries(dev, generic_dev_entries, dir1); - switch(dev->class) + switch(dev->lct_data->class_id) { case I2O_CLASS_SCSI_PERIPHERAL: case I2O_CLASS_RANDOM_BLOCK_STORAGE: @@ -2871,7 +2861,7 @@ static int i2o_proc_add_controller(struct i2o_controller *pctrl, break; case I2O_CLASS_LAN: i2o_proc_create_entries(dev, lan_entries, dir1); - switch(dev->subclass) + switch(dev->lct_data->sub_class) { case I2O_LAN_ETHERNET: i2o_proc_create_entries(dev, lan_eth_entries, @@ -2909,14 +2899,14 @@ static void i2o_proc_remove_controller(struct i2o_controller *pctrl, for(dev=pctrl->devices; dev; dev=dev->next) { de=dev->proc_entry; - sprintf(dev_id, "%0#5x", dev->id); + sprintf(dev_id, "%0#5x", dev->lct_data->tid); /* Would it be safe to remove _files_ even if they are in use? */ if((de) && (!de->count)) { i2o_proc_remove_entries(generic_dev_entries, de); - switch(dev->class) + switch(dev->lct_data->class_id) { case I2O_CLASS_SCSI_PERIPHERAL: case I2O_CLASS_RANDOM_BLOCK_STORAGE: @@ -2924,7 +2914,7 @@ static void i2o_proc_remove_controller(struct i2o_controller *pctrl, break; case I2O_CLASS_LAN: i2o_proc_remove_entries(lan_entries, de); - switch(dev->subclass) + switch(dev->lct_data->sub_class) { case I2O_LAN_ETHERNET: i2o_proc_remove_entries(lan_eth_entries, de); diff --git a/drivers/i2o/i2o_scsi.c b/drivers/i2o/i2o_scsi.c index 7b309411b..46f7fbfb0 100644 --- a/drivers/i2o/i2o_scsi.c +++ b/drivers/i2o/i2o_scsi.c @@ -301,14 +301,12 @@ static int i2o_find_lun(struct i2o_controller *c, struct i2o_device *d, int *tar { u8 reply[8]; - if(i2o_query_scalar(c, d->id, scsi_context|0x40000000, - 0, 3, reply, 4, &lun_done)<0) + if(i2o_query_scalar(c, d->lct_data->tid, 0, 3, reply, 4)) return -1; *target=reply[0]; - if(i2o_query_scalar(c, d->id, scsi_context|0x40000000, - 0, 4, reply, 8, &lun_done)<0) + if(i2o_query_scalar(c, d->lct_data->tid, 0, 4, reply, 8)) return -1; *lun=reply[1]; @@ -325,7 +323,7 @@ void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct Scsi_H int target; h->controller=c; - h->bus_task=d->id; + h->bus_task=d->lct_data->tid; for(target=0;target<16;target++) for(lun=0;lun<8;lun++) @@ -334,34 +332,33 @@ void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct Scsi_H for(unit=c->devices;unit!=NULL;unit=unit->next) { dprintk(("Class %03X, parent %d, want %d.\n", - unit->class, unit->parent, d->id)); + unit->lct_data->class_id, unit->lct_data->parent, d->lct_data->tid)); /* Only look at scsi and fc devices */ - if ( (unit->class != I2O_CLASS_SCSI_PERIPHERAL) - && (unit->class != I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL) + if ( (unit->lct_data->class_id != I2O_CLASS_SCSI_PERIPHERAL) + && (unit->lct_data->class_id != I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL) ) continue; /* On our bus ? */ dprintk(("Found a disk.\n")); - if ( (unit->parent == d->id) - || (unit->parent == d->parent) + if ((unit->lct_data->parent_tid == d->lct_data->tid) + || (unit->lct_data->parent_tid == d->lct_data->parent_tid) ) { u16 limit; dprintk(("Its ours.\n")); if(i2o_find_lun(c, unit, &target, &lun)==-1) { - printk(KERN_ERR "i2o_scsi: Unable to get lun for tid %d.\n", d->id); + printk(KERN_ERR "i2o_scsi: Unable to get lun for tid %d.\n", d->lct_data->tid); continue; } dprintk(("Found disk %d %d.\n", target, lun)); - h->task[target][lun]=unit->id; + h->task[target][lun]=unit->lct_data->tid; h->tagclock[target][lun]=jiffies; /* Get the max fragments/request */ - i2o_query_scalar(c, d->id, scsi_context|0x40000000, - 0xF103, 3, &limit, 2, &lun_done); + i2o_query_scalar(c, d->lct_data->tid, 0xF103, 3, &limit, 2); /* sanity */ if ( limit == 0 ) @@ -435,8 +432,8 @@ int i2o_scsi_detect(Scsi_Host_Template * tpnt) /* * bus_adapter, SCSI (obsolete), or FibreChannel busses only */ - if( (d->class!=I2O_CLASS_BUS_ADAPTER_PORT) // bus_adapter - && (d->class!=I2O_CLASS_FIBRE_CHANNEL_PORT) // FC_PORT + if( (d->lct_data->class_id!=I2O_CLASS_BUS_ADAPTER_PORT) // bus_adapter + && (d->lct_data->class_id!=I2O_CLASS_FIBRE_CHANNEL_PORT) // FC_PORT ) continue; diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c index 720932cc9..39a27107f 100644 --- a/drivers/macintosh/macserial.c +++ b/drivers/macintosh/macserial.c @@ -2584,7 +2584,9 @@ void unregister_serial(int line) * ------------------------------------------------------------ */ #ifdef CONFIG_SERIAL_CONSOLE - +#ifdef CONFIG_SERIAL +#error Cannot build serial console with macserial and serial drivers +#endif /* * Print a string to the serial port trying not to disturb @@ -2843,7 +2845,7 @@ static struct console sercons = { /* * Register console. */ -long __init serial_console_init(long kmem_start, long kmem_end) +void __init serial_console_init(void) { register_console(&sercons); return kmem_start; diff --git a/drivers/misc/acpi.c b/drivers/misc/acpi.c index 03c39fb61..093a7bbb8 100644 --- a/drivers/misc/acpi.c +++ b/drivers/misc/acpi.c @@ -29,8 +29,13 @@ #include #include #include +#include +#include +#include #include #include +#include +#include #include /* @@ -49,7 +54,26 @@ #define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue * x = NULL #endif +static int acpi_do_ulong(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len); +static int acpi_do_event_reg(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len); +static int acpi_do_event(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len); + +static struct ctl_table_header *acpi_sysctl = NULL; + static struct acpi_facp *acpi_facp = NULL; +static int acpi_fake_facp = 0; static unsigned long acpi_facp_addr = 0; static unsigned long acpi_dsdt_addr = 0; @@ -57,15 +81,64 @@ static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED; static volatile u32 acpi_pm1_status = 0; static volatile u32 acpi_gpe_status = 0; static volatile u32 acpi_gpe_level = 0; -static DECLARE_WAIT_QUEUE_HEAD(acpi_wait_event); +static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait); /* Make it impossible to enter L2/L3 until after we've initialized */ static unsigned long acpi_p_lvl2_lat = ~0UL; static unsigned long acpi_p_lvl3_lat = ~0UL; /* Initialize to guaranteed harmless port read */ -static u16 acpi_p_lvl2 = 0x80; -static u16 acpi_p_lvl3 = 0x80; +static unsigned long acpi_p_lvl2 = 0x80; +static unsigned long acpi_p_lvl3 = 0x80; + +static struct ctl_table acpi_table[] = +{ + {ACPI_FACP, "facp", + &acpi_facp_addr, sizeof(acpi_facp_addr), + 0400, NULL, &acpi_do_ulong}, + + {ACPI_DSDT, "dsdt", + &acpi_dsdt_addr, sizeof(acpi_dsdt_addr), + 0400, NULL, &acpi_do_ulong}, + + {ACPI_PM1_ENABLE, "pm1_enable", + NULL, 0, + 0600, NULL, &acpi_do_event_reg}, + + {ACPI_GPE_ENABLE, "gpe_enable", + NULL, 0, + 0600, NULL, &acpi_do_event_reg}, + + {ACPI_GPE_LEVEL, "gpe_level", + NULL, 0, + 0600, NULL, &acpi_do_event_reg}, + + {ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event}, + + {ACPI_P_LVL2, "p_lvl2", + &acpi_p_lvl2, sizeof(acpi_p_lvl2), + 0600, NULL, &acpi_do_ulong}, + + {ACPI_P_LVL3, "p_lvl3", + &acpi_p_lvl3, sizeof(acpi_p_lvl3), + 0600, NULL, &acpi_do_ulong}, + + {ACPI_P_LVL2_LAT, "p_lvl2_lat", + &acpi_p_lvl2_lat, sizeof(acpi_p_lvl2_lat), + 0600, NULL, &acpi_do_ulong}, + + {ACPI_P_LVL3_LAT, "p_lvl3_lat", + &acpi_p_lvl3_lat, sizeof(acpi_p_lvl3_lat), + 0600, NULL, &acpi_do_ulong}, + + {0} +}; + +static struct ctl_table acpi_dir_table[] = +{ + {CTL_ACPI, "acpi", NULL, 0, 0500, acpi_table}, + {0} +}; /* @@ -73,7 +146,9 @@ static u16 acpi_p_lvl3 = 0x80; */ static u32 acpi_read_pm1_control(struct acpi_facp *facp) { - u32 value = inw(facp->pm1a_cnt); + u32 value = 0; + if (facp->pm1a_cnt) + value = inw(facp->pm1a_cnt); if (facp->pm1b_cnt) value |= inw(facp->pm1b_cnt); return value; @@ -84,7 +159,9 @@ static u32 acpi_read_pm1_control(struct acpi_facp *facp) */ static u32 acpi_read_pm1_status(struct acpi_facp *facp) { - u32 value = inw(facp->pm1a_evt); + u32 value = 0; + if (facp->pm1a_evt) + value = inw(facp->pm1a_evt); if (facp->pm1b_evt) value |= inw(facp->pm1b_evt); return value; @@ -95,7 +172,8 @@ static u32 acpi_read_pm1_status(struct acpi_facp *facp) */ static void acpi_write_pm1_status(struct acpi_facp *facp, u32 value) { - outw(value, facp->pm1a_evt); + if (facp->pm1a_evt) + outw(value, facp->pm1a_evt); if (facp->pm1b_evt) outw(value, facp->pm1b_evt); } @@ -106,7 +184,9 @@ static void acpi_write_pm1_status(struct acpi_facp *facp, u32 value) static u32 acpi_read_pm1_enable(struct acpi_facp *facp) { int offset = facp->pm1_evt_len >> 1; - u32 value = inw(facp->pm1a_evt + offset); + u32 value = 0; + if (facp->pm1a_evt) + value = inw(facp->pm1a_evt + offset); if (facp->pm1b_evt) value |= inw(facp->pm1b_evt + offset); return value; @@ -118,7 +198,8 @@ static u32 acpi_read_pm1_enable(struct acpi_facp *facp) static void acpi_write_pm1_enable(struct acpi_facp *facp, u32 value) { int offset = facp->pm1_evt_len >> 1; - outw(value, facp->pm1a_evt + offset); + if (facp->pm1a_evt) + outw(value, facp->pm1a_evt + offset); if (facp->pm1b_evt) outw(value, facp->pm1b_evt + offset); } @@ -136,9 +217,11 @@ static u32 acpi_read_gpe_status(struct acpi_facp *facp) for (i = size - 1; i >= 0; i--) value = (value << 8) | inb(facp->gpe1 + i); } - size = facp->gpe0_len >> 1; - for (i = size - 1; i >= 0; i--) - value = (value << 8) | inb(facp->gpe0 + i); + if (facp->gpe0) { + size = facp->gpe0_len >> 1; + for (i = size - 1; i >= 0; i--) + value = (value << 8) | inb(facp->gpe0 + i); + } return value; } @@ -149,10 +232,12 @@ static void acpi_write_gpe_status(struct acpi_facp *facp, u32 value) { int i, size; - size = facp->gpe0_len >> 1; - for (i = 0; i < size; i++) { - outb(value & 0xff, facp->gpe0 + i); - value >>= 8; + if (facp->gpe0) { + size = facp->gpe0_len >> 1; + for (i = 0; i < size; i++) { + outb(value & 0xff, facp->gpe0 + i); + value >>= 8; + } } if (facp->gpe1) { size = facp->gpe1_len >> 1; @@ -178,9 +263,11 @@ static u32 acpi_read_gpe_enable(struct acpi_facp *facp) value = (value << 8) | inb(facp->gpe1 + offset + i); } } - size = facp->gpe0_len >> 1; - for (i = size - 1; i >= 0; i--) - value = (value << 8) | inb(facp->gpe0 + offset + i); + if (facp->gpe0) { + size = facp->gpe0_len >> 1; + for (i = size - 1; i >= 0; i--) + value = (value << 8) | inb(facp->gpe0 + offset + i); + } return value; } @@ -192,9 +279,11 @@ static void acpi_write_gpe_enable(struct acpi_facp *facp, u32 value) int i, offset; offset = facp->gpe0_len >> 1; - for (i = 0; i < offset; i++) { - outb(value & 0xff, facp->gpe0 + offset + i); - value >>= 8; + if (facp->gpe0) { + for (i = 0; i < offset; i++) { + outb(value & 0xff, facp->gpe0 + offset + i); + value >>= 8; + } } if (facp->gpe1) { offset = facp->gpe1_len >> 1; @@ -238,9 +327,9 @@ static void acpi_unmap_table(struct acpi_table *table) } /* - * Locate and map ACPI tables (FACP, DSDT, ...) + * Locate and map ACPI tables */ -static int __init acpi_map_tables(void) +static int __init acpi_find_tables(void) { struct acpi_rsdp *rsdp; struct acpi_table *rsdt; @@ -251,8 +340,8 @@ static int __init acpi_map_tables(void) // search BIOS memory for RSDP for (i = ACPI_BIOS_ROM_BASE; i < ACPI_BIOS_ROM_END; i += 16) { rsdp = (struct acpi_rsdp *) phys_to_virt(i); - if (rsdp->signature[0] == ACPI_RSDP1_SIG && - rsdp->signature[1] == ACPI_RSDP2_SIG) { + if (rsdp->signature[0] == ACPI_RSDP1_SIG + && rsdp->signature[1] == ACPI_RSDP2_SIG) { char oem[7]; int j; @@ -270,14 +359,13 @@ static int __init acpi_map_tables(void) break; } } - if (i >= ACPI_BIOS_ROM_END) { - printk(KERN_ERR "ACPI: no RSDP found\n"); + if (i >= ACPI_BIOS_ROM_END) return -ENODEV; - } + // fetch RSDT from RSDP rsdt = acpi_map_table(rsdp->rsdt); if (!rsdt || rsdt->signature != ACPI_RSDT_SIG) { - printk(KERN_ERR "ACPI: no RSDT found\n"); + printk(KERN_ERR "ACPI: missing RSDT\n"); acpi_unmap_table(rsdt); return -ENODEV; } @@ -288,11 +376,11 @@ static int __init acpi_map_tables(void) while (rsdt_entry_count) { struct acpi_table *dt = acpi_map_table(*rsdt_entry); if (dt && dt->signature == ACPI_FACP_SIG) { - acpi_facp = (struct acpi_facp *) dt; + acpi_facp = (struct acpi_facp*) dt; acpi_facp_addr = *rsdt_entry; acpi_dsdt_addr = acpi_facp->dsdt; - break; - } else { + } + else { acpi_unmap_table(dt); } rsdt_entry++; @@ -302,22 +390,89 @@ static int __init acpi_map_tables(void) acpi_unmap_table(rsdt); if (!acpi_facp) { - printk(KERN_ERR "ACPI: no FACP found\n"); + printk(KERN_ERR "ACPI: missing FACP\n"); return -ENODEV; } return 0; } /* - * Unmap ACPI tables (FACP, DSDT, ...) + * Unmap or destroy ACPI tables */ -static void acpi_unmap_tables(void) +static void acpi_destroy_tables(void) { - acpi_idle = NULL; + if (!acpi_fake_facp) + acpi_unmap_table((struct acpi_table*) acpi_facp); + else + kfree(acpi_facp); +} + +/* + * Locate PIIX4 device and create a fake FACP + */ +static int __init acpi_find_piix4(void) +{ + struct pci_dev *dev; + u32 base; + u16 cmd; + u8 pmregmisc; + + dev = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_3, + NULL); + if (!dev) + return -ENODEV; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (!(cmd & PCI_COMMAND_IO)) + return -ENODEV; + + pci_read_config_byte(dev, ACPI_PIIX4_PMREGMISC, &pmregmisc); + if (!(pmregmisc & ACPI_PIIX4_PMIOSE)) + return -ENODEV; + + pci_read_config_dword(dev, 0x40, &base); + if (!(base & PCI_BASE_ADDRESS_SPACE_IO)) + return -ENODEV; + + base &= PCI_BASE_ADDRESS_IO_MASK; + if (!base) + return -ENODEV; + + printk(KERN_INFO "ACPI: found PIIX4 at 0x%04x\n", base); + + acpi_facp = kmalloc(sizeof(struct acpi_facp), GFP_KERNEL); + if (!acpi_facp) + return -ENOMEM; + + acpi_fake_facp = 1; + memset(acpi_facp, 0, sizeof(struct acpi_facp)); + acpi_facp->int_model = ACPI_PIIX4_INT_MODEL; + acpi_facp->sci_int = ACPI_PIIX4_SCI_INT; + acpi_facp->smi_cmd = ACPI_PIIX4_SMI_CMD; + acpi_facp->acpi_enable = ACPI_PIIX4_ACPI_ENABLE; + acpi_facp->acpi_disable = ACPI_PIIX4_ACPI_DISABLE; + acpi_facp->s4bios_req = ACPI_PIIX4_S4BIOS_REQ; + acpi_facp->pm1a_evt = base + ACPI_PIIX4_PM1_EVT; + acpi_facp->pm1a_cnt = base + ACPI_PIIX4_PM1_CNT; + acpi_facp->pm2_cnt = ACPI_PIIX4_PM2_CNT; + acpi_facp->pm_tmr = base + ACPI_PIIX4_PM_TMR; + acpi_facp->gpe0 = base + ACPI_PIIX4_GPE0; + acpi_facp->pm1_evt_len = ACPI_PIIX4_PM1_EVT_LEN; + acpi_facp->pm1_cnt_len = ACPI_PIIX4_PM1_CNT_LEN; + acpi_facp->pm2_cnt_len = ACPI_PIIX4_PM2_CNT_LEN; + acpi_facp->pm_tm_len = ACPI_PIIX4_PM_TM_LEN; + acpi_facp->gpe0_len = ACPI_PIIX4_GPE0_LEN; + acpi_facp->p_lvl2_lat = ~0; + acpi_facp->p_lvl3_lat = ~0; + + acpi_facp_addr = virt_to_phys(acpi_facp); acpi_dsdt_addr = 0; - acpi_facp_addr = 0; - acpi_unmap_table((struct acpi_table *) acpi_facp); - acpi_facp = NULL; + + acpi_p_lvl2 = base + ACPI_PIIX4_P_LVL2; + acpi_p_lvl3 = base + ACPI_PIIX4_P_LVL3; + + return 0; } /* @@ -355,25 +510,7 @@ static void acpi_irq(int irq, void *dev_id, struct pt_regs *regs) acpi_pm1_status |= pm1_status; acpi_gpe_status |= gpe_status; spin_unlock_irqrestore(&acpi_event_lock, flags); - wake_up_interruptible(&acpi_wait_event); -} - -/* - * Handle open of /dev/acpi - */ -static int acpi_open(struct inode *inode, struct file *file) -{ - MOD_INC_USE_COUNT; - return 0; -} - -/* - * Handle close of /dev/acpi - */ -static int acpi_release(struct inode *inode, struct file *file) -{ - MOD_DEC_USE_COUNT; - return 0; + wake_up_interruptible(&acpi_event_wait); } /* @@ -389,7 +526,8 @@ static inline int acpi_is_enabled(struct acpi_facp *facp) */ static int acpi_enable(struct acpi_facp *facp) { - outb(facp->acpi_enable, facp->smi_cmd); + if (facp->smi_cmd) + outb(facp->acpi_enable, facp->smi_cmd); return (acpi_is_enabled(facp) ? 0:-1); } @@ -404,132 +542,29 @@ static int acpi_disable(struct acpi_facp *facp) acpi_write_gpe_status(facp, acpi_read_gpe_status(facp)); acpi_write_pm1_enable(facp, 0); acpi_write_pm1_status(facp, acpi_read_pm1_status(facp)); - - outb(facp->acpi_disable, facp->smi_cmd); + + if (facp->smi_cmd) + outb(facp->acpi_disable, facp->smi_cmd); return (acpi_is_enabled(facp) ? -1:0); } /* - * Handle command to /dev/acpi + * Idle loop */ -static int acpi_ioctl(struct inode *inode, - struct file *file, - unsigned cmd, - unsigned long arg) -{ - int status = -EINVAL; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - switch (cmd) { - case ACPI_FIND_TABLES: - status = verify_area(VERIFY_WRITE, - (void *) arg, - sizeof(struct acpi_find_tables)); - if (!status) { - struct acpi_find_tables *rqst - = (struct acpi_find_tables *) arg; - put_user(acpi_facp_addr, &rqst->facp); - put_user(acpi_dsdt_addr, &rqst->dsdt); - status = 0; - } - break; - case ACPI_ENABLE_EVENT: - status = verify_area(VERIFY_READ, - (void *) arg, - sizeof(struct acpi_enable_event)); - if (!status) { - struct acpi_enable_event *rqst - = (struct acpi_enable_event *) arg; - u32 pm1_enable, gpe_enable, gpe_level; - u32 pm1_enabling, gpe_enabling; - - get_user(pm1_enable, &rqst->pm1_enable); - get_user(gpe_enable, &rqst->gpe_enable); - get_user(gpe_level, &rqst->gpe_level); - gpe_level &= gpe_enable; - - // clear previously disabled events before enabling - pm1_enabling = (pm1_enable - & ~acpi_read_pm1_enable(acpi_facp)); - acpi_write_pm1_status(acpi_facp, pm1_enabling); - gpe_enabling = (gpe_enable & - ~acpi_read_gpe_enable(acpi_facp)); - while (acpi_read_gpe_status(acpi_facp) & gpe_enabling) - acpi_write_gpe_status(acpi_facp, gpe_enabling); - - status = 0; - - if (pm1_enable || gpe_enable) { - // enable ACPI unless it is already - if (!acpi_is_enabled(acpi_facp) - && acpi_enable(acpi_facp)) { - status = -EBUSY; - } - } - else { - // disable ACPI unless it is already - if (acpi_is_enabled(acpi_facp) - && acpi_disable(acpi_facp)) { - status = -EBUSY; - } - } - - if (!status) - { - acpi_write_pm1_enable(acpi_facp, pm1_enable); - acpi_write_gpe_enable(acpi_facp, gpe_enable); - acpi_gpe_level = gpe_level; - } - } - break; - case ACPI_WAIT_EVENT: - status = verify_area(VERIFY_WRITE, - (void *) arg, - sizeof(struct acpi_wait_event)); - if (!status) { - struct acpi_wait_event *rqst - = (struct acpi_wait_event *) arg; - u32 pm1_status = 0; - u32 gpe_status = 0; - - for (;;) { - unsigned long flags; - - // we need an atomic exchange here - spin_lock_irqsave(&acpi_event_lock, flags); - pm1_status = acpi_pm1_status; - acpi_pm1_status = 0; - gpe_status = acpi_gpe_status; - acpi_gpe_status = 0; - spin_unlock_irqrestore(&acpi_event_lock, - flags); - - if (pm1_status || gpe_status) - break; - - // wait for an event to arrive - interruptible_sleep_on(&acpi_wait_event); - if (signal_pending(current)) - return -ERESTARTSYS; - } - - put_user(pm1_status, &rqst->pm1_status); - put_user(gpe_status, &rqst->gpe_status); - status = 0; - } - break; - } - return status; -} - static void acpi_idle_handler(void) { - unsigned long time; static int sleep_level = 1; + u32 timer, pm2_cnt; + unsigned long time; - time = inl(acpi_facp->pm_tmr); + // get current time (fallback to CPU cycles if no PM timer) + timer = acpi_facp->pm_tmr; + if (timer) + time = inl(timer); + else + time = get_cycles(); + + // sleep switch (sleep_level) { case 1: __asm__ __volatile__("sti ; hlt": : :"memory"); @@ -538,18 +573,25 @@ static void acpi_idle_handler(void) inb(acpi_p_lvl2); break; case 3: - /* Disable PCI arbitration while sleeping, - to avoid DMA corruption? */ - if (acpi_facp->pm2_cnt) { - unsigned int port = acpi_facp->pm2_cnt; - outb(inb(port) | ACPI_ARB_DIS, port); + pm2_cnt = acpi_facp->pm2_cnt; + if (pm2_cnt) { + /* Disable PCI arbitration while sleeping, + to avoid DMA corruption? */ + outb(inb(pm2_cnt) | ACPI_ARB_DIS, pm2_cnt); + inb(acpi_p_lvl3); + outb(inb(pm2_cnt) & ~ACPI_ARB_DIS, pm2_cnt); + } + else { inb(acpi_p_lvl3); - outb(inb(port) & ~ACPI_ARB_DIS, port); - break; } - inb(acpi_p_lvl3); + break; } - time = (inl(acpi_facp->pm_tmr) - time) & ACPI_TMR_MASK; + + // calculate time spent sleeping (fallback to CPU cycles) + if (timer) + time = (inl(timer) - time) & ACPI_TMR_MASK; + else + time = ACPI_CPU_TO_TMR_TICKS(get_cycles() - time); if (time > acpi_p_lvl3_lat) sleep_level = 3; @@ -559,50 +601,24 @@ static void acpi_idle_handler(void) sleep_level = 1; } -static struct file_operations acpi_fops = -{ - NULL, /* llseek */ - NULL, /* read */ - NULL, /* write */ - NULL, /* readdir */ - NULL, /* poll */ - acpi_ioctl, /* ioctl */ - NULL, /* mmap */ - acpi_open, /* open */ - NULL, /* flush */ - acpi_release, /* release */ - NULL, /* fsync */ - NULL, /* fasync */ - NULL, /* check_media_change */ - NULL, /* revalidate */ - NULL, /* lock */ -}; - -static struct miscdevice acpi_device = -{ - ACPI_MINOR_DEV, - "acpi", - &acpi_fops, - NULL, - NULL -}; - /* * Claim ACPI I/O ports */ static int acpi_claim_ioports(struct acpi_facp *facp) { // we don't get a guarantee of contiguity for any of the ACPI registers - request_region(facp->pm1a_evt, facp->pm1_evt_len, "acpi"); + if (facp->pm1a_evt) + request_region(facp->pm1a_evt, facp->pm1_evt_len, "acpi"); if (facp->pm1b_evt) request_region(facp->pm1b_evt, facp->pm1_evt_len, "acpi"); - request_region(facp->pm1a_cnt, facp->pm1_cnt_len, "acpi"); + if (facp->pm1a_cnt) + request_region(facp->pm1a_cnt, facp->pm1_cnt_len, "acpi"); if (facp->pm1b_cnt) request_region(facp->pm1b_cnt, facp->pm1_cnt_len, "acpi"); - if (facp->pm2_cnt) - request_region(facp->pm2_cnt, facp->pm2_cnt_len, "acpi"); - request_region(facp->pm_tmr, facp->pm_tm_len, "acpi"); - request_region(facp->gpe0, facp->gpe0_len, "acpi"); + if (facp->pm_tmr) + request_region(facp->pm_tmr, facp->pm_tm_len, "acpi"); + if (facp->gpe0) + request_region(facp->gpe0, facp->gpe0_len, "acpi"); if (facp->gpe1) request_region(facp->gpe1, facp->gpe1_len, "acpi"); @@ -615,45 +631,243 @@ static int acpi_claim_ioports(struct acpi_facp *facp) static int acpi_release_ioports(struct acpi_facp *facp) { // we don't get a guarantee of contiguity for any of the ACPI registers - release_region(facp->pm1a_evt, facp->pm1_evt_len); + if (facp->pm1a_evt) + release_region(facp->pm1a_evt, facp->pm1_evt_len); if (facp->pm1b_evt) release_region(facp->pm1b_evt, facp->pm1_evt_len); - release_region(facp->pm1a_cnt, facp->pm1_cnt_len); + if (facp->pm1a_cnt) + release_region(facp->pm1a_cnt, facp->pm1_cnt_len); if (facp->pm1b_cnt) release_region(facp->pm1b_cnt, facp->pm1_cnt_len); - if (facp->pm2_cnt) - release_region(facp->pm2_cnt, facp->pm2_cnt_len); - release_region(facp->pm_tmr, facp->pm_tm_len); - release_region(facp->gpe0, facp->gpe0_len); + if (facp->pm_tmr) + release_region(facp->pm_tmr, facp->pm_tm_len); + if (facp->gpe0) + release_region(facp->gpe0, facp->gpe0_len); if (facp->gpe1) release_region(facp->gpe1, facp->gpe1_len); return 0; } +/* + * Examine/modify value + */ +static int acpi_do_ulong(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len) +{ + char str[2 * sizeof(unsigned long) + 4], *strend; + unsigned long val; + int size; + + if (!write) { + if (file->f_pos) { + *len = 0; + return 0; + } + + val = *(unsigned long*) ctl->data; + size = sprintf(str, "0x%08lx\n", val); + if (*len >= size) { + copy_to_user(buffer, str, size); + *len = size; + } + else + *len = 0; + } + else { + size = sizeof(str) - 1; + if (size > *len) + size = *len; + copy_from_user(str, buffer, size); + str[size] = '\0'; + val = simple_strtoul(str, &strend, 0); + if (strend == str) + return -EINVAL; + *(unsigned long*) ctl->data = val; + } + + file->f_pos += *len; + return 0; +} + +/* + * Examine/modify event register + */ +static int acpi_do_event_reg(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len) +{ + char str[2 * sizeof(u32) + 4], *strend; + u32 val, enabling; + int size; + + if (!write) { + if (file->f_pos) { + *len = 0; + return 0; + } + + val = 0; + switch (ctl->ctl_name) { + case ACPI_PM1_ENABLE: + val = acpi_read_pm1_enable(acpi_facp); + break; + case ACPI_GPE_ENABLE: + val = acpi_read_gpe_enable(acpi_facp); + break; + case ACPI_GPE_LEVEL: + val = acpi_gpe_level; + break; + } + + size = sprintf(str, "0x%08x\n", val); + if (*len >= size) { + copy_to_user(buffer, str, size); + *len = size; + } + else + *len = 0; + } + else + { + // fetch user value + size = sizeof(str) - 1; + if (size > *len) + size = *len; + copy_from_user(str, buffer, size); + str[size] = '\0'; + val = (u32) simple_strtoul(str, &strend, 0); + if (strend == str) + return -EINVAL; + + // store value in register + switch (ctl->ctl_name) { + case ACPI_PM1_ENABLE: + // clear previously disabled events + enabling = (val + & ~acpi_read_pm1_enable(acpi_facp)); + acpi_write_pm1_status(acpi_facp, enabling); + + if (val) { + // enable ACPI unless it is already + if (!acpi_is_enabled(acpi_facp)) + acpi_enable(acpi_facp); + } + else if (!acpi_read_gpe_enable(acpi_facp)) { + // disable ACPI unless it is already + if (acpi_is_enabled(acpi_facp)) + acpi_disable(acpi_facp); + } + + acpi_write_pm1_enable(acpi_facp, val); + break; + case ACPI_GPE_ENABLE: + // clear previously disabled events + enabling = (val + & ~acpi_read_gpe_enable(acpi_facp)); + while (acpi_read_gpe_status(acpi_facp) & enabling) + acpi_write_gpe_status(acpi_facp, enabling); + + if (val) { + // enable ACPI unless it is already + if (!acpi_is_enabled(acpi_facp)) + acpi_enable(acpi_facp); + } + else if (!acpi_read_pm1_enable(acpi_facp)) { + // disable ACPI unless it is already + if (acpi_is_enabled(acpi_facp)) + acpi_disable(acpi_facp); + } + + acpi_write_gpe_enable(acpi_facp, val); + break; + case ACPI_GPE_LEVEL: + acpi_gpe_level = val; + break; + } + } + + file->f_pos += *len; + return 0; +} + +/* + * Wait for next event + */ +static int acpi_do_event(ctl_table *ctl, + int write, + struct file *file, + void *buffer, + size_t *len) +{ + u32 pm1_status = 0, gpe_status = 0; + char str[4 * sizeof(u32) + 6]; + int size; + + if (write) + return -EPERM; + if (*len < sizeof(str)) { + *len = 0; + return 0; + } + + for (;;) { + unsigned long flags; + + // we need an atomic exchange here + spin_lock_irqsave(&acpi_event_lock, flags); + pm1_status = acpi_pm1_status; + acpi_pm1_status = 0; + gpe_status = acpi_gpe_status; + acpi_gpe_status = 0; + spin_unlock_irqrestore(&acpi_event_lock, flags); + + if (pm1_status || gpe_status) + break; + + // wait for an event to arrive + interruptible_sleep_on(&acpi_event_wait); + if (signal_pending(current)) + return -ERESTARTSYS; + } + + size = sprintf(str, "0x%08x 0x%08x\n", pm1_status, gpe_status); + copy_to_user(buffer, str, size); + *len = size; + file->f_pos += size; + + return 0; +} + /* * Initialize and enable ACPI */ static int __init acpi_init(void) { - if (acpi_map_tables()) + if (acpi_find_tables() && acpi_find_piix4()) { + // no ACPI tables and not PIIX4 return -ENODEV; + } - if (request_irq(acpi_facp->sci_int, - acpi_irq, - SA_INTERRUPT | SA_SHIRQ, - "acpi", - NULL)) { + if (acpi_facp->sci_int + && request_irq(acpi_facp->sci_int, + acpi_irq, + SA_INTERRUPT | SA_SHIRQ, + "acpi", + NULL)) { printk(KERN_ERR "ACPI: SCI (IRQ%d) allocation failed\n", acpi_facp->sci_int); - acpi_unmap_tables(); + acpi_destroy_tables(); return -ENODEV; } acpi_claim_ioports(acpi_facp); - - if (misc_register(&acpi_device)) - printk(KERN_ERR "ACPI: misc. register failed\n"); + acpi_sysctl = register_sysctl_table(acpi_dir_table, 1); /* * Set up the ACPI idle function. Note that we can't really @@ -664,7 +878,9 @@ static int __init acpi_init(void) if (smp_num_cpus > 1) return 0; #endif + acpi_idle = acpi_idle_handler; + return 0; } @@ -673,11 +889,16 @@ static int __init acpi_init(void) */ static void __exit acpi_exit(void) { - misc_deregister(&acpi_device); + acpi_idle = NULL; + + unregister_sysctl_table(acpi_sysctl); acpi_disable(acpi_facp); acpi_release_ioports(acpi_facp); - free_irq(acpi_facp->sci_int, NULL); - acpi_unmap_tables(); + + if (acpi_facp->sci_int) + free_irq(acpi_facp->sci_int, NULL); + + acpi_destroy_tables(); } #ifdef MODULE diff --git a/drivers/net/Config.in b/drivers/net/Config.in index d54f8fd30..0757aa349 100644 --- a/drivers/net/Config.in +++ b/drivers/net/Config.in @@ -46,6 +46,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then if [ "$CONFIG_PPC" = "y" ]; then tristate ' MACE (Power Mac ethernet) support' CONFIG_MACE tristate ' BMAC (G3 ethernet) support' CONFIG_BMAC + tristate ' Symbios 53c885 (Synergy ethernet) support' CONFIG_NCR885E fi if [ "$CONFIG_ZORRO" = "y" ]; then tristate ' Ariadne support' CONFIG_ARIADNE @@ -217,6 +218,7 @@ fi tristate 'PPP (point-to-point protocol) support' CONFIG_PPP if [ ! "$CONFIG_PPP" = "n" ]; then dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP + dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP m fi diff --git a/drivers/net/Makefile b/drivers/net/Makefile index fe9208d4d..12fbc99f3 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -299,6 +299,13 @@ CONFIG_SLHC_BUILTIN = y MX_OBJS += ppp_async.o endif endif + ifeq ($(CONFIG_PPP_SYNC_TTY),y) + LX_OBJS += ppp_synctty.o + else + ifeq ($(CONFIG_PPP_SYNC_TTY),m) + MX_OBJS += ppp_synctty.o + endif + endif ifeq ($(CONFIG_PPP_DEFLATE),y) CONFIG_PPPDEF_BUILTIN = y else @@ -316,6 +323,9 @@ else ifeq ($(CONFIG_PPP_ASYNC),m) MX_OBJS += ppp_async.o endif + ifeq ($(CONFIG_PPP_SYNC_TTY),m) + MX_OBJS += ppp_synctty.o + endif ifeq ($(CONFIG_PPP_DEFLATE),m) CONFIG_PPPDEF_MODULE = y endif @@ -1031,6 +1041,14 @@ else endif endif +ifeq ($(CONFIG_NCR885E),y) +L_OBJS += ncr885e.o +else + ifeq ($(CONFIG_NCR885E),m) + M_OBJS += ncr885e.o + endif +endif + ifeq ($(CONFIG_ADAPTEC_STARFIRE),y) L_OBJS += starfire.o else diff --git a/drivers/net/arcnet.c b/drivers/net/arcnet.c index 353b44dc8..906d3fab7 100644 --- a/drivers/net/arcnet.c +++ b/drivers/net/arcnet.c @@ -1,184 +1,184 @@ -/* $Id: arcnet.c,v 1.34 1997/11/09 11:04:55 mj Exp $ - - Written 1994-1996 by Avery Pennarun, - derived from skeleton.c by Donald Becker. - - ********************** - - The original copyright was as follows: - - skeleton.c Written 1993 by Donald Becker. - Copyright 1993 United States Government as represented by the - Director, National Security Agency. This software may only be used - and distributed according to the terms of the GNU Public License as - modified by SRC, incorporated herein by reference. - - ********************** - - v3.02 (98/06/07) - - Use register_netdevice() instead of register_netdev() to create - new devices for RFC1051 and Ethernet encapsulation in arcnet_open. - Likewise for unregistering them later. This avoids the deadlock - encountered because the original routines call rtnl_lock() when - it's already locked. [dw] - - v3.01 (98/04/17) - - Interrupt handler now also checks dev->[se]dev are non-NULL - to avoid crashes in interrupts during card init. [dw] - - v3.00 (97/11/09) - - Minor cleanup of debugging messages. [mj] - - v2.93 ALPHA (97/11/06) - - irq2dev mapping removed. - - Interrupt handler now checks whether dev->priv is non-null in order - to avoid crashes in interrupts which come during card init. [mj] - - v2.92 ALPHA (97/09/02) - - Code cleanup [Martin Mares ] - - Better probing for the COM90xx chipset, although only as - a temporary solution until we implement adding of all found - devices at once. [mj] - - v2.91 ALPHA (97/08/19) - - Add counting of octets in/out. - - v2.90 ALPHA (97/08/08) - - Add support for kernel command line parsing so that chipset - drivers are usable when compiled in. - - v2.80 ALPHA (97/08/01) - - Split source into multiple files; generic arcnet support and - individual chipset drivers. - - v2.61 ALPHA (97/07/30) by David Woodhouse (Dave@imladris.demon.co.uk) - for Nortel (Northern Telecom). - - Added support for IO-mapped modes and for SMC COM20020 chipset. - - Fixed (avoided) race condition in send_packet routines which was - discovered when the buffer copy routines got slow (?). - - Fixed support for device naming at load time. - - Added backplane, clock and timeout options for COM20020. - - Added support for promiscuous mode. - - v2.60 ALPHA (96/11/23) - - Added patch from Vojtech Pavlik - and Martin Mares to make the driver work - with the new Linux 2.1.x memory management. I modified their - patch quite a bit though; bugs are my fault. More changes should - be made to get eliminate any remaining phys_to_virt calls. - - Quietly ignore protocol id's 0, 1, 8, and 243. Thanks to Jake - Messinger for reporting these codes and their - meanings. - - Smarter shmem probe for cards with 4k mirrors. (does it work?) - - Initial support for RIM I type cards which use no I/O ports at - all. To use this option, you need to compile with RIM_I_MODE - enabled. Thanks to Kolja Waschk for explaining - RIM I programming to me. Now, does my RIM I code actually - work? - - v2.56 (96/10/18) - - Turned arc0e/arc0s startup messages back on by default, as most - people will probably not notice the additional devices - otherwise. This causes undue confusion. - - Fixed a tiny but noticeable bug in the packet debugging routines - (thanks Tomasz) - - The following has been SUMMARIZED. The complete ChangeLog is - available in the full Linux-ARCnet package at - http://www.worldvisions.ca/~apenwarr/arcnet - - v2.50 (96/02/24) - - Massively improved autoprobe routines; they now work even as a - module. Thanks to Vojtech Pavlik - for his ideas and help in this area. - - Changed printk's around quite a lot. - - v2.22 (95/12/08) - - Major cleanups, speedups, and better code-sharing. - - Eliminated/changed many useless/meaningless/scary debug messages - (and, in most cases, the bugs that caused them). - - Better IPX support. - - lp->stats updated properly. - - RECON checking now by default only prints a message if there are - excessive errors (ie. your cable is probably broken). - - New RFC1051-compliant "arc0s" virtual device by Tomasz - Motylewski. - - Excess debug messages can be compiled out to reduce code size. - - v2.00 (95/09/06) - - ARCnet RECON messages are now detected and logged as "carrier" - errors. - - The TXACK flag is now checked, and errors are logged. - - Debug levels are now completely different. See the README. - - Massive code cleanups, with several no-longer-necessary and some - completely useless options removed. - - Multiprotocol support. You can now use the "arc0e" device to - send "Ethernet-Encapsulation" packets, which are compatible with - Windows for Workgroups and LAN Manager, and possibly other - software. See the README for more information. - - v1.02 (95/06/21) - - A fix to make "exception" packets sent from Linux receivable - on other systems. (The protocol_id byte was sometimes being set - incorrectly, and Linux wasn't checking it on receive so it - didn't show up) - - v1.01 (95/03/24) - - Fixed some IPX-related bugs. (Thanks to Tomasz Motylewski - for the patches to make arcnet work - with dosemu!) - - v1.00 (95/02/15) - - Initial non-alpha release. - - - TO DO: (semi-prioritized) - - - Use cleaner "architecture-independent" shared memory access. - This is half-done in ARCnet 2.60, but still uses some - undocumented i386 stuff. (We shouldn't call phys_to_virt, - for example.) - - Allow use of RFC1051 or Ether devices without RFC1201. - - Keep separate stats for each device. - - Support "arpless" mode like NetBSD does, and as recommended - by the (obsoleted) RFC1051. - - Smarter recovery from RECON-during-transmit conditions. (ie. - retransmit immediately) - - Add support for the new 1.3.x IP header cache, and other features. - - Replace setting of debug level with the "metric" flag hack by - something that still exists. SIOCDEVPRIVATE is a good candidate, - but it would require an extra user-level utility. - - - What about cards with shared memory that can be "turned off?" - (or that have none at all, like the SMC PC500longboard) - Does this work now, with IO_MAPPED_BUFFERS? - - - Autoconfigure PDI5xxPlus cards. (I now have a PDI508Plus to play - with temporarily.) Update: yes, the Pure Data config program - for DOS works fine, but the PDI508Plus I have doesn't! :) - - ATA protocol support?? - - VINES TCP/IP encapsulation?? (info needed) - - Sources: - - Crynwr arcnet.com/arcether.com packet drivers. - - arcnet.c v0.00 dated 1/1/94 and apparently by - Donald Becker - it didn't work :) - - skeleton.c v0.05 dated 11/16/93 by Donald Becker - (from Linux Kernel 1.1.45) - - RFC's 1201 and 1051 - re: TCP/IP over ARCnet - - The official ARCnet COM9026 data sheets (!) thanks to Ken - Cornetet - - The official ARCnet COM20020 data sheets. - - Information on some more obscure ARCnet controller chips, thanks - to the nice people at SMC. - - net/inet/eth.c (from kernel 1.1.50) for header-building info. - - Alternate Linux ARCnet source by V.Shergin - - Textual information and more alternate source from Joachim Koenig - -*/ +/* $Id: arcnet.c,v 1.34 1997/11/09 11:04:55 mj Exp $ + + Written 1994-1996 by Avery Pennarun, + derived from skeleton.c by Donald Becker. + + ********************** + + The original copyright was as follows: + + skeleton.c Written 1993 by Donald Becker. + Copyright 1993 United States Government as represented by the + Director, National Security Agency. This software may only be used + and distributed according to the terms of the GNU Public License as + modified by SRC, incorporated herein by reference. + + ********************** + + v3.02 (98/06/07) + - Use register_netdevice() instead of register_netdev() to create + new devices for RFC1051 and Ethernet encapsulation in arcnet_open. + Likewise for unregistering them later. This avoids the deadlock + encountered because the original routines call rtnl_lock() when + it's already locked. [dw] + + v3.01 (98/04/17) + - Interrupt handler now also checks dev->[se]dev are non-NULL + to avoid crashes in interrupts during card init. [dw] + + v3.00 (97/11/09) + - Minor cleanup of debugging messages. [mj] + + v2.93 ALPHA (97/11/06) + - irq2dev mapping removed. + - Interrupt handler now checks whether dev->priv is non-null in order + to avoid crashes in interrupts which come during card init. [mj] + + v2.92 ALPHA (97/09/02) + - Code cleanup [Martin Mares ] + - Better probing for the COM90xx chipset, although only as + a temporary solution until we implement adding of all found + devices at once. [mj] + + v2.91 ALPHA (97/08/19) + - Add counting of octets in/out. + + v2.90 ALPHA (97/08/08) + - Add support for kernel command line parsing so that chipset + drivers are usable when compiled in. + + v2.80 ALPHA (97/08/01) + - Split source into multiple files; generic arcnet support and + individual chipset drivers. + + v2.61 ALPHA (97/07/30) by David Woodhouse (Dave@imladris.demon.co.uk) + for Nortel (Northern Telecom). + - Added support for IO-mapped modes and for SMC COM20020 chipset. + - Fixed (avoided) race condition in send_packet routines which was + discovered when the buffer copy routines got slow (?). + - Fixed support for device naming at load time. + - Added backplane, clock and timeout options for COM20020. + - Added support for promiscuous mode. + + v2.60 ALPHA (96/11/23) + - Added patch from Vojtech Pavlik + and Martin Mares to make the driver work + with the new Linux 2.1.x memory management. I modified their + patch quite a bit though; bugs are my fault. More changes should + be made to get eliminate any remaining phys_to_virt calls. + - Quietly ignore protocol id's 0, 1, 8, and 243. Thanks to Jake + Messinger for reporting these codes and their + meanings. + - Smarter shmem probe for cards with 4k mirrors. (does it work?) + - Initial support for RIM I type cards which use no I/O ports at + all. To use this option, you need to compile with RIM_I_MODE + enabled. Thanks to Kolja Waschk for explaining + RIM I programming to me. Now, does my RIM I code actually + work? + + v2.56 (96/10/18) + - Turned arc0e/arc0s startup messages back on by default, as most + people will probably not notice the additional devices + otherwise. This causes undue confusion. + - Fixed a tiny but noticeable bug in the packet debugging routines + (thanks Tomasz) + + The following has been SUMMARIZED. The complete ChangeLog is + available in the full Linux-ARCnet package at + http://www.worldvisions.ca/~apenwarr/arcnet + + v2.50 (96/02/24) + - Massively improved autoprobe routines; they now work even as a + module. Thanks to Vojtech Pavlik + for his ideas and help in this area. + - Changed printk's around quite a lot. + + v2.22 (95/12/08) + - Major cleanups, speedups, and better code-sharing. + - Eliminated/changed many useless/meaningless/scary debug messages + (and, in most cases, the bugs that caused them). + - Better IPX support. + - lp->stats updated properly. + - RECON checking now by default only prints a message if there are + excessive errors (ie. your cable is probably broken). + - New RFC1051-compliant "arc0s" virtual device by Tomasz + Motylewski. + - Excess debug messages can be compiled out to reduce code size. + + v2.00 (95/09/06) + - ARCnet RECON messages are now detected and logged as "carrier" + errors. + - The TXACK flag is now checked, and errors are logged. + - Debug levels are now completely different. See the README. + - Massive code cleanups, with several no-longer-necessary and some + completely useless options removed. + - Multiprotocol support. You can now use the "arc0e" device to + send "Ethernet-Encapsulation" packets, which are compatible with + Windows for Workgroups and LAN Manager, and possibly other + software. See the README for more information. + + v1.02 (95/06/21) + - A fix to make "exception" packets sent from Linux receivable + on other systems. (The protocol_id byte was sometimes being set + incorrectly, and Linux wasn't checking it on receive so it + didn't show up) + + v1.01 (95/03/24) + - Fixed some IPX-related bugs. (Thanks to Tomasz Motylewski + for the patches to make arcnet work + with dosemu!) + + v1.00 (95/02/15) + - Initial non-alpha release. + + + TO DO: (semi-prioritized) + + - Use cleaner "architecture-independent" shared memory access. + This is half-done in ARCnet 2.60, but still uses some + undocumented i386 stuff. (We shouldn't call phys_to_virt, + for example.) + - Allow use of RFC1051 or Ether devices without RFC1201. + - Keep separate stats for each device. + - Support "arpless" mode like NetBSD does, and as recommended + by the (obsoleted) RFC1051. + - Smarter recovery from RECON-during-transmit conditions. (ie. + retransmit immediately) + - Add support for the new 1.3.x IP header cache, and other features. + - Replace setting of debug level with the "metric" flag hack by + something that still exists. SIOCDEVPRIVATE is a good candidate, + but it would require an extra user-level utility. + + - What about cards with shared memory that can be "turned off?" + (or that have none at all, like the SMC PC500longboard) + Does this work now, with IO_MAPPED_BUFFERS? + + - Autoconfigure PDI5xxPlus cards. (I now have a PDI508Plus to play + with temporarily.) Update: yes, the Pure Data config program + for DOS works fine, but the PDI508Plus I have doesn't! :) + - ATA protocol support?? + - VINES TCP/IP encapsulation?? (info needed) + + Sources: + - Crynwr arcnet.com/arcether.com packet drivers. + - arcnet.c v0.00 dated 1/1/94 and apparently by + Donald Becker - it didn't work :) + - skeleton.c v0.05 dated 11/16/93 by Donald Becker + (from Linux Kernel 1.1.45) + - RFC's 1201 and 1051 - re: TCP/IP over ARCnet + - The official ARCnet COM9026 data sheets (!) thanks to Ken + Cornetet + - The official ARCnet COM20020 data sheets. + - Information on some more obscure ARCnet controller chips, thanks + to the nice people at SMC. + - net/inet/eth.c (from kernel 1.1.50) for header-building info. + - Alternate Linux ARCnet source by V.Shergin + - Textual information and more alternate source from Joachim Koenig + + */ static const char *version = - "arcnet.c: v3.02 98/06/07 Avery Pennarun et al.\n"; +"arcnet.c: v3.02 98/06/07 Avery Pennarun et al.\n"; #include #include @@ -230,15 +230,15 @@ static const char *version = #define ARCSTATUS ((*lp->astatus)(dev)) #define ACOMMAND(x) ((*lp->acommand)(dev, x)) -int arcnet_debug=ARCNET_DEBUG; +int arcnet_debug = ARCNET_DEBUG; /* Exported function prototypes */ #ifdef MODULE -int init_module(void); +int init_module(void); void cleanup_module(void); #else -void arcnet_init(void); +int arcnet_init(void); static int init_module(void); #ifdef CONFIG_ARCNET_COM90xx extern char com90xx_explicit; @@ -247,13 +247,13 @@ extern int arc90xx_probe(struct net_device *dev); #endif void arcnet_tx_done(struct net_device *dev, struct arcnet_local *lp); -void arcnet_use_count (int open); +void arcnet_use_count(int open); void arcnet_setup(struct net_device *dev); void arcnet_makename(char *device); void arcnetA_continue_tx(struct net_device *dev); -int arcnet_go_tx(struct net_device *dev,int enable_irq); -void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs); -void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr); +int arcnet_go_tx(struct net_device *dev, int enable_irq); +void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs); +void arcnet_rx(struct arcnet_local *lp, u_char * arcsoft, short length, int saddr, int daddr); EXPORT_SYMBOL(arcnet_debug); EXPORT_SYMBOL(arcnet_tx_done); @@ -266,32 +266,32 @@ EXPORT_SYMBOL(arcnet_interrupt); EXPORT_SYMBOL(arcnet_rx); #if ARCNET_DEBUG_MAX & D_SKB -void arcnet_dump_skb(struct net_device *dev,struct sk_buff *skb, - char *desc); +void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, + char *desc); EXPORT_SYMBOL(arcnet_dump_skb); #else -# define arcnet_dump_skb(dev,skb,desc) ; +#define arcnet_dump_skb(dev,skb,desc) ; #endif #if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX) -void arcnet_dump_packet(struct net_device *dev,u_char *buffer,int ext, - char *desc); +void arcnet_dump_packet(struct net_device *dev, u_char * buffer, int ext, + char *desc); EXPORT_SYMBOL(arcnet_dump_packet); #else -# define arcnet_dump_packet(dev,buffer,ext,desc) ; +#define arcnet_dump_packet(dev,buffer,ext,desc) ; #endif /* Internal function prototypes */ static int arcnet_open(struct net_device *dev); static int arcnet_close(struct net_device *dev); -static int arcnetA_header(struct sk_buff *skb,struct net_device *dev, - unsigned short type,void *daddr,void *saddr,unsigned len); +static int arcnetA_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, void *daddr, void *saddr, unsigned len); static int arcnetA_rebuild_header(struct sk_buff *skb); -static int arcnet_send_packet_bad(struct sk_buff *skb,struct net_device *dev); +static int arcnet_send_packet_bad(struct sk_buff *skb, struct net_device *dev); static int arcnetA_send_packet(struct sk_buff *skb, struct net_device *dev); -static void arcnetA_rx(struct net_device *dev,u_char *buf, - int length,u_char saddr, u_char daddr); +static void arcnetA_rx(struct net_device *dev, u_char * buf, + int length, u_char saddr, u_char daddr); static struct net_device_stats *arcnet_get_stats(struct net_device *dev); static unsigned short arcnetA_type_trans(struct sk_buff *skb, struct net_device *dev); @@ -302,8 +302,8 @@ static unsigned short arcnetA_type_trans(struct sk_buff *skb, static int arcnetE_init(struct net_device *dev); static int arcnetE_open_close(struct net_device *dev); static int arcnetE_send_packet(struct sk_buff *skb, struct net_device *dev); -static void arcnetE_rx(struct net_device *dev,u_char *arcsoft, - int length,u_char saddr, u_char daddr); +static void arcnetE_rx(struct net_device *dev, u_char * arcsoft, + int length, u_char saddr, u_char daddr); #endif @@ -312,12 +312,12 @@ static void arcnetE_rx(struct net_device *dev,u_char *arcsoft, static int arcnetS_init(struct net_device *dev); static int arcnetS_open_close(struct net_device *dev); static int arcnetS_send_packet(struct sk_buff *skb, struct net_device *dev); -static void arcnetS_rx(struct net_device *dev,u_char *buf, - int length,u_char saddr, u_char daddr); -static int arcnetS_header(struct sk_buff *skb,struct net_device *dev, - unsigned short type,void *daddr,void *saddr,unsigned len); +static void arcnetS_rx(struct net_device *dev, u_char * buf, + int length, u_char saddr, u_char daddr); +static int arcnetS_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, void *daddr, void *saddr, unsigned len); static int arcnetS_rebuild_header(struct sk_buff *skb); -static unsigned short arcnetS_type_trans(struct sk_buff *skb,struct net_device *dev); +static unsigned short arcnetS_type_trans(struct sk_buff *skb, struct net_device *dev); #endif @@ -330,22 +330,21 @@ static unsigned short arcnetS_type_trans(struct sk_buff *skb,struct net_device * /* Dump the contents of an sk_buff */ #if ARCNET_DEBUG_MAX & D_SKB -void arcnet_dump_skb(struct net_device *dev,struct sk_buff *skb,char *desc) +void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc) { int i; long flags; save_flags(flags); cli(); - printk(KERN_DEBUG "%6s: skb dump (%s) follows:",dev->name,desc); - for(i=0; ilen; i++) - { - if (i%16==0) - printk("\n" KERN_DEBUG "[%04X] ",i); - printk("%02X ",((u_char *)skb->data)[i]); + printk(KERN_DEBUG "%6s: skb dump (%s) follows:", dev->name, desc); + for (i = 0; i < skb->len; i++) { + if (i % 16 == 0) + printk("\n" KERN_DEBUG "[%04X] ", i); + printk("%02X ", ((u_char *) skb->data)[i]); } - printk("\n"); - restore_flags(flags); + printk("\n"); + restore_flags(flags); } #endif @@ -353,19 +352,18 @@ void arcnet_dump_skb(struct net_device *dev,struct sk_buff *skb,char *desc) /* Dump the contents of an ARCnet buffer */ #if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX) -void arcnet_dump_packet(struct net_device *dev,u_char *buffer,int ext,char *desc) +void arcnet_dump_packet(struct net_device *dev, u_char * buffer, int ext, char *desc) { int i; long flags; save_flags(flags); cli(); - printk(KERN_DEBUG "%6s: packet dump (%s) follows:",dev->name,desc); - for (i=0; i<256+(ext!=0)*256; i++) - { - if (i%16==0) - printk("\n" KERN_DEBUG "[%04X] ",i); - printk("%02X ",buffer[i]); + printk(KERN_DEBUG "%6s: packet dump (%s) follows:", dev->name, desc); + for (i = 0; i < 256 + (ext != 0) * 256; i++) { + if (i % 16 == 0) + printk("\n" KERN_DEBUG "[%04X] ", i); + printk("%02X ", buffer[i]); } printk("\n"); restore_flags(flags); @@ -386,24 +384,24 @@ void arcnet_setup(struct net_device *dev) { dev_init_buffers(dev); - dev->broadcast[0] = 0x00; /* for us, broadcasts are address 0 */ - dev->addr_len = 1; - dev->type = ARPHRD_ARCNET; - dev->tx_queue_len = 30; + dev->broadcast[0] = 0x00; /* for us, broadcasts are address 0 */ + dev->addr_len = 1; + dev->type = ARPHRD_ARCNET; + dev->tx_queue_len = 30; /* New-style flags. */ - dev->flags = IFF_BROADCAST; + dev->flags = IFF_BROADCAST; /* Put in this stuff here, so we don't have to export the symbols * to the chipset drivers. */ - dev->open=arcnet_open; - dev->stop=arcnet_close; - dev->hard_start_xmit=arcnetA_send_packet; - dev->get_stats=arcnet_get_stats; - dev->hard_header=arcnetA_header; - dev->rebuild_header=arcnetA_rebuild_header; + dev->open = arcnet_open; + dev->stop = arcnet_close; + dev->hard_start_xmit = arcnetA_send_packet; + dev->get_stats = arcnet_get_stats; + dev->hard_header = arcnetA_header; + dev->rebuild_header = arcnetA_rebuild_header; } @@ -420,167 +418,164 @@ void arcnet_setup(struct net_device *dev) * registers that "should" only need to be set once at boot, so that * there is non-reboot way to recover if something goes wrong. */ -static int -arcnet_open(struct net_device *dev) +static int arcnet_open(struct net_device *dev) { - struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - - /* if (dev->metric>=1000) - * { - * arcnet_debug=dev->metric-1000; - * printk(KERN_INFO "%6s: debug level set to %d\n",dev->name,arcnet_debug); - * dev->metric=1; - *} - */ - BUGMSG(D_INIT,"arcnet_open: resetting card.\n"); - - /* try to put the card in a defined state - if it fails the first - * time, actually reset it. - */ - if ((*lp->arcnet_reset)(dev,0) && (*lp->arcnet_reset)(dev,1)) - return -ENODEV; - - dev->tbusy=0; - dev->interrupt=0; - lp->intx=0; - lp->in_txhandler=0; - - /* The RFC1201 driver is the default - just store */ - lp->adev=dev; - - /* we're started */ - dev->start=1; + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + + /* if (dev->metric>=1000) + * { + * arcnet_debug=dev->metric-1000; + * printk(KERN_INFO "%6s: debug level set to %d\n",dev->name,arcnet_debug); + * dev->metric=1; + *} + */ + BUGMSG(D_INIT, "arcnet_open: resetting card.\n"); + + /* try to put the card in a defined state - if it fails the first + * time, actually reset it. + */ + if ((*lp->arcnet_reset) (dev, 0) && (*lp->arcnet_reset) (dev, 1)) + return -ENODEV; + + dev->tbusy = 0; + dev->interrupt = 0; + lp->intx = 0; + lp->in_txhandler = 0; + + /* The RFC1201 driver is the default - just store */ + lp->adev = dev; + + /* we're started */ + dev->start = 1; #ifdef CONFIG_ARCNET_ETH - /* Initialize the ethernet-encap protocol driver */ - lp->edev=(struct net_device *)kmalloc(sizeof(struct net_device),GFP_KERNEL); - if (lp->edev == NULL) - return -ENOMEM; - memcpy(lp->edev,dev,sizeof(struct net_device)); - lp->edev->type=ARPHRD_ETHER; - lp->edev->name=(char *)kmalloc(10,GFP_KERNEL); - if (lp->edev->name == NULL) { - kfree(lp->edev); - lp->edev = NULL; - return -ENOMEM; - } - sprintf(lp->edev->name,"%se",dev->name); - lp->edev->init=arcnetE_init; - register_netdevice(lp->edev); + /* Initialize the ethernet-encap protocol driver */ + lp->edev = (struct net_device *) kmalloc(sizeof(struct net_device), GFP_KERNEL); + if (lp->edev == NULL) + return -ENOMEM; + memcpy(lp->edev, dev, sizeof(struct net_device)); + lp->edev->type = ARPHRD_ETHER; + lp->edev->name = (char *) kmalloc(10, GFP_KERNEL); + if (lp->edev->name == NULL) { + kfree(lp->edev); + lp->edev = NULL; + return -ENOMEM; + } + sprintf(lp->edev->name, "%se", dev->name); + lp->edev->init = arcnetE_init; + register_netdevice(lp->edev); #endif #ifdef CONFIG_ARCNET_1051 - /* Initialize the RFC1051-encap protocol driver */ - lp->sdev=(struct net_device *)kmalloc(sizeof(struct net_device)+10,GFP_KERNEL); - if(lp->sdev == NULL) - { + /* Initialize the RFC1051-encap protocol driver */ + lp->sdev = (struct net_device *) kmalloc(sizeof(struct net_device) + 10, GFP_KERNEL); + if (lp->sdev == NULL) { #ifdef CONFIG_ARCNET_ETH - if(lp->edev) - kfree(lp->edev); - lp->edev=NULL; - return -ENOMEM; -#endif - } - memcpy(lp->sdev,dev,sizeof(struct net_device)); - lp->sdev->name=(char *)(lp+1); - sprintf(lp->sdev->name,"%ss",dev->name); - lp->sdev->init=arcnetS_init; - register_netdevice(lp->sdev); + if (lp->edev) + kfree(lp->edev); + lp->edev = NULL; + return -ENOMEM; +#endif + } + memcpy(lp->sdev, dev, sizeof(struct net_device)); + lp->sdev->name = (char *) (lp + 1); + sprintf(lp->sdev->name, "%ss", dev->name); + lp->sdev->init = arcnetS_init; + register_netdevice(lp->sdev); #endif - /* Enable TX if we need to */ - if (lp->en_dis_able_TX) - (*lp->en_dis_able_TX)(dev, 1); + /* Enable TX if we need to */ + if (lp->en_dis_able_TX) + (*lp->en_dis_able_TX) (dev, 1); - /* make sure we're ready to receive IRQ's. - * arcnet_reset sets this for us, but if we receive one before - * START is set to 1, it could be ignored. So, we turn IRQ's - * off, then on again to clean out the IRQ controller. - */ + /* make sure we're ready to receive IRQ's. + * arcnet_reset sets this for us, but if we receive one before + * START is set to 1, it could be ignored. So, we turn IRQ's + * off, then on again to clean out the IRQ controller. + */ - AINTMASK(0); - udelay(1); /* give it time to set the mask before - * we reset it again. (may not even be - * necessary) - */ - SETMASK; + AINTMASK(0); + udelay(1); /* give it time to set the mask before + * we reset it again. (may not even be + * necessary) + */ + SETMASK; - /* Let it increase its use count */ - (*lp->openclose_device)(1); + /* Let it increase its use count */ + (*lp->openclose_device) (1); - return 0; + return 0; } /* The inverse routine to arcnet_open - shuts down the card. */ -static int -arcnet_close(struct net_device *dev) +static int arcnet_close(struct net_device *dev) { - struct arcnet_local *lp = (struct arcnet_local *)dev->priv; + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; - if (test_and_set_bit(0, (int *)&dev->tbusy)) - BUGMSG(D_NORMAL, "arcnet_close: tbusy already set!\n"); + if (test_and_set_bit(0, (int *) &dev->tbusy)) + BUGMSG(D_NORMAL, "arcnet_close: tbusy already set!\n"); - dev->start=0; + dev->start = 0; #ifdef CONFIG_ARCNET_1051 - lp->sdev->tbusy=1; - lp->sdev->start=0; + lp->sdev->tbusy = 1; + lp->sdev->start = 0; #endif #ifdef CONFIG_ARCNET_ETH - lp->edev->tbusy=1; - lp->edev->start=0; + lp->edev->tbusy = 1; + lp->edev->start = 0; #endif - /* Shut down the card */ + /* Shut down the card */ - /* Disable TX if we need to */ - if (lp->en_dis_able_TX) - (*lp->en_dis_able_TX)(dev, 0); + /* Disable TX if we need to */ + if (lp->en_dis_able_TX) + (*lp->en_dis_able_TX) (dev, 0); - (*lp->arcnet_reset)(dev, 3); /* reset IRQ won't run if START=0 */ + (*lp->arcnet_reset) (dev, 3); /* reset IRQ won't run if START=0 */ #if 0 - lp->intmask=0; - SETMASK; /* no IRQ's (except RESET, of course) */ - ACOMMAND(NOTXcmd); /* stop transmit */ - ACOMMAND(NORXcmd); /* disable receive */ + lp->intmask = 0; + SETMASK; /* no IRQ's (except RESET, of course) */ + ACOMMAND(NOTXcmd); /* stop transmit */ + ACOMMAND(NORXcmd); /* disable receive */ #endif - /* reset more flags */ - dev->interrupt=0; + /* reset more flags */ + dev->interrupt = 0; #ifdef CONFIG_ARCNET_ETH - lp->edev->interrupt=0; + lp->edev->interrupt = 0; #endif #ifdef CONFIG_ARCNET_1051 - lp->sdev->interrupt=0; + lp->sdev->interrupt = 0; #endif - /* do NOT free lp->adev!! It's static! */ - lp->adev=NULL; + /* do NOT free lp->adev!! It's static! */ + lp->adev = NULL; #ifdef CONFIG_ARCNET_ETH - /* free the ethernet-encap protocol device */ - lp->edev->priv=NULL; - unregister_netdevice(lp->edev); - kfree(lp->edev->name); - kfree(lp->edev); - lp->edev=NULL; + /* free the ethernet-encap protocol device */ + lp->edev->priv = NULL; + unregister_netdevice(lp->edev); + kfree(lp->edev->name); + kfree(lp->edev); + lp->edev = NULL; #endif #ifdef CONFIG_ARCNET_1051 - /* free the RFC1051-encap protocol device */ - lp->sdev->priv=NULL; - unregister_netdevice(lp->sdev); - kfree(lp->sdev); - lp->sdev=NULL; + /* free the RFC1051-encap protocol device */ + lp->sdev->priv = NULL; + unregister_netdevice(lp->sdev); + kfree(lp->sdev); + lp->sdev = NULL; #endif - /* Update the statistics here. (not necessary in ARCnet) */ + /* Update the statistics here. (not necessary in ARCnet) */ - /* Decrease the use count */ - (*lp->openclose_device)(0); + /* Decrease the use count */ + (*lp->openclose_device) (0); - return 0; + return 0; } @@ -592,241 +587,213 @@ arcnet_close(struct net_device *dev) /* Generic error checking routine for arcnet??_send_packet */ -static int -arcnet_send_packet_bad(struct sk_buff *skb, struct net_device *dev) +static int arcnet_send_packet_bad(struct sk_buff *skb, struct net_device *dev) { - struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - - BUGMSG(D_DURING,"transmit requested (status=%Xh, inTX=%d)\n", - ARCSTATUS,lp->intx); - - if (lp->in_txhandler) - { - BUGMSG(D_NORMAL,"send_packet called while in txhandler!\n"); - lp->stats.tx_dropped++; - return 1; - } - - if (lp->intx>1) - { - BUGMSG(D_NORMAL,"send_packet called while intx!\n"); - lp->stats.tx_dropped++; - return 1; - } - - if (test_bit(0, (int *)&dev->tbusy)) - { - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ - int tickssofar = jiffies - dev->trans_start; - - int status=ARCSTATUS; - - if (tickssofar < TX_TIMEOUT) - { - BUGMSG(D_DURING,"premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d\n", - status,tickssofar,lp->outgoing.skb, - lp->outgoing.numsegs, - lp->outgoing.segnum); - return 1; - } + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; - lp->intmask &= ~TXFREEflag; - SETMASK; + BUGMSG(D_DURING, "transmit requested (status=%Xh, inTX=%d)\n", + ARCSTATUS, lp->intx); - if (status&TXFREEflag) /* transmit _DID_ finish */ - { - BUGMSG(D_NORMAL,"tx timeout - missed IRQ? (status=%Xh, ticks=%d, mask=%Xh, dest=%02Xh)\n", - status,tickssofar,lp->intmask,lp->lasttrans_dest); - lp->stats.tx_errors++; + if (lp->in_txhandler) { + BUGMSG(D_NORMAL, "send_packet called while in txhandler!\n"); + lp->stats.tx_dropped++; + return 1; } - else - { - BUGMSG(D_EXTRA,"tx timed out (status=%Xh, tickssofar=%d, intmask=%Xh, dest=%02Xh)\n", - status,tickssofar,lp->intmask,lp->lasttrans_dest); - lp->stats.tx_errors++; - lp->stats.tx_aborted_errors++; - - ACOMMAND(NOTXcmd); + if (lp->intx > 1) { + BUGMSG(D_NORMAL, "send_packet called while intx!\n"); + lp->stats.tx_dropped++; + return 1; } + if (test_bit(0, (int *) &dev->tbusy)) { + /* If we get here, some higher level has decided we are broken. + There should really be a "kick me" function call instead. */ + int tickssofar = jiffies - dev->trans_start; + + int status = ARCSTATUS; + + if (tickssofar < TX_TIMEOUT) { + BUGMSG(D_DURING, "premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d\n", + status, tickssofar, lp->outgoing.skb, + lp->outgoing.numsegs, + lp->outgoing.segnum); + return 1; + } + lp->intmask &= ~TXFREEflag; + SETMASK; + + if (status & TXFREEflag) { /* transmit _DID_ finish */ + BUGMSG(D_NORMAL, "tx timeout - missed IRQ? (status=%Xh, ticks=%d, mask=%Xh, dest=%02Xh)\n", + status, tickssofar, lp->intmask, lp->lasttrans_dest); + lp->stats.tx_errors++; + } else { + BUGMSG(D_EXTRA, "tx timed out (status=%Xh, tickssofar=%d, intmask=%Xh, dest=%02Xh)\n", + status, tickssofar, lp->intmask, lp->lasttrans_dest); + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + + ACOMMAND(NOTXcmd); + } - if (lp->outgoing.skb) - { - dev_kfree_skb(lp->outgoing.skb); - lp->stats.tx_dropped++; - } - lp->outgoing.skb=NULL; + if (lp->outgoing.skb) { + dev_kfree_skb(lp->outgoing.skb); + lp->stats.tx_dropped++; + } + lp->outgoing.skb = NULL; #ifdef CONFIG_ARCNET_ETH - lp->edev->tbusy=0; + lp->edev->tbusy = 0; #endif #ifdef CONFIG_ARCNET_1051 - lp->sdev->tbusy=0; + lp->sdev->tbusy = 0; #endif - if (!test_and_clear_bit(0,(int *)&dev->tbusy)) - BUGMSG(D_EXTRA, "after timing out, tbusy was clear!\n"); - - lp->txready=0; - lp->sending=0; - - return 1; - } - - if (lp->txready) /* transmit already in progress! */ - { - BUGMSG(D_NORMAL,"trying to start new packet while busy! (status=%Xh)\n", - ARCSTATUS); - lp->intmask &= ~TXFREEflag; - SETMASK; - ACOMMAND(NOTXcmd); /* abort current send */ - (*lp->inthandler)(dev); /* fake an interrupt */ - lp->stats.tx_errors++; - lp->stats.tx_fifo_errors++; - lp->txready=0; /* we definitely need this line! */ - - return 1; - } - - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (int *)&lp->adev->tbusy)) - { - BUGMSG(D_NORMAL,"transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n", - ARCSTATUS,lp->intx,jiffies-dev->trans_start); - lp->stats.tx_errors++; - lp->stats.tx_fifo_errors++; - return -EBUSY; - } + if (!test_and_clear_bit(0, (int *) &dev->tbusy)) + BUGMSG(D_EXTRA, "after timing out, tbusy was clear!\n"); + + lp->txready = 0; + lp->sending = 0; + + return 1; + } + if (lp->txready) { /* transmit already in progress! */ + BUGMSG(D_NORMAL, "trying to start new packet while busy! (status=%Xh)\n", + ARCSTATUS); + lp->intmask &= ~TXFREEflag; + SETMASK; + ACOMMAND(NOTXcmd); /* abort current send */ + (*lp->inthandler) (dev); /* fake an interrupt */ + lp->stats.tx_errors++; + lp->stats.tx_fifo_errors++; + lp->txready = 0; /* we definitely need this line! */ + + return 1; + } + /* Block a timer-based transmit from overlapping. This could better be + done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ + if (test_and_set_bit(0, (int *) &lp->adev->tbusy)) { + BUGMSG(D_NORMAL, "transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n", + ARCSTATUS, lp->intx, jiffies - dev->trans_start); + lp->stats.tx_errors++; + lp->stats.tx_fifo_errors++; + return -EBUSY; + } #ifdef CONFIG_ARCNET_1051 - lp->sdev->tbusy=1; + lp->sdev->tbusy = 1; #endif #ifdef CONFIG_ARCNET_ETH - lp->edev->tbusy=1; + lp->edev->tbusy = 1; #endif - return 0; + return 0; } /* Called by the kernel in order to transmit a packet. */ -static int -arcnetA_send_packet(struct sk_buff *skb, struct net_device *dev) +static int arcnetA_send_packet(struct sk_buff *skb, struct net_device *dev) { - struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - int bad,oldmask=0; - struct Outgoing *out=&(lp->outgoing); - - lp->intx++; - - oldmask |= lp->intmask; - lp->intmask=0; - SETMASK; - - bad=arcnet_send_packet_bad(skb,dev); - if (bad) - { - lp->intx--; - lp->intmask=oldmask; - SETMASK; - return bad; - } - - /* arcnet_send_packet_pad has already set tbusy - don't bother here. */ - - lp->intmask = oldmask & ~TXFREEflag; - SETMASK; - - out->length = 1 < skb->len ? skb->len : 1; - out->hdr=(struct ClientData*)skb->data; - out->skb=skb; - - BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx"); - - out->hdr->sequence=(lp->sequence++); - - /* fits in one packet? */ - if (out->length-EXTRA_CLIENTDATA<=XMTU) - { - BUGMSG(D_DURING,"not splitting %d-byte packet. (split_flag=%d)\n", - out->length,out->hdr->split_flag); - if (out->hdr->split_flag) - BUGMSG(D_NORMAL,"short packet has split_flag set?! (split_flag=%d)\n", - out->hdr->split_flag); - out->numsegs=1; - out->segnum=1; - (*lp->prepare_tx)(dev, - ((char *)out->hdr)+EXTRA_CLIENTDATA, - sizeof(struct ClientData)-EXTRA_CLIENTDATA, - ((char *)skb->data)+sizeof(struct ClientData), - out->length-sizeof(struct ClientData), - out->hdr->daddr,1,0); - - /* done right away */ - lp->stats.tx_bytes += out->skb->len; - dev_kfree_skb(out->skb); - out->skb=NULL; - - if (arcnet_go_tx(dev,1)) - { - /* inform upper layers */ - arcnet_tx_done(dev, lp); - } - } - else /* too big for one - split it */ - { - int maxsegsize=XMTU-4; - - out->data=(u_char *)skb->data - + sizeof(struct ClientData); - out->dataleft=out->length-sizeof(struct ClientData); - out->numsegs=(out->dataleft+maxsegsize-1)/maxsegsize; - out->segnum=0; - - BUGMSG(D_TX,"packet (%d bytes) split into %d fragments:\n", - out->length,out->numsegs); - - /* if a packet waiting, launch it */ - arcnet_go_tx(dev,1); - - if (!lp->txready) - { - /* prepare a packet, launch it and prepare - * another. - */ - arcnetA_continue_tx(dev); - if (arcnet_go_tx(dev,1)) - { - arcnetA_continue_tx(dev); - arcnet_go_tx(dev,1); - } + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + int bad, oldmask = 0; + struct Outgoing *out = &(lp->outgoing); + + lp->intx++; + + oldmask |= lp->intmask; + lp->intmask = 0; + SETMASK; + + bad = arcnet_send_packet_bad(skb, dev); + if (bad) { + lp->intx--; + lp->intmask = oldmask; + SETMASK; + return bad; } + /* arcnet_send_packet_pad has already set tbusy - don't bother here. */ + + lp->intmask = oldmask & ~TXFREEflag; + SETMASK; - /* if segnum==numsegs, the transmission is finished; - * free the skb right away. - */ - - if (out->segnum==out->numsegs) - { - /* transmit completed */ - out->segnum++; - if (out->skb) - { - lp->stats.tx_bytes += skb->len; - dev_kfree_skb(out->skb); - } - out->skb=NULL; + out->length = 1 < skb->len ? skb->len : 1; + out->hdr = (struct ClientData *) skb->data; + out->skb = skb; + + BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "tx"); + + out->hdr->sequence = (lp->sequence++); + + /* fits in one packet? */ + if (out->length - EXTRA_CLIENTDATA <= XMTU) { + BUGMSG(D_DURING, "not splitting %d-byte packet. (split_flag=%d)\n", + out->length, out->hdr->split_flag); + if (out->hdr->split_flag) + BUGMSG(D_NORMAL, "short packet has split_flag set?! (split_flag=%d)\n", + out->hdr->split_flag); + out->numsegs = 1; + out->segnum = 1; + (*lp->prepare_tx) (dev, + ((char *) out->hdr) + EXTRA_CLIENTDATA, + sizeof(struct ClientData) - EXTRA_CLIENTDATA, + ((char *) skb->data) + sizeof(struct ClientData), + out->length - sizeof(struct ClientData), + out->hdr->daddr, 1, 0); + + /* done right away */ + lp->stats.tx_bytes += out->skb->len; + dev_kfree_skb(out->skb); + out->skb = NULL; + + if (arcnet_go_tx(dev, 1)) { + /* inform upper layers */ + arcnet_tx_done(dev, lp); + } + } else { /* too big for one - split it */ + int maxsegsize = XMTU - 4; + + out->data = (u_char *) skb->data + + sizeof(struct ClientData); + out->dataleft = out->length - sizeof(struct ClientData); + out->numsegs = (out->dataleft + maxsegsize - 1) / maxsegsize; + out->segnum = 0; + + BUGMSG(D_TX, "packet (%d bytes) split into %d fragments:\n", + out->length, out->numsegs); + + /* if a packet waiting, launch it */ + arcnet_go_tx(dev, 1); + + if (!lp->txready) { + /* prepare a packet, launch it and prepare + * another. + */ + arcnetA_continue_tx(dev); + if (arcnet_go_tx(dev, 1)) { + arcnetA_continue_tx(dev); + arcnet_go_tx(dev, 1); + } + } + /* if segnum==numsegs, the transmission is finished; + * free the skb right away. + */ + + if (out->segnum == out->numsegs) { + /* transmit completed */ + out->segnum++; + if (out->skb) { + lp->stats.tx_bytes += skb->len; + dev_kfree_skb(out->skb); + } + out->skb = NULL; + } } - } - dev->trans_start=jiffies; - lp->intx--; + dev->trans_start = jiffies; + lp->intx--; - /* make sure we didn't ignore a TX IRQ while we were in here */ - lp->intmask |= TXFREEflag; - SETMASK; + /* make sure we didn't ignore a TX IRQ while we were in here */ + lp->intmask |= TXFREEflag; + SETMASK; - return 0; + return 0; } @@ -836,44 +803,41 @@ arcnetA_send_packet(struct sk_buff *skb, struct net_device *dev) */ void arcnetA_continue_tx(struct net_device *dev) { - struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - int maxsegsize=XMTU-4; - struct Outgoing *out=&(lp->outgoing); - - BUGMSG(D_DURING,"continue_tx called (status=%Xh, intx=%d, intxh=%d, intmask=%Xh\n", - ARCSTATUS,lp->intx,lp->in_txhandler,lp->intmask); - - if (lp->txready) - { - BUGMSG(D_NORMAL,"continue_tx: called with packet in buffer!\n"); - return; - } - - if (out->segnum>=out->numsegs) - { - BUGMSG(D_NORMAL,"continue_tx: building segment %d of %d!\n", - out->segnum+1,out->numsegs); - } - - if (!out->segnum) /* first packet */ - out->hdr->split_flag=((out->numsegs-2)<<1)+1; - else - out->hdr->split_flag=out->segnum<<1; - - out->seglen=maxsegsize; - if (out->seglen>out->dataleft) out->seglen=out->dataleft; - - BUGMSG(D_TX,"building packet #%d (%d bytes) of %d (%d total), splitflag=%d\n", - out->segnum+1,out->seglen,out->numsegs, - out->length,out->hdr->split_flag); - - (*lp->prepare_tx)(dev,((char *)out->hdr)+EXTRA_CLIENTDATA, - sizeof(struct ClientData)-EXTRA_CLIENTDATA, - out->data,out->seglen,out->hdr->daddr,1,0); - - out->dataleft-=out->seglen; - out->data+=out->seglen; - out->segnum++; + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + int maxsegsize = XMTU - 4; + struct Outgoing *out = &(lp->outgoing); + + BUGMSG(D_DURING, "continue_tx called (status=%Xh, intx=%d, intxh=%d, intmask=%Xh\n", + ARCSTATUS, lp->intx, lp->in_txhandler, lp->intmask); + + if (lp->txready) { + BUGMSG(D_NORMAL, "continue_tx: called with packet in buffer!\n"); + return; + } + if (out->segnum >= out->numsegs) { + BUGMSG(D_NORMAL, "continue_tx: building segment %d of %d!\n", + out->segnum + 1, out->numsegs); + } + if (!out->segnum) /* first packet */ + out->hdr->split_flag = ((out->numsegs - 2) << 1) + 1; + else + out->hdr->split_flag = out->segnum << 1; + + out->seglen = maxsegsize; + if (out->seglen > out->dataleft) + out->seglen = out->dataleft; + + BUGMSG(D_TX, "building packet #%d (%d bytes) of %d (%d total), splitflag=%d\n", + out->segnum + 1, out->seglen, out->numsegs, + out->length, out->hdr->split_flag); + + (*lp->prepare_tx) (dev, ((char *) out->hdr) + EXTRA_CLIENTDATA, + sizeof(struct ClientData) - EXTRA_CLIENTDATA, + out->data, out->seglen, out->hdr->daddr, 1, 0); + + out->dataleft -= out->seglen; + out->data += out->seglen; + out->segnum++; } @@ -887,36 +851,34 @@ void arcnetA_continue_tx(struct net_device *dev) * to the card; TXFREEflag is always OR'ed into the memory variable either * way. */ -int arcnet_go_tx(struct net_device *dev,int enable_irq) +int arcnet_go_tx(struct net_device *dev, int enable_irq) { - struct arcnet_local *lp=(struct arcnet_local *)dev->priv; + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; - BUGMSG(D_DURING,"go_tx: status=%Xh, intmask=%Xh, txready=%d, sending=%d\n", - ARCSTATUS,lp->intmask,lp->txready,lp->sending); + BUGMSG(D_DURING, "go_tx: status=%Xh, intmask=%Xh, txready=%d, sending=%d\n", + ARCSTATUS, lp->intmask, lp->txready, lp->sending); - if (lp->sending || !lp->txready) - { - if (enable_irq && lp->sending) - { + if (lp->sending || !lp->txready) { + if (enable_irq && lp->sending) { lp->intmask |= TXFREEflag; SETMASK; } return 0; } - /* start sending */ - ACOMMAND(TXcmd|(lp->txready<<3)); + ACOMMAND(TXcmd | (lp->txready << 3)); lp->stats.tx_packets++; - lp->txready=0; + lp->txready = 0; lp->sending++; - lp->lasttrans_dest=lp->lastload_dest; - lp->lastload_dest=0; + lp->lasttrans_dest = lp->lastload_dest; + lp->lastload_dest = 0; lp->intmask |= TXFREEflag; - if (enable_irq) SETMASK; + if (enable_irq) + SETMASK; return 1; } @@ -933,85 +895,75 @@ int arcnet_go_tx(struct net_device *dev,int enable_irq) * interrupts. Establish which device needs attention, and call the correct * chipset interrupt handler. */ -void -arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs) +void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; struct arcnet_local *lp; - if (dev==NULL) - { - BUGMSG(D_DURING, "arcnet: irq %d for unknown device.\n", irq); - return; - } - - BUGMSG(D_DURING,"in arcnet_interrupt\n"); - - lp=(struct arcnet_local *)dev->priv; - if (!lp) - { - BUGMSG(D_DURING, "arcnet: irq ignored.\n"); - return; - } + if (dev == NULL) { + BUGMSG(D_DURING, "arcnet: irq %d for unknown device.\n", irq); + return; + } + BUGMSG(D_DURING, "in arcnet_interrupt\n"); + lp = (struct arcnet_local *) dev->priv; + if (!lp) { + BUGMSG(D_DURING, "arcnet: irq ignored.\n"); + return; + } /* RESET flag was enabled - if !dev->start, we must clear it right * away (but nothing else) since inthandler() is never called. */ - if (!dev->start) - { - if (ARCSTATUS & RESETflag) - ACOMMAND(CFLAGScmd|RESETclear); - return; - } - - - if (test_and_set_bit(0, (int *)&dev->interrupt)) - { - BUGMSG(D_NORMAL,"DRIVER PROBLEM! Nested arcnet interrupts!\n"); - return; /* don't even try. */ - } + if (!dev->start) { + if (ARCSTATUS & RESETflag) + ACOMMAND(CFLAGScmd | RESETclear); + return; + } + if (test_and_set_bit(0, (int *) &dev->interrupt)) { + BUGMSG(D_NORMAL, "DRIVER PROBLEM! Nested arcnet interrupts!\n"); + return; /* don't even try. */ + } #ifdef CONFIG_ARCNET_1051 if (lp->sdev) - lp->sdev->interrupt=1; + lp->sdev->interrupt = 1; #endif #ifdef CONFIG_ARCNET_ETH if (lp->edev) - lp->edev->interrupt=1; + lp->edev->interrupt = 1; #endif /* Call the "real" interrupt handler. */ - (*lp->inthandler)(dev); + (*lp->inthandler) (dev); #ifdef CONFIG_ARCNET_ETH if (lp->edev) - lp->edev->interrupt=0; + lp->edev->interrupt = 0; #endif #ifdef CONFIG_ARCNET_1051 if (lp->sdev) - lp->sdev->interrupt=0; + lp->sdev->interrupt = 0; #endif - if (!test_and_clear_bit(0, (int *)&dev->interrupt)) - BUGMSG(D_NORMAL, "Someone cleared our dev->interrupt flag!\n"); + if (!test_and_clear_bit(0, (int *) &dev->interrupt)) + BUGMSG(D_NORMAL, "Someone cleared our dev->interrupt flag!\n"); } void arcnet_tx_done(struct net_device *dev, struct arcnet_local *lp) { - if (dev->tbusy) - { + if (dev->tbusy) { #ifdef CONFIG_ARCNET_ETH - lp->edev->tbusy=0; + lp->edev->tbusy = 0; #endif #ifdef CONFIG_ARCNET_1051 - lp->sdev->tbusy=0; + lp->sdev->tbusy = 0; #endif - if (!test_and_clear_bit(0, (int *)&dev->tbusy)) - BUGMSG(D_NORMAL, "In arcnet_tx_done: Someone cleared our dev->tbusy" - " flag!\n"); + if (!test_and_clear_bit(0, (int *) &dev->tbusy)) + BUGMSG(D_NORMAL, "In arcnet_tx_done: Someone cleared our dev->tbusy" + " flag!\n"); - mark_bh(NET_BH); - } + mark_bh(NET_BH); + } } @@ -1026,53 +978,52 @@ void arcnet_tx_done(struct net_device *dev, struct arcnet_local *lp) * protocol ID found. */ -void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr) +void arcnet_rx(struct arcnet_local *lp, u_char * arcsoft, short length, int saddr, int daddr) { - struct net_device *dev=lp->adev; - - BUGMSG(D_DURING,"received packet from %02Xh to %02Xh (%d bytes)\n", - saddr,daddr,length); - - /* call the right receiver for the protocol */ - switch (arcsoft[0]) - { - case ARC_P_IP: - case ARC_P_ARP: - case ARC_P_RARP: - case ARC_P_IPX: - case ARC_P_NOVELL_EC: - arcnetA_rx(lp->adev,arcsoft,length,saddr,daddr); - break; + struct net_device *dev = lp->adev; + + BUGMSG(D_DURING, "received packet from %02Xh to %02Xh (%d bytes)\n", + saddr, daddr, length); + + /* call the right receiver for the protocol */ + switch (arcsoft[0]) { + case ARC_P_IP: + case ARC_P_ARP: + case ARC_P_RARP: + case ARC_P_IPX: + case ARC_P_NOVELL_EC: + arcnetA_rx(lp->adev, arcsoft, length, saddr, daddr); + break; #ifdef CONFIG_ARCNET_ETH - case ARC_P_ETHER: - arcnetE_rx(lp->edev,arcsoft,length,saddr,daddr); - break; + case ARC_P_ETHER: + arcnetE_rx(lp->edev, arcsoft, length, saddr, daddr); + break; #endif #ifdef CONFIG_ARCNET_1051 - case ARC_P_IP_RFC1051: - case ARC_P_ARP_RFC1051: - arcnetS_rx(lp->sdev,arcsoft,length,saddr,daddr); - break; + case ARC_P_IP_RFC1051: + case ARC_P_ARP_RFC1051: + arcnetS_rx(lp->sdev, arcsoft, length, saddr, daddr); + break; #endif - case ARC_P_DATAPOINT_BOOT: - case ARC_P_DATAPOINT_MOUNT: - break; - case ARC_P_POWERLAN_BEACON: - case ARC_P_POWERLAN_BEACON2: - break; - case ARC_P_LANSOFT: /* don't understand. fall through. */ - default: - BUGMSG(D_EXTRA,"received unknown protocol %d (%Xh) from station %d.\n", - arcsoft[0],arcsoft[0],saddr); - lp->stats.rx_errors++; - lp->stats.rx_crc_errors++; - break; - } - - /* If any worth-while packets have been received, a mark_bh(NET_BH) - * has been done by netif_rx and Linux will handle them after we - * return. - */ + case ARC_P_DATAPOINT_BOOT: + case ARC_P_DATAPOINT_MOUNT: + break; + case ARC_P_POWERLAN_BEACON: + case ARC_P_POWERLAN_BEACON2: + break; + case ARC_P_LANSOFT: /* don't understand. fall through. */ + default: + BUGMSG(D_EXTRA, "received unknown protocol %d (%Xh) from station %d.\n", + arcsoft[0], arcsoft[0], saddr); + lp->stats.rx_errors++; + lp->stats.rx_crc_errors++; + break; + } + + /* If any worth-while packets have been received, a mark_bh(NET_BH) + * has been done by netif_rx and Linux will handle them after we + * return. + */ } @@ -1081,275 +1032,238 @@ void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr /* Packet receiver for "standard" RFC1201-style packets */ -static void -arcnetA_rx(struct net_device *dev,u_char *buf, - int length, u_char saddr, u_char daddr) +static void arcnetA_rx(struct net_device *dev, u_char * buf, + int length, u_char saddr, u_char daddr) { - struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - struct sk_buff *skb; - struct ClientData *arcsoft,*soft; - - BUGMSG(D_DURING,"it's an RFC1201 packet (length=%d)\n", - length); - - /* compensate for EXTRA_CLIENTDATA (which isn't actually in the - * packet) - */ - arcsoft=(struct ClientData *)(buf-EXTRA_CLIENTDATA); - length+=EXTRA_CLIENTDATA; - - if (arcsoft->split_flag==0xFF) /* Exception Packet */ - { - BUGMSG(D_DURING,"compensating for exception packet\n"); - - /* skip over 4-byte junkola */ - arcsoft=(struct ClientData *) - ((u_char *)arcsoft + 4); - length-=4; - } - - if (!arcsoft->split_flag) /* not split */ - { - struct Incoming *in=&lp->incoming[saddr]; - - BUGMSG(D_RX,"incoming is not split (splitflag=%d)\n", - arcsoft->split_flag); - - if (in->skb) /* already assembling one! */ - { - BUGMSG(D_EXTRA,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n", - in->sequence,arcsoft->split_flag, - arcsoft->sequence); - lp->aborted_seq=arcsoft->sequence; - kfree_skb(in->skb); - lp->stats.rx_errors++; - lp->stats.rx_missed_errors++; - in->skb=NULL; + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + struct sk_buff *skb; + struct ClientData *arcsoft, *soft; + + BUGMSG(D_DURING, "it's an RFC1201 packet (length=%d)\n", + length); + + /* compensate for EXTRA_CLIENTDATA (which isn't actually in the + * packet) + */ + arcsoft = (struct ClientData *) (buf - EXTRA_CLIENTDATA); + length += EXTRA_CLIENTDATA; + + if (arcsoft->split_flag == 0xFF) { /* Exception Packet */ + BUGMSG(D_DURING, "compensating for exception packet\n"); + + /* skip over 4-byte junkola */ + arcsoft = (struct ClientData *) + ((u_char *) arcsoft + 4); + length -= 4; } + if (!arcsoft->split_flag) { /* not split */ + struct Incoming *in = &lp->incoming[saddr]; + + BUGMSG(D_RX, "incoming is not split (splitflag=%d)\n", + arcsoft->split_flag); + + if (in->skb) { /* already assembling one! */ + BUGMSG(D_EXTRA, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n", + in->sequence, arcsoft->split_flag, + arcsoft->sequence); + lp->aborted_seq = arcsoft->sequence; + kfree_skb(in->skb); + lp->stats.rx_errors++; + lp->stats.rx_missed_errors++; + in->skb = NULL; + } + in->sequence = arcsoft->sequence; - in->sequence=arcsoft->sequence; - - skb = alloc_skb(length, GFP_ATOMIC); - if (skb == NULL) { - BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n"); - lp->stats.rx_dropped++; - return; - } - soft=(struct ClientData *)skb->data; - - skb_put(skb,length); - skb->dev = dev; - - memcpy((u_char *)soft+EXTRA_CLIENTDATA, - (u_char *)arcsoft+EXTRA_CLIENTDATA, - length-EXTRA_CLIENTDATA); - soft->daddr=daddr; - soft->saddr=saddr; - - /* ARP packets have problems when sent from DOS. - * source address is always 0 on some systems! So we take - * the hardware source addr (which is impossible to fumble) - * and insert it ourselves. - */ - if (soft->protocol_id == ARC_P_ARP) - { - struct arphdr *arp=(struct arphdr *) - ((char *)soft+sizeof(struct ClientData)); - - /* make sure addresses are the right length */ - if (arp->ar_hln==1 && arp->ar_pln==4) - { - char *cptr=(char *)(arp)+sizeof(struct arphdr); - - if (!*cptr) /* is saddr = 00? */ - { - BUGMSG(D_EXTRA,"ARP source address was 00h, set to %02Xh.\n", - saddr); - lp->stats.rx_crc_errors++; - *cptr=saddr; + skb = alloc_skb(length, GFP_ATOMIC); + if (skb == NULL) { + BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); + lp->stats.rx_dropped++; + return; } - else - { - BUGMSG(D_DURING,"ARP source address (%Xh) is fine.\n", - *cptr); + soft = (struct ClientData *) skb->data; + + skb_put(skb, length); + skb->dev = dev; + + memcpy((u_char *) soft + EXTRA_CLIENTDATA, + (u_char *) arcsoft + EXTRA_CLIENTDATA, + length - EXTRA_CLIENTDATA); + soft->daddr = daddr; + soft->saddr = saddr; + + /* ARP packets have problems when sent from DOS. + * source address is always 0 on some systems! So we take + * the hardware source addr (which is impossible to fumble) + * and insert it ourselves. + */ + if (soft->protocol_id == ARC_P_ARP) { + struct arphdr *arp = (struct arphdr *) + ((char *) soft + sizeof(struct ClientData)); + + /* make sure addresses are the right length */ + if (arp->ar_hln == 1 && arp->ar_pln == 4) { + char *cptr = (char *) (arp) + sizeof(struct arphdr); + + if (!*cptr) { /* is saddr = 00? */ + BUGMSG(D_EXTRA, "ARP source address was 00h, set to %02Xh.\n", + saddr); + lp->stats.rx_crc_errors++; + *cptr = saddr; + } else { + BUGMSG(D_DURING, "ARP source address (%Xh) is fine.\n", + *cptr); + } + } else { + BUGMSG(D_NORMAL, "funny-shaped ARP packet. (%Xh, %Xh)\n", + arp->ar_hln, arp->ar_pln); + lp->stats.rx_errors++; + lp->stats.rx_crc_errors++; + } } - } - else - { - BUGMSG(D_NORMAL,"funny-shaped ARP packet. (%Xh, %Xh)\n", - arp->ar_hln,arp->ar_pln); - lp->stats.rx_errors++; - lp->stats.rx_crc_errors++; - } - } + BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); + + lp->stats.rx_bytes += skb->len; + skb->protocol = arcnetA_type_trans(skb, dev); + netif_rx(skb); + } else { /* split packet */ + /* NOTE: MSDOS ARP packet correction should only need to + * apply to unsplit packets, since ARP packets are so short. + * + * My interpretation of the RFC1201 (ARCnet) document is that + * if a packet is received out of order, the entire assembly + * process should be aborted. + * + * The RFC also mentions "it is possible for successfully + * received packets to be retransmitted." As of 0.40 all + * previously received packets are allowed, not just the + * most recent one. + * + * We allow multiple assembly processes, one for each + * ARCnet card possible on the network. Seems rather like + * a waste of memory. Necessary? + */ - BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx"); - - lp->stats.rx_bytes += skb->len; - skb->protocol=arcnetA_type_trans(skb,dev); - netif_rx(skb); - } - else /* split packet */ - { - /* NOTE: MSDOS ARP packet correction should only need to - * apply to unsplit packets, since ARP packets are so short. - * - * My interpretation of the RFC1201 (ARCnet) document is that - * if a packet is received out of order, the entire assembly - * process should be aborted. - * - * The RFC also mentions "it is possible for successfully - * received packets to be retransmitted." As of 0.40 all - * previously received packets are allowed, not just the - * most recent one. - * - * We allow multiple assembly processes, one for each - * ARCnet card possible on the network. Seems rather like - * a waste of memory. Necessary? - */ - - struct Incoming *in=&lp->incoming[saddr]; - - BUGMSG(D_RX,"packet is split (splitflag=%d, seq=%d)\n", - arcsoft->split_flag,in->sequence); - - if (in->skb && in->sequence!=arcsoft->sequence) - { - BUGMSG(D_EXTRA,"wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n", - saddr,in->sequence,arcsoft->sequence, - arcsoft->split_flag); - kfree_skb(in->skb); - in->skb=NULL; - lp->stats.rx_errors++; - lp->stats.rx_missed_errors++; - in->lastpacket=in->numpackets=0; - } + struct Incoming *in = &lp->incoming[saddr]; - if (arcsoft->split_flag & 1) /* first packet in split */ - { - BUGMSG(D_RX,"brand new splitpacket (splitflag=%d)\n", - arcsoft->split_flag); - if (in->skb) /* already assembling one! */ - { - BUGMSG(D_EXTRA,"aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n", - in->sequence,arcsoft->split_flag, - arcsoft->sequence); - lp->stats.rx_errors++; - lp->stats.rx_missed_errors++; - kfree_skb(in->skb); - } - - in->sequence=arcsoft->sequence; - in->numpackets=((unsigned)arcsoft->split_flag>>1)+2; - in->lastpacket=1; - - if (in->numpackets>16) - { - BUGMSG(D_EXTRA,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n", - arcsoft->split_flag); - lp->stats.rx_errors++; - lp->stats.rx_length_errors++; - return; - } - - in->skb=skb=alloc_skb(508*in->numpackets - + sizeof(struct ClientData), - GFP_ATOMIC); - if (skb == NULL) { - BUGMSG(D_NORMAL,"(split) memory squeeze, dropping packet.\n"); - lp->stats.rx_dropped++; - return; - } - - soft=(struct ClientData *)skb->data; - - skb_put(skb,sizeof(struct ClientData)); - skb->dev=dev; - - memcpy((u_char *)soft+EXTRA_CLIENTDATA, - (u_char *)arcsoft+EXTRA_CLIENTDATA, - sizeof(struct ClientData)-EXTRA_CLIENTDATA); - soft->split_flag=0; /* final packet won't be split */ - } - else /* not first packet */ - { - int packetnum=((unsigned)arcsoft->split_flag>>1) + 1; - - /* if we're not assembling, there's no point - * trying to continue. - */ - if (!in->skb) - { - if (lp->aborted_seq != arcsoft->sequence) - { - BUGMSG(D_EXTRA,"can't continue split without starting first! (splitflag=%d, seq=%d, aborted=%d)\n", - arcsoft->split_flag,arcsoft->sequence, lp->aborted_seq); - lp->stats.rx_errors++; - lp->stats.rx_missed_errors++; + BUGMSG(D_RX, "packet is split (splitflag=%d, seq=%d)\n", + arcsoft->split_flag, in->sequence); + + if (in->skb && in->sequence != arcsoft->sequence) { + BUGMSG(D_EXTRA, "wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n", + saddr, in->sequence, arcsoft->sequence, + arcsoft->split_flag); + kfree_skb(in->skb); + in->skb = NULL; + lp->stats.rx_errors++; + lp->stats.rx_missed_errors++; + in->lastpacket = in->numpackets = 0; } - return; - } - - in->lastpacket++; - if (packetnum!=in->lastpacket) /* not the right flag! */ - { - /* harmless duplicate? ignore. */ - if (packetnum<=in->lastpacket-1) - { - BUGMSG(D_EXTRA,"duplicate splitpacket ignored! (splitflag=%d)\n", - arcsoft->split_flag); - lp->stats.rx_errors++; - lp->stats.rx_frame_errors++; - return; + if (arcsoft->split_flag & 1) { /* first packet in split */ + BUGMSG(D_RX, "brand new splitpacket (splitflag=%d)\n", + arcsoft->split_flag); + if (in->skb) { /* already assembling one! */ + BUGMSG(D_EXTRA, "aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n", + in->sequence, arcsoft->split_flag, + arcsoft->sequence); + lp->stats.rx_errors++; + lp->stats.rx_missed_errors++; + kfree_skb(in->skb); + } + in->sequence = arcsoft->sequence; + in->numpackets = ((unsigned) arcsoft->split_flag >> 1) + 2; + in->lastpacket = 1; + + if (in->numpackets > 16) { + BUGMSG(D_EXTRA, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n", + arcsoft->split_flag); + lp->stats.rx_errors++; + lp->stats.rx_length_errors++; + return; + } + in->skb = skb = alloc_skb(508 * in->numpackets + + sizeof(struct ClientData), + GFP_ATOMIC); + if (skb == NULL) { + BUGMSG(D_NORMAL, "(split) memory squeeze, dropping packet.\n"); + lp->stats.rx_dropped++; + return; + } + soft = (struct ClientData *) skb->data; + + skb_put(skb, sizeof(struct ClientData)); + skb->dev = dev; + + memcpy((u_char *) soft + EXTRA_CLIENTDATA, + (u_char *) arcsoft + EXTRA_CLIENTDATA, + sizeof(struct ClientData) - EXTRA_CLIENTDATA); + soft->split_flag = 0; /* final packet won't be split */ + } else { /* not first packet */ + int packetnum = ((unsigned) arcsoft->split_flag >> 1) + 1; + + /* if we're not assembling, there's no point + * trying to continue. + */ + if (!in->skb) { + if (lp->aborted_seq != arcsoft->sequence) { + BUGMSG(D_EXTRA, "can't continue split without starting first! (splitflag=%d, seq=%d, aborted=%d)\n", + arcsoft->split_flag, arcsoft->sequence, lp->aborted_seq); + lp->stats.rx_errors++; + lp->stats.rx_missed_errors++; + } + return; + } + in->lastpacket++; + if (packetnum != in->lastpacket) { /* not the right flag! */ + /* harmless duplicate? ignore. */ + if (packetnum <= in->lastpacket - 1) { + BUGMSG(D_EXTRA, "duplicate splitpacket ignored! (splitflag=%d)\n", + arcsoft->split_flag); + lp->stats.rx_errors++; + lp->stats.rx_frame_errors++; + return; + } + /* "bad" duplicate, kill reassembly */ + BUGMSG(D_EXTRA, "out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n", + in->sequence, arcsoft->split_flag, + arcsoft->sequence); + lp->aborted_seq = arcsoft->sequence; + kfree_skb(in->skb); + in->skb = NULL; + lp->stats.rx_errors++; + lp->stats.rx_missed_errors++; + in->lastpacket = in->numpackets = 0; + return; + } + soft = (struct ClientData *) in->skb->data; } - /* "bad" duplicate, kill reassembly */ - BUGMSG(D_EXTRA,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n", - in->sequence,arcsoft->split_flag, - arcsoft->sequence); - lp->aborted_seq=arcsoft->sequence; - kfree_skb(in->skb); - in->skb=NULL; - lp->stats.rx_errors++; - lp->stats.rx_missed_errors++; - in->lastpacket=in->numpackets=0; - return; - } - - soft=(struct ClientData *)in->skb->data; - } + skb = in->skb; + + memcpy(skb->data + skb->len, + (u_char *) arcsoft + sizeof(struct ClientData), + length - sizeof(struct ClientData)); + skb_put(skb, length - sizeof(struct ClientData)); - skb=in->skb; - - memcpy(skb->data+skb->len, - (u_char *)arcsoft+sizeof(struct ClientData), - length-sizeof(struct ClientData)); - skb_put(skb,length-sizeof(struct ClientData)); - - soft->daddr=daddr; - soft->saddr=saddr; - - /* are we done? */ - if (in->lastpacket == in->numpackets) - { - if (!skb || !in->skb) - { - BUGMSG(D_NORMAL,"?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)\n", - skb,in->skb); - } - else - { - in->skb=NULL; - in->lastpacket=in->numpackets=0; - - BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx"); - - lp->stats.rx_bytes += skb->len; - skb->protocol=arcnetA_type_trans(skb,dev); - netif_rx(skb); - } + soft->daddr = daddr; + soft->saddr = saddr; + + /* are we done? */ + if (in->lastpacket == in->numpackets) { + if (!skb || !in->skb) { + BUGMSG(D_NORMAL, "?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)\n", + skb, in->skb); + } else { + in->skb = NULL; + in->lastpacket = in->numpackets = 0; + + BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); + + lp->stats.rx_bytes += skb->len; + skb->protocol = arcnetA_type_trans(skb, dev); + netif_rx(skb); + } + } } - } } @@ -1359,89 +1273,86 @@ arcnetA_rx(struct net_device *dev,u_char *buf, * * ****************************************************************************/ -/* Get the current statistics. This may be called with the card open or +/* Get the current statistics. This may be called with the card open or * closed. */ static struct net_device_stats *arcnet_get_stats(struct net_device *dev) { - struct arcnet_local *lp = (struct arcnet_local *)dev->priv; + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; - return &lp->stats; + return &lp->stats; } /* Create the ARCnet ClientData header for an arbitrary protocol layer - * - * saddr=NULL means use device source address (always will anyway) - * daddr=NULL means leave destination address (eg unresolved arp) + + * saddr=NULL means use device source address (always will anyway) + * daddr=NULL means leave destination address (eg unresolved arp) */ -static int arcnetA_header(struct sk_buff *skb,struct net_device *dev, - unsigned short type,void *daddr,void *saddr,unsigned len) +static int arcnetA_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, void *daddr, void *saddr, unsigned len) { - struct ClientData *head = (struct ClientData *) - skb_push(skb,dev->hard_header_len); - struct arcnet_local *lp=(struct arcnet_local *)(dev->priv); - - BUGMSG(D_DURING,"create header from %d to %d; protocol %d (%Xh); size %u.\n", - saddr ? *(u_char*)saddr : -1, - daddr ? *(u_char*)daddr : -1, - type,type,len); - - /* set the protocol ID according to RFC1201 */ - switch(type) - { - case ETH_P_IP: - head->protocol_id=ARC_P_IP; - break; - case ETH_P_ARP: - head->protocol_id=ARC_P_ARP; - break; - case ETH_P_RARP: - head->protocol_id=ARC_P_RARP; - break; - case ETH_P_IPX: - case ETH_P_802_3: - case ETH_P_802_2: - head->protocol_id=ARC_P_IPX; - break; - case ETH_P_ATALK: - head->protocol_id=ARC_P_ATALK; - break; - default: - BUGMSG(D_NORMAL,"I don't understand protocol %d (%Xh)\n", - type,type); - lp->stats.tx_errors++; - lp->stats.tx_aborted_errors++; - return 0; - } - - /* - * Set the source hardware address. - * - * This is pretty pointless for most purposes, but it can help - * in debugging. saddr is stored in the ClientData header and - * removed before sending the packet (since ARCnet does not allow - * us to change the source address in the actual packet sent) - */ - if(saddr) - head->saddr=((u_char*)saddr)[0]; - else - head->saddr=((u_char*)(dev->dev_addr))[0]; - - head->split_flag=0; /* split packets are done elsewhere */ - head->sequence=0; /* so are sequence numbers */ - - /* supposedly if daddr is NULL, we should ignore it... */ - if(daddr) - { - head->daddr=((u_char*)daddr)[0]; - return dev->hard_header_len; - } - else - head->daddr=0; /* better fill one in anyway */ - - return -dev->hard_header_len; + struct ClientData *head = (struct ClientData *) + skb_push(skb, dev->hard_header_len); + struct arcnet_local *lp = (struct arcnet_local *) (dev->priv); + + BUGMSG(D_DURING, "create header from %d to %d; protocol %d (%Xh); size %u.\n", + saddr ? *(u_char *) saddr : -1, + daddr ? *(u_char *) daddr : -1, + type, type, len); + + /* set the protocol ID according to RFC1201 */ + switch (type) { + case ETH_P_IP: + head->protocol_id = ARC_P_IP; + break; + case ETH_P_ARP: + head->protocol_id = ARC_P_ARP; + break; + case ETH_P_RARP: + head->protocol_id = ARC_P_RARP; + break; + case ETH_P_IPX: + case ETH_P_802_3: + case ETH_P_802_2: + head->protocol_id = ARC_P_IPX; + break; + case ETH_P_ATALK: + head->protocol_id = ARC_P_ATALK; + break; + default: + BUGMSG(D_NORMAL, "I don't understand protocol %d (%Xh)\n", + type, type); + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + return 0; + } + + /* + * Set the source hardware address. + * + * This is pretty pointless for most purposes, but it can help + * in debugging. saddr is stored in the ClientData header and + * removed before sending the packet (since ARCnet does not allow + * us to change the source address in the actual packet sent) + */ + if (saddr) + head->saddr = ((u_char *) saddr)[0]; + else + head->saddr = ((u_char *) (dev->dev_addr))[0]; + + head->split_flag = 0; /* split packets are done elsewhere */ + head->sequence = 0; /* so are sequence numbers */ + + /* supposedly if daddr is NULL, we should ignore it... */ + if (daddr) { + head->daddr = ((u_char *) daddr)[0]; + return dev->hard_header_len; + } else + head->daddr = 0; /* better fill one in anyway */ + + return -dev->hard_header_len; } @@ -1451,86 +1362,84 @@ static int arcnetA_header(struct sk_buff *skb,struct net_device *dev, */ static int arcnetA_rebuild_header(struct sk_buff *skb) { - struct ClientData *head = (struct ClientData *)skb->data; - struct net_device *dev=skb->dev; - struct arcnet_local *lp=(struct arcnet_local *)(dev->priv); + struct ClientData *head = (struct ClientData *) skb->data; + struct net_device *dev = skb->dev; + struct arcnet_local *lp = (struct arcnet_local *) (dev->priv); #ifdef CONFIG_INET - int status; + int status; #endif - /* - * Only ARP and IP are currently supported - * - * FIXME: Anyone want to spec IPv6 over ARCnet ? - */ - - if(head->protocol_id != ARC_P_IP) - { - BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n", - head->protocol_id,head->protocol_id); - lp->stats.tx_errors++; - lp->stats.tx_aborted_errors++; - head->daddr=0; - /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/ - return 0; - } - - /* - * Try to get ARP to resolve the header. - */ + /* + * Only ARP and IP are currently supported + * + * FIXME: Anyone want to spec IPv6 over ARCnet ? + */ + + if (head->protocol_id != ARC_P_IP) { + BUGMSG(D_NORMAL, "I don't understand protocol type %d (%Xh) addresses!\n", + head->protocol_id, head->protocol_id); + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + head->daddr = 0; + /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len); */ + return 0; + } + /* + * Try to get ARP to resolve the header. + */ #ifdef CONFIG_INET - BUGMSG(D_DURING,"rebuild header from %d to %d; protocol %Xh\n", - head->saddr,head->daddr,head->protocol_id); - status=arp_find(&(head->daddr),skb)? 1 : 0; - BUGMSG(D_DURING," rebuilt: from %d to %d; protocol %Xh\n", - head->saddr,head->daddr,head->protocol_id); - return status; + BUGMSG(D_DURING, "rebuild header from %d to %d; protocol %Xh\n", + head->saddr, head->daddr, head->protocol_id); + status = arp_find(&(head->daddr), skb) ? 1 : 0; + BUGMSG(D_DURING, " rebuilt: from %d to %d; protocol %Xh\n", + head->saddr, head->daddr, head->protocol_id); + return status; #else - return 0; + return 0; #endif } /* Determine a packet's protocol ID. - * + * With ARCnet we have to convert everything to Ethernet-style stuff. */ -static unsigned short arcnetA_type_trans(struct sk_buff *skb,struct net_device *dev) +static unsigned short arcnetA_type_trans(struct sk_buff *skb, struct net_device *dev) { - struct ClientData *head; - struct arcnet_local *lp=(struct arcnet_local *) (dev->priv); - - /* Pull off the arcnet header. */ - skb->mac.raw=skb->data; - skb_pull(skb,dev->hard_header_len); - head=(struct ClientData *)skb->mac.raw; - - if (head->daddr==0) - skb->pkt_type=PACKET_BROADCAST; - else if (dev->flags&IFF_PROMISC) - { - /* if we're not sending to ourselves :) */ - if (head->daddr != dev->dev_addr[0]) - skb->pkt_type=PACKET_OTHERHOST; - } - - /* now return the protocol number */ - switch (head->protocol_id) - { - case ARC_P_IP: return htons(ETH_P_IP); - case ARC_P_ARP: return htons(ETH_P_ARP); - case ARC_P_RARP: return htons(ETH_P_RARP); - - case ARC_P_IPX: - case ARC_P_NOVELL_EC: - return htons(ETH_P_802_3); - default: - lp->stats.rx_errors++; - lp->stats.rx_crc_errors++; - return 0; - } - - return htons(ETH_P_IP); + struct ClientData *head; + struct arcnet_local *lp = (struct arcnet_local *) (dev->priv); + + /* Pull off the arcnet header. */ + skb->mac.raw = skb->data; + skb_pull(skb, dev->hard_header_len); + head = (struct ClientData *) skb->mac.raw; + + if (head->daddr == 0) + skb->pkt_type = PACKET_BROADCAST; + else if (dev->flags & IFF_PROMISC) { + /* if we're not sending to ourselves :) */ + if (head->daddr != dev->dev_addr[0]) + skb->pkt_type = PACKET_OTHERHOST; + } + /* now return the protocol number */ + switch (head->protocol_id) { + case ARC_P_IP: + return htons(ETH_P_IP); + case ARC_P_ARP: + return htons(ETH_P_ARP); + case ARC_P_RARP: + return htons(ETH_P_RARP); + + case ARC_P_IPX: + case ARC_P_NOVELL_EC: + return htons(ETH_P_802_3); + default: + lp->stats.rx_errors++; + lp->stats.rx_crc_errors++; + return 0; + } + + return htons(ETH_P_IP); } @@ -1545,17 +1454,17 @@ static unsigned short arcnetA_type_trans(struct sk_buff *skb,struct net_device * */ static int arcnetE_init(struct net_device *dev) { - struct arcnet_local *lp = (struct arcnet_local *)dev->priv; + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; - ether_setup(dev); /* we're emulating ether here, not ARCnet */ - dev->dev_addr[0]=0; - dev->dev_addr[5]=lp->stationid; - dev->mtu=512-sizeof(struct archdr)-dev->hard_header_len-1; - dev->open=arcnetE_open_close; - dev->stop=arcnetE_open_close; - dev->hard_start_xmit=arcnetE_send_packet; + ether_setup(dev); /* we're emulating ether here, not ARCnet */ + dev->dev_addr[0] = 0; + dev->dev_addr[5] = lp->stationid; + dev->mtu = 512 - sizeof(struct archdr) - dev->hard_header_len - 1; + dev->open = arcnetE_open_close; + dev->stop = arcnetE_open_close; + dev->hard_start_xmit = arcnetE_send_packet; - return 0; + return 0; } @@ -1564,86 +1473,77 @@ static int arcnetE_init(struct net_device *dev) */ static int arcnetE_open_close(struct net_device *dev) { - return 0; + return 0; } /* Called by the kernel in order to transmit an ethernet-type packet. */ -static int -arcnetE_send_packet(struct sk_buff *skb, struct net_device *dev) +static int arcnetE_send_packet(struct sk_buff *skb, struct net_device *dev) { - struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - int bad,oldmask=0; - u_char daddr; - short offset,length=skb->len+1; - u_char proto=ARC_P_ETHER; - - lp->intx++; - - oldmask |= lp->intmask; - lp->intmask=0; - SETMASK; - - bad=arcnet_send_packet_bad(skb,dev); - if (bad) - { - lp->intx--; - lp->intmask=oldmask; - SETMASK; - return bad; - } - - /* arcnet_send_packet_pad has already set tbusy - don't bother here. */ - - lp->intmask=oldmask; - SETMASK; - - if (length>XMTU) - { - BUGMSG(D_NORMAL,"MTU must be <= 493 for ethernet encap (length=%d).\n", - length); - BUGMSG(D_NORMAL,"transmit aborted.\n"); - - dev_kfree_skb(skb); - lp->intx--; - return 0; - } - - BUGMSG(D_DURING,"starting tx sequence...\n"); - - /* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */ - if (((struct ethhdr*)(skb->data))->h_dest[0] == 0xFF) - daddr=0; - else - daddr=((struct ethhdr*)(skb->data))->h_dest[5]; - - /* load packet into shared memory */ - offset=512-length; - if (length>MTU) /* long/exception packet */ - { - if (lengthprepare_tx)(dev, &proto, 1, skb->data, length-1, daddr, 0, - offset); + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + int bad, oldmask = 0; + u_char daddr; + short offset, length = skb->len + 1; + u_char proto = ARC_P_ETHER; + + lp->intx++; + + oldmask |= lp->intmask; + lp->intmask = 0; + SETMASK; + + bad = arcnet_send_packet_bad(skb, dev); + if (bad) { + lp->intx--; + lp->intmask = oldmask; + SETMASK; + return bad; + } + /* arcnet_send_packet_pad has already set tbusy - don't bother here. */ - dev_kfree_skb(skb); + lp->intmask = oldmask; + SETMASK; + + if (length > XMTU) { + BUGMSG(D_NORMAL, "MTU must be <= 493 for ethernet encap (length=%d).\n", + length); + BUGMSG(D_NORMAL, "transmit aborted.\n"); + + dev_kfree_skb(skb); + lp->intx--; + return 0; + } + BUGMSG(D_DURING, "starting tx sequence...\n"); + + /* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */ + if (((struct ethhdr *) (skb->data))->h_dest[0] == 0xFF) + daddr = 0; + else + daddr = ((struct ethhdr *) (skb->data))->h_dest[5]; + + /* load packet into shared memory */ + offset = 512 - length; + if (length > MTU) { /* long/exception packet */ + if (length < MinTU) + offset -= 3; + } else { /* short packet */ + offset -= 256; + } - if (arcnet_go_tx(dev,1)) - { - /* inform upper layers */ - arcnet_tx_done(lp->adev, lp); - } + BUGMSG(D_DURING, " length=%Xh, offset=%Xh\n", + length, offset); - dev->trans_start=jiffies; + (*lp->prepare_tx) (dev, &proto, 1, skb->data, length - 1, daddr, 0, + offset); + + dev_kfree_skb(skb); + + if (arcnet_go_tx(dev, 1)) { + /* inform upper layers */ + arcnet_tx_done(lp->adev, lp); + } + dev->trans_start = jiffies; lp->intx--; /* make sure we didn't ignore a TX IRQ while we were in here */ @@ -1656,37 +1556,35 @@ arcnetE_send_packet(struct sk_buff *skb, struct net_device *dev) /* Packet receiver for ethernet-encap packets. */ -static void -arcnetE_rx(struct net_device *dev,u_char *arcsoft, - int length,u_char saddr, u_char daddr) +static void arcnetE_rx(struct net_device *dev, u_char * arcsoft, + int length, u_char saddr, u_char daddr) { - struct arcnet_local *lp = (struct arcnet_local *)dev->priv; + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; struct sk_buff *skb; - BUGMSG(D_DURING,"it's an ethernet-encap packet (length=%d)\n", - length); - - skb = alloc_skb(length, GFP_ATOMIC); - if (skb == NULL) { - BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n"); - lp->stats.rx_dropped++; - return; - } + BUGMSG(D_DURING, "it's an ethernet-encap packet (length=%d)\n", + length); - skb_put(skb,length); + skb = alloc_skb(length, GFP_ATOMIC); + if (skb == NULL) { + BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); + lp->stats.rx_dropped++; + return; + } + skb_put(skb, length); - skb->dev = dev; + skb->dev = dev; - memcpy(skb->data,(u_char *)arcsoft+1,length-1); + memcpy(skb->data, (u_char *) arcsoft + 1, length - 1); - BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx"); + BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); lp->stats.rx_bytes += skb->len; - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); } -#endif /* CONFIG_ARCNET_ETH */ +#endif /* CONFIG_ARCNET_ETH */ #ifdef CONFIG_ARCNET_1051 /**************************************************************************** @@ -1699,22 +1597,22 @@ arcnetE_rx(struct net_device *dev,u_char *arcsoft, */ static int arcnetS_init(struct net_device *dev) { - struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - - arcnet_setup(dev); - - /* And now fill particular fields with arcnet values */ - dev->dev_addr[0]=lp->stationid; - dev->hard_header_len=sizeof(struct S_ClientData); - dev->mtu=512-sizeof(struct archdr)-dev->hard_header_len - + S_EXTRA_CLIENTDATA; - dev->open=arcnetS_open_close; - dev->stop=arcnetS_open_close; - dev->hard_start_xmit=arcnetS_send_packet; - dev->hard_header=arcnetS_header; - dev->rebuild_header=arcnetS_rebuild_header; - - return 0; + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + + arcnet_setup(dev); + + /* And now fill particular fields with arcnet values */ + dev->dev_addr[0] = lp->stationid; + dev->hard_header_len = sizeof(struct S_ClientData); + dev->mtu = 512 - sizeof(struct archdr) - dev->hard_header_len + + S_EXTRA_CLIENTDATA; + dev->open = arcnetS_open_close; + dev->stop = arcnetS_open_close; + dev->hard_start_xmit = arcnetS_send_packet; + dev->hard_header = arcnetS_header; + dev->rebuild_header = arcnetS_rebuild_header; + + return 0; } @@ -1723,171 +1621,160 @@ static int arcnetS_init(struct net_device *dev) */ static int arcnetS_open_close(struct net_device *dev) { - return 0; + return 0; } /* Called by the kernel in order to transmit an RFC1051-type packet. */ -static int -arcnetS_send_packet(struct sk_buff *skb, struct net_device *dev) +static int arcnetS_send_packet(struct sk_buff *skb, struct net_device *dev) { - struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - int bad,length; - struct S_ClientData *hdr=(struct S_ClientData *)skb->data; - - lp->intx++; - - bad=arcnet_send_packet_bad(skb,dev); - if (bad) - { - lp->intx--; - return bad; - } - - /* arcnet_send_packet_pad has already set tbusy - don't bother here. */ - - length = 1 < skb->len ? skb->len : 1; - - BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx"); - - /* fits in one packet? */ - if (length-S_EXTRA_CLIENTDATA<=XMTU) - { - (*lp->prepare_tx)(dev, - skb->data+S_EXTRA_CLIENTDATA, - sizeof(struct S_ClientData)-S_EXTRA_CLIENTDATA, - skb->data+sizeof(struct S_ClientData), - length-sizeof(struct S_ClientData), - hdr->daddr,0,0); - - /* done right away */ - dev_kfree_skb(skb); - - if (arcnet_go_tx(dev,1)) - { - /* inform upper layers */ - arcnet_tx_done(lp->adev, lp); + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + int bad, length; + struct S_ClientData *hdr = (struct S_ClientData *) skb->data; + + lp->intx++; + + bad = arcnet_send_packet_bad(skb, dev); + if (bad) { + lp->intx--; + return bad; } - } - else /* too big for one - not accepted */ - { - BUGMSG(D_NORMAL,"packet too long (length=%d)\n", - length); - dev_kfree_skb(skb); - lp->stats.tx_dropped++; - arcnet_tx_done(lp->adev, lp); - } - - dev->trans_start=jiffies; - lp->intx--; - - /* make sure we didn't ignore a TX IRQ while we were in here */ - lp->intmask |= TXFREEflag; - SETMASK; - - return 0; + /* arcnet_send_packet_pad has already set tbusy - don't bother here. */ + + length = 1 < skb->len ? skb->len : 1; + + BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "tx"); + + /* fits in one packet? */ + if (length - S_EXTRA_CLIENTDATA <= XMTU) { + (*lp->prepare_tx) (dev, + skb->data + S_EXTRA_CLIENTDATA, + sizeof(struct S_ClientData) - S_EXTRA_CLIENTDATA, + skb->data + sizeof(struct S_ClientData), + length - sizeof(struct S_ClientData), + hdr->daddr, 0, 0); + + /* done right away */ + dev_kfree_skb(skb); + + if (arcnet_go_tx(dev, 1)) { + /* inform upper layers */ + arcnet_tx_done(lp->adev, lp); + } + } else { /* too big for one - not accepted */ + BUGMSG(D_NORMAL, "packet too long (length=%d)\n", + length); + dev_kfree_skb(skb); + lp->stats.tx_dropped++; + arcnet_tx_done(lp->adev, lp); + } + + dev->trans_start = jiffies; + lp->intx--; + + /* make sure we didn't ignore a TX IRQ while we were in here */ + lp->intmask |= TXFREEflag; + SETMASK; + + return 0; } /* Packet receiver for RFC1051 packets; */ -static void -arcnetS_rx(struct net_device *dev,u_char *buf, - int length,u_char saddr, u_char daddr) +static void arcnetS_rx(struct net_device *dev, u_char * buf, + int length, u_char saddr, u_char daddr) { - struct arcnet_local *lp = (struct arcnet_local *)dev->priv; - struct sk_buff *skb; - struct S_ClientData *arcsoft,*soft; - - arcsoft=(struct S_ClientData *)(buf-S_EXTRA_CLIENTDATA); - length+=S_EXTRA_CLIENTDATA; - - BUGMSG(D_DURING,"it's an RFC1051 packet (length=%d)\n", - length); - - { /* was "if not split" in A protocol, S is never split */ - - skb = alloc_skb(length, GFP_ATOMIC); - if (skb == NULL) { - BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n"); - lp->stats.rx_dropped++; - return; - } - soft=(struct S_ClientData *)skb->data; - skb_put(skb,length); - - memcpy((u_char *)soft + sizeof(struct S_ClientData) - S_EXTRA_CLIENTDATA, - (u_char *)arcsoft + sizeof(struct S_ClientData) -S_EXTRA_CLIENTDATA, - length - sizeof(struct S_ClientData) + S_EXTRA_CLIENTDATA); - soft->protocol_id=arcsoft->protocol_id; - soft->daddr=daddr; - soft->saddr=saddr; - skb->dev = dev; /* is already lp->sdev */ - - BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx"); - - lp->stats.rx_bytes += skb->len; - skb->protocol=arcnetS_type_trans(skb,dev); - netif_rx(skb); - } + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + struct sk_buff *skb; + struct S_ClientData *arcsoft, *soft; + + arcsoft = (struct S_ClientData *) (buf - S_EXTRA_CLIENTDATA); + length += S_EXTRA_CLIENTDATA; + + BUGMSG(D_DURING, "it's an RFC1051 packet (length=%d)\n", + length); + + { /* was "if not split" in A protocol, S is never split */ + + skb = alloc_skb(length, GFP_ATOMIC); + if (skb == NULL) { + BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); + lp->stats.rx_dropped++; + return; + } + soft = (struct S_ClientData *) skb->data; + skb_put(skb, length); + + memcpy((u_char *) soft + sizeof(struct S_ClientData) - S_EXTRA_CLIENTDATA, + (u_char *) arcsoft + sizeof(struct S_ClientData) - S_EXTRA_CLIENTDATA, + length - sizeof(struct S_ClientData) + S_EXTRA_CLIENTDATA); + soft->protocol_id = arcsoft->protocol_id; + soft->daddr = daddr; + soft->saddr = saddr; + skb->dev = dev; /* is already lp->sdev */ + + BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); + + lp->stats.rx_bytes += skb->len; + skb->protocol = arcnetS_type_trans(skb, dev); + netif_rx(skb); + } } /* Create the ARCnet ClientData header for an arbitrary protocol layer - * - * saddr=NULL means use device source address (always will anyway) - * daddr=NULL means leave destination address (eg unresolved arp) + + * saddr=NULL means use device source address (always will anyway) + * daddr=NULL means leave destination address (eg unresolved arp) */ -static int arcnetS_header(struct sk_buff *skb,struct net_device *dev, - unsigned short type,void *daddr,void *saddr,unsigned len) +static int arcnetS_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, void *daddr, void *saddr, unsigned len) { - struct S_ClientData *head = (struct S_ClientData *) - skb_push(skb,dev->hard_header_len); - struct arcnet_local *lp=(struct arcnet_local *)(dev->priv); - - /* set the protocol ID according to RFC1051 */ - switch(type) - { - case ETH_P_IP: - head->protocol_id=ARC_P_IP_RFC1051; - BUGMSG(D_DURING,"S_header: IP_RFC1051 packet.\n"); - break; - case ETH_P_ARP: - head->protocol_id=ARC_P_ARP_RFC1051; - BUGMSG(D_DURING,"S_header: ARP_RFC1051 packet.\n"); - break; - default: - BUGMSG(D_NORMAL,"I don't understand protocol %d (%Xh)\n", - type,type); - lp->stats.tx_errors++; - lp->stats.tx_aborted_errors++; - return 0; - } - - /* - * Set the source hardware address. - * - * This is pretty pointless for most purposes, but it can help - * in debugging. saddr is stored in the ClientData header and - * removed before sending the packet (since ARCnet does not allow - * us to change the source address in the actual packet sent) - */ - if(saddr) - head->saddr=((u_char*)saddr)[0]; - else - head->saddr=((u_char*)(dev->dev_addr))[0]; - - /* supposedly if daddr is NULL, we should ignore it... */ - if(daddr) - { - head->daddr=((u_char*)daddr)[0]; + struct S_ClientData *head = (struct S_ClientData *) + skb_push(skb, dev->hard_header_len); + struct arcnet_local *lp = (struct arcnet_local *) (dev->priv); + + /* set the protocol ID according to RFC1051 */ + switch (type) { + case ETH_P_IP: + head->protocol_id = ARC_P_IP_RFC1051; + BUGMSG(D_DURING, "S_header: IP_RFC1051 packet.\n"); + break; + case ETH_P_ARP: + head->protocol_id = ARC_P_ARP_RFC1051; + BUGMSG(D_DURING, "S_header: ARP_RFC1051 packet.\n"); + break; + default: + BUGMSG(D_NORMAL, "I don't understand protocol %d (%Xh)\n", + type, type); + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + return 0; + } + + /* + * Set the source hardware address. + * + * This is pretty pointless for most purposes, but it can help + * in debugging. saddr is stored in the ClientData header and + * removed before sending the packet (since ARCnet does not allow + * us to change the source address in the actual packet sent) + */ + if (saddr) + head->saddr = ((u_char *) saddr)[0]; + else + head->saddr = ((u_char *) (dev->dev_addr))[0]; + + /* supposedly if daddr is NULL, we should ignore it... */ + if (daddr) { + head->daddr = ((u_char *) daddr)[0]; return dev->hard_header_len; - } - else - head->daddr=0; /* better fill one in anyway */ + } else + head->daddr = 0; /* better fill one in anyway */ - return -dev->hard_header_len; + return -dev->hard_header_len; } @@ -1897,75 +1784,73 @@ static int arcnetS_header(struct sk_buff *skb,struct net_device *dev, */ static int arcnetS_rebuild_header(struct sk_buff *skb) { - struct net_device *dev=skb->dev; - struct S_ClientData *head = (struct S_ClientData *)skb->data; - struct arcnet_local *lp=(struct arcnet_local *)(dev->priv); - - /* - * Only ARP and IP are currently supported - */ - - if(head->protocol_id != ARC_P_IP_RFC1051) - { - BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n", - head->protocol_id,head->protocol_id); - lp->stats.tx_errors++; - lp->stats.tx_aborted_errors++; - head->daddr=0; - /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/ - return 0; - } - - /* - * Try to get ARP to resolve the header. - */ + struct net_device *dev = skb->dev; + struct S_ClientData *head = (struct S_ClientData *) skb->data; + struct arcnet_local *lp = (struct arcnet_local *) (dev->priv); + + /* + * Only ARP and IP are currently supported + */ + + if (head->protocol_id != ARC_P_IP_RFC1051) { + BUGMSG(D_NORMAL, "I don't understand protocol type %d (%Xh) addresses!\n", + head->protocol_id, head->protocol_id); + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + head->daddr = 0; + /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len); */ + return 0; + } + /* + * Try to get ARP to resolve the header. + */ #ifdef CONFIG_INET - return arp_find(&(head->daddr),skb)? 1 : 0; + return arp_find(&(head->daddr), skb) ? 1 : 0; #else - return 0; + return 0; #endif } /* Determine a packet's protocol ID. - * + * With ARCnet we have to convert everything to Ethernet-style stuff. */ -unsigned short arcnetS_type_trans(struct sk_buff *skb,struct net_device *dev) +unsigned short arcnetS_type_trans(struct sk_buff *skb, struct net_device *dev) { - struct S_ClientData *head; - struct arcnet_local *lp=(struct arcnet_local *) (dev->priv); - - /* Pull off the arcnet header. */ - skb->mac.raw=skb->data; - skb_pull(skb,dev->hard_header_len); - head=(struct S_ClientData *)skb->mac.raw; - - if (head->daddr==0) - skb->pkt_type=PACKET_BROADCAST; - else if (dev->flags&IFF_PROMISC) - { - /* if we're not sending to ourselves :) */ - if (head->daddr != dev->dev_addr[0]) - skb->pkt_type=PACKET_OTHERHOST; - } - - /* now return the protocol number */ - switch (head->protocol_id) - { - case ARC_P_IP_RFC1051: return htons(ETH_P_IP); - case ARC_P_ARP_RFC1051: return htons(ETH_P_ARP); - case ARC_P_ATALK: return htons(ETH_P_ATALK); /* untested appletalk */ - default: - lp->stats.rx_errors++; - lp->stats.rx_crc_errors++; - return 0; - } - - return htons(ETH_P_IP); + struct S_ClientData *head; + struct arcnet_local *lp = (struct arcnet_local *) (dev->priv); + + /* Pull off the arcnet header. */ + skb->mac.raw = skb->data; + skb_pull(skb, dev->hard_header_len); + head = (struct S_ClientData *) skb->mac.raw; + + if (head->daddr == 0) + skb->pkt_type = PACKET_BROADCAST; + else if (dev->flags & IFF_PROMISC) { + /* if we're not sending to ourselves :) */ + if (head->daddr != dev->dev_addr[0]) + skb->pkt_type = PACKET_OTHERHOST; + } + /* now return the protocol number */ + switch (head->protocol_id) { + case ARC_P_IP_RFC1051: + return htons(ETH_P_IP); + case ARC_P_ARP_RFC1051: + return htons(ETH_P_ARP); + case ARC_P_ATALK: + return htons(ETH_P_ATALK); /* untested appletalk */ + default: + lp->stats.rx_errors++; + lp->stats.rx_crc_errors++; + return 0; + } + + return htons(ETH_P_IP); } -#endif /* CONFIG_ARCNET_1051 */ +#endif /* CONFIG_ARCNET_1051 */ /**************************************************************************** @@ -1978,15 +1863,15 @@ unsigned short arcnetS_type_trans(struct sk_buff *skb,struct net_device *dev) void cleanup_module(void) { - printk("Generic arcnet support removed.\n"); + printk("Generic arcnet support removed.\n"); } void arcnet_use_count(int open) { - if (open) - MOD_INC_USE_COUNT; - else - MOD_DEC_USE_COUNT; + if (open) + MOD_INC_USE_COUNT; + else + MOD_DEC_USE_COUNT; } #else @@ -1996,54 +1881,52 @@ void arcnet_use_count(int open) } struct net_device arcnet_devs[MAX_ARCNET_DEVS]; -int arcnet_num_devs=0; +int arcnet_num_devs = 0; char arcnet_dev_names[MAX_ARCNET_DEVS][10]; -void __init arcnet_init(void) +int __init arcnet_init(void) { - int c; + int c; - init_module(); + init_module(); - /* Don't register_netdev here. The chain hasn't been initialised. */ + /* Don't register_netdev here. The chain hasn't been initialised. */ #ifdef CONFIG_ARCNET_COM90xx - if ((!com90xx_explicit) && arcnet_num_devs < MAX_ARCNET_DEVS) - { - arcnet_devs[arcnet_num_devs].init=arc90xx_probe; - arcnet_devs[arcnet_num_devs].name= - (char *)&arcnet_dev_names[arcnet_num_devs]; - arcnet_num_devs++; - } + if ((!com90xx_explicit) && arcnet_num_devs < MAX_ARCNET_DEVS) { + arcnet_devs[arcnet_num_devs].init = arc90xx_probe; + arcnet_devs[arcnet_num_devs].name = + (char *) &arcnet_dev_names[arcnet_num_devs]; + arcnet_num_devs++; + } #endif - if (!arcnet_num_devs) - { - printk("Don't forget to load the chipset driver.\n"); - return; - } - - /* Link into the device chain */ + if (!arcnet_num_devs) { + printk("Don't forget to load the chipset driver.\n"); + return 0; + } + /* Link into the device chain */ - /* Q: Should we put ourselves at the beginning or the end of the chain? */ - /* Probably the end, because we're not so fast, but... */ + /* Q: Should we put ourselves at the beginning or the end of the chain? */ + /* Probably the end, because we're not so fast, but... */ - for (c=0; c< (arcnet_num_devs-1); c++) - arcnet_devs[c].next=&arcnet_devs[c+1]; + for (c = 0; c < (arcnet_num_devs - 1); c++) + arcnet_devs[c].next = &arcnet_devs[c + 1]; - write_lock_bh(&dev_base_lock); - arcnet_devs[c].next=dev_base; - dev_base=&arcnet_devs[0]; - write_unlock_bh(&dev_base_lock); + write_lock_bh(&dev_base_lock); + arcnet_devs[c].next = dev_base; + dev_base = &arcnet_devs[0]; + write_unlock_bh(&dev_base_lock); - /* Give names to those without them */ + /* Give names to those without them */ - for (c=0; c< arcnet_num_devs; c++) - if (!arcnet_dev_names[c][0]) - arcnet_makename((char *)&arcnet_dev_names[c]); + for (c = 0; c < arcnet_num_devs; c++) + if (!arcnet_dev_names[c][0]) + arcnet_makename((char *) &arcnet_dev_names[c]); + return 0; } -#endif /* MODULE */ +#endif /* MODULE */ #ifdef MODULE @@ -2053,48 +1936,46 @@ static int __init init_module(void) #endif { #ifdef ALPHA_WARNING - BUGLVL(D_EXTRA) - { - printk("arcnet: ***\n"); - printk("arcnet: * Read arcnet.txt for important release notes!\n"); - printk("arcnet: *\n"); - printk("arcnet: * This is an ALPHA version! (Last stable release: v2.56) E-mail me if\n"); - printk("arcnet: * you have any questions, comments, or bug reports.\n"); - printk("arcnet: ***\n"); - } + BUGLVL(D_EXTRA) { + printk("arcnet: ***\n"); + printk("arcnet: * Read arcnet.txt for important release notes!\n"); + printk("arcnet: *\n"); + printk("arcnet: * This is an ALPHA version! (Last stable release: v2.56) E-mail me if\n"); + printk("arcnet: * you have any questions, comments, or bug reports.\n"); + printk("arcnet: ***\n"); + } #endif - printk("%sAvailable protocols: ARCnet RFC1201" + printk("%sAvailable protocols: ARCnet RFC1201" #ifdef CONFIG_ARCNET_ETH - ", Ethernet-Encap" + ", Ethernet-Encap" #endif #ifdef CONFIG_ARCNET_1051 - ", ARCnet RFC1051" + ", ARCnet RFC1051" #endif #ifdef MODULE - ".\nDon't forget to load the chipset driver" + ".\nDon't forget to load the chipset driver" #endif - ".\n",version); - return 0; + ".\n", version); + return 0; } void arcnet_makename(char *device) { - struct net_device *dev; - int arcnum; - - arcnum = 0; - for (;;) - { - sprintf(device, "arc%d", arcnum); - read_lock_bh(&dev_base_lock); - for (dev = dev_base; dev; dev=dev->next) - if (dev->name != device && !strcmp(dev->name, device)) - break; - read_unlock_bh(&dev_base_lock); - if (!dev) - return; - arcnum++; - } + struct net_device *dev; + int arcnum; + + arcnum = 0; + for (;;) { + sprintf(device, "arc%d", arcnum); + read_lock_bh(&dev_base_lock); + for (dev = dev_base; dev; dev = dev->next) + if (dev->name != device && !strcmp(dev->name, device)) + break; + read_unlock_bh(&dev_base_lock); + if (!dev) + return; + arcnum++; + } } diff --git a/drivers/net/irda/actisys.c b/drivers/net/irda/actisys.c index f83fce38c..10d6cf208 100644 --- a/drivers/net/irda/actisys.c +++ b/drivers/net/irda/actisys.c @@ -7,7 +7,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Wed Oct 21 20:02:35 1998 - * Modified at: Sat Jun 26 16:57:57 1999 + * Modified at: Mon Oct 18 23:37:06 1999 * Modified by: Dag Brattli * * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. @@ -32,33 +32,31 @@ #include #include #include -#include -static void actisys_reset(struct irda_device *dev); -static void actisys_open(struct irda_device *idev, int type); -static void actisys_close(struct irda_device *dev); -static void actisys_change_speed( struct irda_device *dev, __u32 speed); -static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos); +static int actisys_change_speed(struct irda_task *task); +static int actisys_reset(struct irda_task *task); +static void actisys_open(dongle_t *self, struct qos_info *qos); +static void actisys_close(dongle_t *self); /* These are the baudrates supported */ -static __u32 baud_rates[] = { 9600, 19200, 57600, 115200, 38400}; +static __u32 baud_rates[] = { 9600, 19200, 57600, 115200, 38400 }; -static struct dongle dongle = { - ACTISYS_DONGLE, +static struct dongle_reg dongle = { + Q_NULL, + IRDA_ACTISYS_DONGLE, actisys_open, actisys_close, actisys_reset, actisys_change_speed, - actisys_init_qos, }; -static struct dongle dongle_plus = { - ACTISYS_PLUS_DONGLE, +static struct dongle_reg dongle_plus = { + Q_NULL, + IRDA_ACTISYS_PLUS_DONGLE, actisys_open, actisys_close, actisys_reset, actisys_change_speed, - actisys_init_qos, }; int __init actisys_init(void) @@ -82,20 +80,23 @@ void actisys_cleanup(void) irda_device_unregister_dongle(&dongle_plus); } -static void actisys_open(struct irda_device *idev, int type) +static void actisys_open(dongle_t *self, struct qos_info *qos) { - strcat(idev->description, " <-> actisys"); + qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; - idev->io.dongle_id = type; - idev->flags |= IFF_DONGLE; + /* Remove support for 38400 if this is not a 220L+ dongle */ + if (self->issue->type == IRDA_ACTISYS_DONGLE) + qos->baud_rate.bits &= ~IR_38400; + + qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */ MOD_INC_USE_COUNT; } -static void actisys_close(struct irda_device *idev) +static void actisys_close(dongle_t *self) { /* Power off dongle */ - irda_device_set_dtr_rts(idev, FALSE, FALSE); + self->set_dtr_rts(self->dev, FALSE, FALSE); MOD_DEC_USE_COUNT; } @@ -107,52 +108,84 @@ static void actisys_close(struct irda_device *idev) * To cycle through the available baud rates, pulse RTS low for a few * ms. */ -static void actisys_change_speed(struct irda_device *idev, __u32 speed) +static int actisys_change_speed(struct irda_task *task) { - __u32 current_baudrate; + dongle_t *self = (dongle_t *) task->instance; + __u32 speed = (__u32) task->param; + __u32 current_speed; int index = 0; + int ret = 0; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - - current_baudrate = idev->qos.baud_rate.value; + current_speed = self->speed; /* Find the correct baudrate index for the currently used baudrate */ - while (current_baudrate != baud_rates[index]) + while (current_speed != baud_rates[index]) index++; - DEBUG( 4, __FUNCTION__ "(), index=%d\n", index); + IRDA_DEBUG(4, __FUNCTION__ "(), index=%d\n", index); - /* Cycle through avaiable baudrates until we reach the correct one */ - while (current_baudrate != speed) { - DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", + switch (task->state) { + case IRDA_TASK_INIT: + /* Lock dongle */ + if (irda_lock((void *) &self->busy) == FALSE) { + IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n"); + ret = MSECS_TO_JIFFIES(100); + break; + } + + IRDA_DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", baud_rates[index]); /* Set DTR, clear RTS */ - irda_device_set_dtr_rts(idev, TRUE, FALSE); + self->set_dtr_rts(self->dev, TRUE, FALSE); - /* Wait at a few ms */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(MSECS_TO_JIFFIES(20)); + irda_task_next_state(task, IRDA_TASK_WAIT1); + /* Wait at a few ms */ + ret = MSECS_TO_JIFFIES(20); + break; + case IRDA_TASK_WAIT1: /* Set DTR, Set RTS */ - irda_device_set_dtr_rts(idev, TRUE, TRUE); + self->set_dtr_rts(self->dev, TRUE, TRUE); - /* Wait at a few ms again */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(MSECS_TO_JIFFIES(20)); + irda_task_next_state(task, IRDA_TASK_WAIT2); + /* Wait at a few ms again */ + ret = MSECS_TO_JIFFIES(20); + break; + case IRDA_TASK_WAIT2: /* Go to next baudrate */ - if (idev->io.dongle_id == ACTISYS_DONGLE) + if (self->issue->type == IRDA_ACTISYS_DONGLE) index = (index+1) % 4; /* IR-220L */ else index = (index+1) % 5; /* IR-220L+ */ - current_baudrate = baud_rates[index]; + current_speed = baud_rates[index]; + + /* Check if we need to go some more rounds */ + if (current_speed != speed) + irda_task_next_state(task, IRDA_TASK_INIT); + else { + irda_task_next_state(task, IRDA_TASK_DONE); + self->busy = 0; + } + break; + default: + ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); + irda_task_next_state(task, IRDA_TASK_DONE); + self->busy = 0; + ret = -1; + break; } - DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", baud_rates[index]); + + self->speed = speed; + + IRDA_DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", + baud_rates[index]); + + return ret; } /* @@ -162,45 +195,42 @@ static void actisys_change_speed(struct irda_device *idev, __u32 speed) * called with a process context! * * 1. Clear DTR for a few ms. - * */ -static void actisys_reset(struct irda_device *idev) +static int actisys_reset(struct irda_task *task) { - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - - /* Clear DTR */ - irda_device_set_dtr_rts(idev, FALSE, TRUE); + dongle_t *self = (dongle_t *) task->instance; + int ret = 0; - /* Sleep 10-20 ms*/ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(MSECS_TO_JIFFIES(20)); - - /* Go back to normal mode */ - irda_device_set_dtr_rts(idev, TRUE, TRUE); - - idev->qos.baud_rate.value = 9600; -} + ASSERT(task != NULL, return -1;); -/* - * Function actisys_init_qos (qos) - * - * Initialize QoS capabilities - * - */ -static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos) -{ - qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; + switch (task->state) { + case IRDA_TASK_INIT: + /* Clear DTR */ + self->set_dtr_rts(self->dev, FALSE, TRUE); + + irda_task_next_state(task, IRDA_TASK_WAIT); - /* Remove support for 38400 if this is not a 220L+ dongle */ - if (idev->io.dongle_id == ACTISYS_DONGLE) - qos->baud_rate.bits &= ~IR_38400; + /* Sleep 10-20 ms*/ + ret = MSECS_TO_JIFFIES(20); + break; + case IRDA_TASK_WAIT: + /* Go back to normal mode */ + self->set_dtr_rts(self->dev, TRUE, TRUE); - qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */ + irda_task_next_state(task, IRDA_TASK_DONE); + + self->speed = 9600; + break; + default: + ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); + irda_task_next_state(task, IRDA_TASK_DONE); + ret = -1; + break; + } + return ret; } #ifdef MODULE - MODULE_AUTHOR("Dag Brattli "); MODULE_DESCRIPTION("ACTiSYS IR-220L and IR-220L+ dongle driver"); @@ -225,5 +255,4 @@ void cleanup_module(void) { actisys_cleanup(); } - -#endif +#endif /* MODULE */ diff --git a/drivers/net/irda/airport.c b/drivers/net/irda/airport.c index edfc2e6e6..a1eee252b 100644 --- a/drivers/net/irda/airport.c +++ b/drivers/net/irda/airport.c @@ -56,7 +56,7 @@ int __init airport_init(void) { int ret; - DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, __FUNCTION__ "()\n"); ret = irda_device_register_dongle(&dongle); if (ret < 0) return ret; @@ -65,17 +65,17 @@ int __init airport_init(void) void airport_cleanup(void) { - DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, __FUNCTION__ "()\n"); irda_device_unregister_dongle(&dongle); } static void airport_open(struct irda_device *idev, int type) { - DEBUG(2, __FUNCTION__ "(,%d)\n", type); + IRDA_DEBUG(2, __FUNCTION__ "(,%d)\n", type); if (strlen(idev->description) < sizeof(idev->description) - 13) strcat(idev->description, " <-> airport"); else - DEBUG(0, __FUNCTION__ " description too long: %s\n", + IRDA_DEBUG(0, __FUNCTION__ " description too long: %s\n", idev->description); idev->io.dongle_id = type; @@ -86,7 +86,7 @@ static void airport_open(struct irda_device *idev, int type) static void airport_close(struct irda_device *idev) { - DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, __FUNCTION__ "()\n"); /* Power off dongle */ irda_device_set_dtr_rts(idev, FALSE, FALSE); @@ -95,13 +95,13 @@ static void airport_close(struct irda_device *idev) static void airport_set_command_mode(struct irda_device *idev) { - DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, __FUNCTION__ "()\n"); irda_device_set_dtr_rts(idev, FALSE, TRUE); } static void airport_set_normal_mode(struct irda_device *idev) { - DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, __FUNCTION__ "()\n"); irda_device_set_dtr_rts(idev, TRUE, TRUE); } @@ -109,7 +109,7 @@ static void airport_set_normal_mode(struct irda_device *idev) void airport_write_char(struct irda_device *idev, unsigned char c) { int actual; - DEBUG(2, __FUNCTION__ "(,0x%x)\n", c & 0xff); + IRDA_DEBUG(2, __FUNCTION__ "(,0x%x)\n", c & 0xff); actual = idev->raw_write(idev, &c, 1); ASSERT(actual == 1, return;); } @@ -120,22 +120,22 @@ static int airport_waitfor_char(struct irda_device *idev, unsigned char c) { int i, found = FALSE; int before; - DEBUG(2, __FUNCTION__ "(,0x%x)\n", c); + IRDA_DEBUG(2, __FUNCTION__ "(,0x%x)\n", c); /* Sleep approx. 10 ms */ before = jiffies; current->state = TASK_INTERRUPTIBLE; schedule_timeout(MSECS_TO_JIFFIES(20)); - DEBUG(4, __FUNCTION__ " waited %ldms\n", + IRDA_DEBUG(4, __FUNCTION__ " waited %ldms\n", JIFFIES_TO_MSECS(jiffies - before)); for ( i = 0 ; !found && i < idev->rx_buff.len ; i++ ) { - /* DEBUG(6, __FUNCTION__ " 0x02x\n", idev->rx_buff.data[i]); */ + /* IRDA_DEBUG(6, __FUNCTION__ " 0x02x\n", idev->rx_buff.data[i]); */ found = c == idev->rx_buff.data[i]; } idev->rx_buff.len = 0; - DEBUG(2, __FUNCTION__ " returns %s\n", (found ? "true" : "false")); + IRDA_DEBUG(2, __FUNCTION__ " returns %s\n", (found ? "true" : "false")); return found; } @@ -144,7 +144,7 @@ static int airport_check_command_mode(struct irda_device *idev) int i; int found = FALSE; - DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, __FUNCTION__ "()\n"); current->state = TASK_INTERRUPTIBLE; schedule_timeout(MSECS_TO_JIFFIES(20)); airport_set_command_mode(idev); @@ -160,9 +160,9 @@ static int airport_check_command_mode(struct irda_device *idev) } if (found) { - DEBUG(2, __FUNCTION__ " OK. (%d)\n", i); + IRDA_DEBUG(2, __FUNCTION__ " OK. (%d)\n", i); } else { - DEBUG(0, __FUNCTION__ " FAILED!\n"); + IRDA_DEBUG(0, __FUNCTION__ " FAILED!\n"); } return found; } @@ -173,7 +173,7 @@ static int airport_write_register(struct irda_device *idev, unsigned char reg) int ok = FALSE; int i; - DEBUG(4, __FUNCTION__ "(,0x%x)\n", reg); + IRDA_DEBUG(4, __FUNCTION__ "(,0x%x)\n", reg); airport_check_command_mode(idev); for ( i = 0 ; i < 6 ; i++ ) { @@ -191,9 +191,9 @@ static int airport_write_register(struct irda_device *idev, unsigned char reg) airport_set_normal_mode(idev); if (ok) { - DEBUG(4, __FUNCTION__ "(,0x%x) returns OK\n", reg); + IRDA_DEBUG(4, __FUNCTION__ "(,0x%x) returns OK\n", reg); } else { - DEBUG(0, __FUNCTION__ "(,0x%x) returns False!\n", reg); + IRDA_DEBUG(0, __FUNCTION__ "(,0x%x) returns False!\n", reg); } return ok; } @@ -209,7 +209,7 @@ static void airport_change_speed(struct irda_device *idev, __u32 speed) __u32 current_baudrate; int baudcode; - DEBUG(4, __FUNCTION__ "(,%d)\n", speed); + IRDA_DEBUG(4, __FUNCTION__ "(,%d)\n", speed); ASSERT(idev != NULL, return;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); @@ -224,16 +224,16 @@ static void airport_change_speed(struct irda_device *idev, __u32 speed) case 57600: baudcode = 0x60; break; case 115200: baudcode = 0x70; break; default: - DEBUG(0, __FUNCTION__ " bad baud rate: %d\n", speed); + IRDA_DEBUG(0, __FUNCTION__ " bad baud rate: %d\n", speed); return; } current_baudrate = idev->qos.baud_rate.value; - DEBUG(4, __FUNCTION__ " current baudrate: %d\n", current_baudrate); + IRDA_DEBUG(4, __FUNCTION__ " current baudrate: %d\n", current_baudrate); /* The dongle falls back to 9600 baud */ if (current_baudrate != 9600) { - DEBUG(4, __FUNCTION__ " resetting speed to 9600 baud\n"); + IRDA_DEBUG(4, __FUNCTION__ " resetting speed to 9600 baud\n"); ASSERT(idev->change_speed , return;); idev->change_speed(idev, 9600); idev->qos.baud_rate.value = 9600; @@ -247,11 +247,11 @@ static void airport_change_speed(struct irda_device *idev, __u32 speed) if (airport_write_register(idev, baudcode|0x01)) { /* ok */ } else { - DEBUG(0, __FUNCTION__ + IRDA_DEBUG(0, __FUNCTION__ " Cannot set new speed in second register\n"); } } else { - DEBUG(0, __FUNCTION__ + IRDA_DEBUG(0, __FUNCTION__ " Cannot set new speed in first register\n"); } @@ -260,7 +260,7 @@ static void airport_change_speed(struct irda_device *idev, __u32 speed) /* How do I signal an error in these functions? */ - DEBUG(4, __FUNCTION__ " returning\n"); + IRDA_DEBUG(4, __FUNCTION__ " returning\n"); } @@ -275,7 +275,7 @@ static void airport_reset(struct irda_device *idev) { int ok; - DEBUG(2, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, __FUNCTION__ "()\n"); ASSERT(idev != NULL, return;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); ASSERT(idev->set_raw_mode /* The airport needs this */, return;); @@ -286,10 +286,10 @@ static void airport_reset(struct irda_device *idev) airport_set_normal_mode(idev); /* Sleep 2000 ms */ - DEBUG(2, __FUNCTION__ " waiting for powerup\n"); + IRDA_DEBUG(2, __FUNCTION__ " waiting for powerup\n"); current->state = TASK_INTERRUPTIBLE; schedule_timeout(MSECS_TO_JIFFIES(2000)); - DEBUG(2, __FUNCTION__ " finished waiting for powerup\n"); + IRDA_DEBUG(2, __FUNCTION__ " finished waiting for powerup\n"); /* set dongle speed to 9600 */ ok = TRUE; @@ -322,12 +322,12 @@ static void airport_reset(struct irda_device *idev) current->state = TASK_INTERRUPTIBLE; schedule_timeout(MSECS_TO_JIFFIES(20)); - DEBUG(4, __FUNCTION__ " waited 20ms\n"); + IRDA_DEBUG(4, __FUNCTION__ " waited 20ms\n"); idev->qos.baud_rate.value = 9600; if (!ok) MESSAGE(__FUNCTION__ "() failed.\n"); - DEBUG(2, __FUNCTION__ " returning.\n"); + IRDA_DEBUG(2, __FUNCTION__ " returning.\n"); } /* diff --git a/drivers/net/irda/esi.c b/drivers/net/irda/esi.c index f531c1af4..bc6f28da7 100644 --- a/drivers/net/irda/esi.c +++ b/drivers/net/irda/esi.c @@ -1,27 +1,33 @@ /********************************************************************* * * Filename: esi.c - * Version: 1.4 + * Version: 1.5 * Description: Driver for the Extended Systems JetEye PC dongle * Status: Experimental. - * Author: Thomas Davis, + * Author: Dag Brattli * Created at: Sat Feb 21 18:54:38 1998 - * Modified at: Sat Jun 26 16:50:17 1999 + * Modified at: Mon Oct 18 12:35:43 1999 * Modified by: Dag Brattli - * Sources: esi.c - * - * Copyright (c) 1998-1999, Dag Brattli, - * Copyright (c) 1998, Thomas Davis, , + * + * Copyright (c) 1999 Dag Brattli, , + * Copyright (c) 1998 Thomas Davis, , * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. - * - * I, Thomas Davis, provide no warranty for any of this software. - * This material is provided "AS-IS" and at no charge. - * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * ********************************************************************/ #include @@ -34,22 +40,19 @@ #include #include #include -#include -#include -static void esi_open(struct irda_device *idev, int type); -static void esi_close(struct irda_device *driver); -static void esi_change_speed(struct irda_device *idev, __u32 speed); -static void esi_reset(struct irda_device *idev); -static void esi_qos_init(struct irda_device *idev, struct qos_info *qos); +static void esi_open(dongle_t *self, struct qos_info *qos); +static void esi_close(dongle_t *self); +static int esi_change_speed(struct irda_task *task); +static int esi_reset(struct irda_task *task); -static struct dongle dongle = { - ESI_DONGLE, +static struct dongle_reg dongle = { + Q_NULL, + IRDA_ESI_DONGLE, esi_open, esi_close, esi_reset, esi_change_speed, - esi_qos_init, }; int __init esi_init(void) @@ -62,37 +65,40 @@ void esi_cleanup(void) irda_device_unregister_dongle(&dongle); } -static void esi_open(struct irda_device *idev, int type) +static void esi_open(dongle_t *self, struct qos_info *qos) { - strcat(idev->description, " <-> esi"); - - idev->io.dongle_id = type; - idev->flags |= IFF_DONGLE; + qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200; + qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */ MOD_INC_USE_COUNT; } -static void esi_close(struct irda_device *idev) +static void esi_close(dongle_t *dongle) { /* Power off dongle */ - irda_device_set_dtr_rts(idev, FALSE, FALSE); + dongle->set_dtr_rts(dongle->dev, FALSE, FALSE); MOD_DEC_USE_COUNT; } /* - * Function esi_change_speed (idev, speed) + * Function esi_change_speed (task) * * Set the speed for the Extended Systems JetEye PC ESI-9680 type dongle * */ -static void esi_change_speed(struct irda_device *idev, __u32 speed) +static int esi_change_speed(struct irda_task *task) { + dongle_t *self = (dongle_t *) task->instance; + __u32 speed = (__u32) task->param; int dtr, rts; - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - + /* Lock dongle */ + if (irda_lock((void *) &self->busy) == FALSE) { + IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n"); + return MSECS_TO_JIFFIES(100); + } + switch (speed) { case 19200: dtr = TRUE; @@ -109,28 +115,34 @@ static void esi_change_speed(struct irda_device *idev, __u32 speed) } /* Change speed of dongle */ - irda_device_set_dtr_rts(idev, dtr, rts); -} + self->set_dtr_rts(self->dev, dtr, rts); + self->speed = speed; -static void esi_reset( struct irda_device *idev) -{ - /* Empty */ + irda_task_next_state(task, IRDA_TASK_DONE); + + /* Unlock */ + self->busy = 0; + + return 0; } /* - * Function esi_qos_init (qos) + * Function esi_reset (task) * - * Init QoS capabilities for the dongle + * Reset dongle; * */ -static void esi_qos_init(struct irda_device *idev, struct qos_info *qos) +static int esi_reset(struct irda_task *task) { - qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200; - qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */ + dongle_t *self = (dongle_t *) task->instance; + + self->set_dtr_rts(self->dev, FALSE, FALSE); + irda_task_next_state(task, IRDA_TASK_DONE); + + return 0; } #ifdef MODULE - MODULE_AUTHOR("Dag Brattli "); MODULE_DESCRIPTION("Extended Systems JetEye PC dongle driver"); @@ -155,6 +167,5 @@ void cleanup_module(void) { esi_cleanup(); } - -#endif +#endif /* MODULE */ diff --git a/drivers/net/irda/girbil.c b/drivers/net/irda/girbil.c index 2d1d1f269..4fa2ec59f 100644 --- a/drivers/net/irda/girbil.c +++ b/drivers/net/irda/girbil.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Feb 6 21:02:33 1999 - * Modified at: Sun Jul 18 12:09:26 1999 + * Modified at: Mon Oct 18 22:15:20 1999 * Modified by: Dag Brattli * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -32,13 +32,11 @@ #include #include #include -#include -static void girbil_reset(struct irda_device *dev); -static void girbil_open(struct irda_device *dev, int type); -static void girbil_close(struct irda_device *dev); -static void girbil_change_speed(struct irda_device *dev, __u32 speed); -static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos); +static int girbil_reset(struct irda_task *task); +static void girbil_open(dongle_t *self, struct qos_info *qos); +static void girbil_close(dongle_t *self); +static int girbil_change_speed(struct irda_task *task); /* Control register 1 */ #define GIRBIL_TXEN 0x01 /* Enable transmitter */ @@ -67,13 +65,13 @@ static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos); /* Control register 2 (0x5) */ #define GIRBIL_LOAD 0x51 /* Load the new baud rate value */ -static struct dongle dongle = { - GIRBIL_DONGLE, +static struct dongle_reg dongle = { + Q_NULL, + IRDA_GIRBIL_DONGLE, girbil_open, girbil_close, girbil_reset, girbil_change_speed, - girbil_init_qos, }; int __init girbil_init(void) @@ -86,20 +84,18 @@ void girbil_cleanup(void) irda_device_unregister_dongle(&dongle); } -static void girbil_open(struct irda_device *idev, int type) +static void girbil_open(dongle_t *self, struct qos_info *qos) { - strcat(idev->description, " <-> girbil"); + qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; + qos->min_turn_time.bits &= 0x03; - idev->io.dongle_id = type; - idev->flags |= IFF_DONGLE; - MOD_INC_USE_COUNT; } -static void girbil_close(struct irda_device *idev) +static void girbil_close(dongle_t *self) { /* Power off dongle */ - irda_device_set_dtr_rts(idev, FALSE, FALSE); + self->set_dtr_rts(self->dev, FALSE, FALSE); MOD_DEC_USE_COUNT; } @@ -111,47 +107,80 @@ static void girbil_close(struct irda_device *idev) * function must be called with a process context! * */ -static void girbil_change_speed(struct irda_device *idev, __u32 speed) +static int girbil_change_speed(struct irda_task *task) { + dongle_t *self = (dongle_t *) task->instance; + __u32 speed = (__u32) task->param; __u8 control[2]; - - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - - switch (speed) { - case 9600: - default: - control[0] = GIRBIL_9600; + int ret = 0; + + switch (task->state) { + case IRDA_TASK_INIT: + /* Lock dongle */ + if (irda_lock((void *) &self->busy) == FALSE) { + IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n"); + return MSECS_TO_JIFFIES(100); + } + + /* Need to reset the dongle and go to 9600 bps before + programming */ + if (irda_task_execute(self, girbil_reset, NULL, task, + (void *) speed)) + { + /* Dongle need more time to reset */ + irda_task_next_state(task, IRDA_TASK_CHILD_WAIT); + + /* Give reset 1 sec to finish */ + ret = MSECS_TO_JIFFIES(1000); + } break; - case 19200: - control[0] = GIRBIL_19200; + case IRDA_TASK_CHILD_WAIT: + WARNING(__FUNCTION__ "(), resetting dongle timed out!\n"); + ret = -1; break; - case 34800: - control[0] = GIRBIL_38400; + case IRDA_TASK_CHILD_DONE: + /* Set DTR and Clear RTS to enter command mode */ + self->set_dtr_rts(self->dev, FALSE, TRUE); + + switch (speed) { + case 9600: + default: + control[0] = GIRBIL_9600; + break; + case 19200: + control[0] = GIRBIL_19200; + break; + case 34800: + control[0] = GIRBIL_38400; + break; + case 57600: + control[0] = GIRBIL_57600; + break; + case 115200: + control[0] = GIRBIL_115200; + break; + } + control[1] = GIRBIL_LOAD; + + /* Write control bytes */ + self->write(self->dev, control, 2); + irda_task_next_state(task, IRDA_TASK_WAIT); + ret = MSECS_TO_JIFFIES(100); break; - case 57600: - control[0] = GIRBIL_57600; + case IRDA_TASK_WAIT: + /* Go back to normal mode */ + self->set_dtr_rts(self->dev, TRUE, TRUE); + irda_task_next_state(task, IRDA_TASK_DONE); + self->busy = 0; break; - case 115200: - control[0] = GIRBIL_115200; + default: + ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); + irda_task_next_state(task, IRDA_TASK_DONE); + self->busy = 0; + ret = -1; break; } - control[1] = GIRBIL_LOAD; - - /* Need to reset the dongle and go to 9600 bps before programming */ - girbil_reset(idev); - - /* Set DTR and Clear RTS to enter command mode */ - irda_device_set_dtr_rts(idev, FALSE, TRUE); - - /* Write control bytes */ - irda_device_raw_write(idev, control, 2); - - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(MSECS_TO_JIFFIES(100)); - - /* Go back to normal mode */ - irda_device_set_dtr_rts(idev, TRUE, TRUE); + return ret; } /* @@ -164,54 +193,47 @@ static void girbil_change_speed(struct irda_device *idev, __u32 speed) * 0. set RTS, and wait at least 5 ms * 1. clear RTS */ -void girbil_reset(struct irda_device *idev) +static int girbil_reset(struct irda_task *task) { + dongle_t *self = (dongle_t *) task->instance; __u8 control = GIRBIL_TXEN | GIRBIL_RXEN; - - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - - /* Make sure the IrDA chip also goes to defalt speed */ - if (idev->change_speed) - idev->change_speed(idev, 9600); - - /* Reset dongle */ - irda_device_set_dtr_rts(idev, TRUE, FALSE); - - /* Sleep at least 5 ms */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(MSECS_TO_JIFFIES(10)); - - /* Set DTR and clear RTS to enter command mode */ - irda_device_set_dtr_rts(idev, FALSE, TRUE); - - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(MSECS_TO_JIFFIES(10)); - - /* Write control byte */ - irda_device_raw_write(idev, &control, 1); - - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(MSECS_TO_JIFFIES(20)); - - /* Go back to normal mode */ - irda_device_set_dtr_rts(idev, TRUE, TRUE); -} - -/* - * Function girbil_init_qos (qos) - * - * Initialize QoS capabilities - * - */ -static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos) -{ - qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; - qos->min_turn_time.bits &= 0x03; + int ret = 0; + + switch (task->state) { + case IRDA_TASK_INIT: + /* Reset dongle */ + self->set_dtr_rts(self->dev, TRUE, FALSE); + irda_task_next_state(task, IRDA_TASK_WAIT1); + /* Sleep at least 5 ms */ + ret = MSECS_TO_JIFFIES(10); + break; + case IRDA_TASK_WAIT1: + /* Set DTR and clear RTS to enter command mode */ + self->set_dtr_rts(self->dev, FALSE, TRUE); + irda_task_next_state(task, IRDA_TASK_WAIT2); + ret = MSECS_TO_JIFFIES(10); + break; + case IRDA_TASK_WAIT2: + /* Write control byte */ + self->write(self->dev, &control, 1); + irda_task_next_state(task, IRDA_TASK_WAIT3); + ret = MSECS_TO_JIFFIES(20); + break; + case IRDA_TASK_WAIT3: + /* Go back to normal mode */ + self->set_dtr_rts(self->dev, TRUE, TRUE); + irda_task_next_state(task, IRDA_TASK_DONE); + break; + default: + ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); + irda_task_next_state(task, IRDA_TASK_DONE); + ret = -1; + break; + } + return ret; } #ifdef MODULE - MODULE_AUTHOR("Dag Brattli "); MODULE_DESCRIPTION("Greenwich GIrBIL dongle driver"); @@ -236,5 +258,4 @@ void cleanup_module(void) { girbil_cleanup(); } - #endif /* MODULE */ diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c index b60241a40..d4f4f6d71 100644 --- a/drivers/net/irda/irport.c +++ b/drivers/net/irda/irport.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 3 13:49:59 1997 - * Modified at: Tue Aug 31 13:54:27 1999 + * Modified at: Wed Oct 20 00:07:42 1999 * Modified by: Dag Brattli * Sources: serial.c by Linus Torvalds * @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -69,22 +70,22 @@ static unsigned int irq[] = { 0, 0, 0, 0 }; static unsigned int qos_mtt_bits = 0x03; -static struct irda_device *dev_self[] = { NULL, NULL, NULL, NULL}; +static struct irport_cb *dev_self[] = { NULL, NULL, NULL, NULL}; static char *driver_name = "irport"; static int irport_open(int i, unsigned int iobase, unsigned int irq); -static int irport_close(struct irda_device *idev); +static int irport_close(struct irport_cb *self); -static void irport_write_wakeup(struct irda_device *idev); +static void irport_write_wakeup(struct irport_cb *self); static int irport_write(int iobase, int fifo_size, __u8 *buf, int len); -static void irport_receive(struct irda_device *idev); +static void irport_receive(struct irport_cb *self); static int irport_net_init(struct net_device *dev); static int irport_net_open(struct net_device *dev); static int irport_net_close(struct net_device *dev); -static int irport_is_receiving(struct irda_device *idev); -static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts); -static int irport_raw_write(struct irda_device *idev, __u8 *buf, int len); +static int irport_is_receiving(struct irport_cb *self); +static void irport_set_dtr_rts(struct net_device *dev, int dtr, int rts); +static int irport_raw_write(struct net_device *dev, __u8 *buf, int len); int __init irport_init(void) { @@ -114,7 +115,7 @@ static void irport_cleanup(void) { int i; - DEBUG( 4, __FUNCTION__ "()\n"); + IRDA_DEBUG( 4, __FUNCTION__ "()\n"); for (i=0; i < 4; i++) { if (dev_self[i]) @@ -125,108 +126,154 @@ static void irport_cleanup(void) static int irport_open(int i, unsigned int iobase, unsigned int irq) { - struct irda_device *idev; + struct net_device *dev; + struct irport_cb *self; int ret; + int err; - DEBUG( 0, __FUNCTION__ "()\n"); - -/* if (irport_probe(iobase, irq) == -1) */ -/* return -1; */ + IRDA_DEBUG(0, __FUNCTION__ "()\n"); /* * Allocate new instance of the driver */ - idev = kmalloc(sizeof(struct irda_device), GFP_KERNEL); - if (idev == NULL) { - printk( KERN_ERR "IrDA: Can't allocate memory for " - "IrDA control block!\n"); + self = kmalloc(sizeof(struct irport_cb), GFP_KERNEL); + if (!self) { + ERROR(__FUNCTION__ "(), can't allocate memory for " + "control block!\n"); return -ENOMEM; } - memset(idev, 0, sizeof(struct irda_device)); + memset(self, 0, sizeof(struct irport_cb)); + spin_lock_init(&self->lock); + /* Need to store self somewhere */ - dev_self[i] = idev; + dev_self[i] = self; /* Initialize IO */ - idev->io.iobase2 = iobase; - idev->io.irq2 = irq; - idev->io.io_ext = IO_EXTENT; - idev->io.fifo_size = 16; - - idev->netdev.base_addr = iobase; - idev->netdev.irq = irq; + self->io.iobase2 = iobase; + self->io.irq2 = irq; + self->io.io_ext = IO_EXTENT; + self->io.fifo_size = 16; /* Lock the port that we need */ - ret = check_region(idev->io.iobase2, idev->io.io_ext); + ret = check_region(self->io.iobase2, self->io.io_ext); if (ret < 0) { - DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", - idev->io.iobase2); - /* irport_cleanup(self->idev); */ + IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", + self->io.iobase2); + /* irport_cleanup(self->self); */ return -ENODEV; } - request_region(idev->io.iobase2, idev->io.io_ext, idev->name); + request_region(self->io.iobase2, self->io.io_ext, driver_name); /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&idev->qos); + irda_init_max_qos_capabilies(&self->qos); - idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| + self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| IR_115200; - idev->qos.min_turn_time.bits = qos_mtt_bits; - irda_qos_bits_to_value(&idev->qos); + self->qos.min_turn_time.bits = qos_mtt_bits; + irda_qos_bits_to_value(&self->qos); - idev->flags = IFF_SIR|IFF_PIO; + self->flags = IFF_SIR|IFF_PIO; - /* Specify which buffer allocation policy we need */ - idev->rx_buff.flags = GFP_KERNEL; - idev->tx_buff.flags = GFP_KERNEL; - - idev->rx_buff.truesize = 4000; - idev->tx_buff.truesize = 4000; + /* Specify how much memory we want */ + self->rx_buff.truesize = 4000; + self->tx_buff.truesize = 4000; - /* Initialize callbacks */ - idev->change_speed = irport_change_speed; - idev->wait_until_sent = irport_wait_until_sent; - idev->is_receiving = irport_is_receiving; - idev->set_dtr_rts = irport_set_dtr_rts; - idev->raw_write = irport_raw_write; + /* Allocate memory if needed */ + if (self->rx_buff.truesize > 0) { + self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize, + GFP_KERNEL); + if (self->rx_buff.head == NULL) + return -ENOMEM; + memset(self->rx_buff.head, 0, self->rx_buff.truesize); + } + if (self->tx_buff.truesize > 0) { + self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, + GFP_KERNEL); + if (self->tx_buff.head == NULL) { + kfree(self->rx_buff.head); + return -ENOMEM; + } + memset(self->tx_buff.head, 0, self->tx_buff.truesize); + } + self->rx_buff.in_frame = FALSE; + self->rx_buff.state = OUTSIDE_FRAME; + self->tx_buff.data = self->tx_buff.head; + self->rx_buff.data = self->rx_buff.head; + self->mode = IRDA_IRLAP; + + if (!(dev = dev_alloc("irda%d", &err))) { + ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); + return -ENOMEM; + } + /* dev_alloc doesn't clear the struct, so lets do a little hack */ + memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*)); + + dev->priv = (void *) self; + self->netdev = dev; /* Override the network functions we need to use */ - idev->netdev.init = irport_net_init; - idev->netdev.hard_start_xmit = irport_hard_xmit; - idev->netdev.open = irport_net_open; - idev->netdev.stop = irport_net_close; + dev->init = irport_net_init; + dev->hard_start_xmit = irport_hard_xmit; + dev->open = irport_net_open; + dev->stop = irport_net_close; + + /* Make ifconfig display some details */ + dev->base_addr = iobase; + dev->irq = irq; + + rtnl_lock(); + err = register_netdevice(dev); + rtnl_unlock(); + if (err) { + ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); + return -1; + } + MESSAGE("IrDA: Registered device %s\n", dev->name); - /* Open the IrDA device */ - irda_device_open(idev, driver_name, NULL); - return 0; } -static int irport_close(struct irda_device *idev) +static int irport_close(struct irport_cb *self) { - ASSERT(idev != NULL, return -1;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); + ASSERT(self != NULL, return -1;); - /* Release the IO-port that this driver is using */ - DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", - idev->io.iobase2); - release_region(idev->io.iobase2, idev->io.io_ext); + /* We are not using any dongle anymore! */ + if (self->dongle) + irda_device_dongle_cleanup(self->dongle); + self->dongle = NULL; + + /* Remove netdevice */ + if (self->netdev) { + rtnl_lock(); + unregister_netdevice(self->netdev); + rtnl_unlock(); + } - irda_device_close(idev); + /* Release the IO-port that this driver is using */ + IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", + self->io.iobase2); + release_region(self->io.iobase2, self->io.io_ext); - kfree(idev); + if (self->tx_buff.head) + kfree(self->tx_buff.head); + + if (self->rx_buff.head) + kfree(self->rx_buff.head); + + kfree(self); return 0; } -void irport_start(struct irda_device *idev, int iobase) +void irport_start(struct irport_cb *self, int iobase) { unsigned long flags; - spin_lock_irqsave(&idev->lock, flags); + spin_lock_irqsave(&self->lock, flags); - irport_stop(idev, iobase); + irport_stop(self, iobase); /* Initialize UART */ outb(UART_LCR_WLEN8, iobase+UART_LCR); /* Reset DLAB */ @@ -235,14 +282,14 @@ void irport_start(struct irda_device *idev, int iobase) /* Turn on interrups */ outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, iobase+UART_IER); - spin_unlock_irqrestore(&idev->lock, flags); + spin_unlock_irqrestore(&self->lock, flags); } -void irport_stop(struct irda_device *idev, int iobase) +void irport_stop(struct irport_cb *self, int iobase) { unsigned long flags; - spin_lock_irqsave(&idev->lock, flags); + spin_lock_irqsave(&self->lock, flags); /* Reset UART */ outb(0, iobase+UART_MCR); @@ -250,7 +297,7 @@ void irport_stop(struct irda_device *idev, int iobase) /* Turn off interrupts */ outb(0, iobase+UART_IER); - spin_unlock_irqrestore(&idev->lock, flags); + spin_unlock_irqrestore(&self->lock, flags); } /* @@ -261,18 +308,18 @@ void irport_stop(struct irda_device *idev, int iobase) */ int irport_probe(int iobase) { - DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase); + IRDA_DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase); return 0; } /* - * Function irport_change_speed (idev, speed) + * Function irport_change_speed (self, speed) * * Set speed of IrDA port to specified baudrate * */ -void irport_change_speed(struct irda_device *idev, __u32 speed) +void irport_change_speed(struct irport_cb *self, __u32 speed) { unsigned long flags; int iobase; @@ -280,17 +327,16 @@ void irport_change_speed(struct irda_device *idev, __u32 speed) int lcr; /* Line control reg */ int divisor; - DEBUG(2, __FUNCTION__ "(), Setting speed to: %d\n", speed); + IRDA_DEBUG(2, __FUNCTION__ "(), Setting speed to: %d\n", speed); - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(self != NULL, return;); - iobase = idev->io.iobase2; + iobase = self->io.iobase2; /* Update accounting for new speed */ - idev->io.baudrate = speed; + self->io.speed = speed; - spin_lock_irqsave(&idev->lock, flags); + spin_lock_irqsave(&self->lock, flags); /* Turn off interrupts */ outb(0, iobase+UART_IER); @@ -304,7 +350,7 @@ void irport_change_speed(struct irda_device *idev, __u32 speed) * almost 1,7 ms at 19200 bps. At speeds above that we can just forget * about this timeout since it will always be fast enough. */ - if (idev->io.baudrate < 38400) + if (self->io.speed < 38400) fcr |= UART_FCR_TRIGGER_1; else fcr |= UART_FCR_TRIGGER_14; @@ -321,7 +367,7 @@ void irport_change_speed(struct irda_device *idev, __u32 speed) /* Turn on interrups */ outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER); - spin_unlock_irqrestore(&idev->lock, flags); + spin_unlock_irqrestore(&self->lock, flags); } /* @@ -331,39 +377,38 @@ void irport_change_speed(struct irda_device *idev, __u32 speed) * more packets to send, we send them here. * */ -static void irport_write_wakeup(struct irda_device *idev) +static void irport_write_wakeup(struct irport_cb *self) { int actual = 0; int iobase; int fcr; - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(self != NULL, return;); - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); /* Finished with frame? */ - if (idev->tx_buff.len > 0) { + if (self->tx_buff.len > 0) { /* Write data left in transmit buffer */ - actual = irport_write(idev->io.iobase2, idev->io.fifo_size, - idev->tx_buff.data, idev->tx_buff.len); - idev->tx_buff.data += actual; - idev->tx_buff.len -= actual; + actual = irport_write(self->io.iobase2, self->io.fifo_size, + self->tx_buff.data, self->tx_buff.len); + self->tx_buff.data += actual; + self->tx_buff.len -= actual; } else { - iobase = idev->io.iobase2; + iobase = self->io.iobase2; /* * Now serial buffer is almost free & we can start * transmission of another packet */ - idev->netdev.tbusy = 0; /* Unlock */ - idev->stats.tx_packets++; + self->netdev->tbusy = 0; /* Unlock */ + self->stats.tx_packets++; /* Schedule network layer, so we can get some more frames */ mark_bh(NET_BH); fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR; - if (idev->io.baudrate < 38400) + if (self->io.speed < 38400) fcr |= UART_FCR_TRIGGER_1; else fcr |= UART_FCR_TRIGGER_14; @@ -391,7 +436,7 @@ static int irport_write(int iobase, int fifo_size, __u8 *buf, int len) /* Tx FIFO should be empty! */ if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { - DEBUG(0, __FUNCTION__ "(), failed, fifo not empty!\n"); + IRDA_DEBUG(0, __FUNCTION__ "(), failed, fifo not empty!\n"); return -1; } @@ -415,19 +460,19 @@ static int irport_write(int iobase, int fifo_size, __u8 *buf, int len) */ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev) { - struct irda_device *idev; + struct irport_cb *self; unsigned long flags; int actual = 0; int iobase; + __u32 speed; ASSERT(dev != NULL, return 0;); - idev = (struct irda_device *) dev->priv; + self = (struct irport_cb *) dev->priv; - ASSERT(idev != NULL, return 0;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;); + ASSERT(self != NULL, return 0;); - iobase = idev->io.iobase2; + iobase = self->io.iobase2; /* Lock transmit buffer */ if (irda_lock((void *) &dev->tbusy) == FALSE) { @@ -436,28 +481,32 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev) return -EBUSY; WARNING("%s: transmit timed out\n", dev->name); - irport_start(idev, iobase); - irport_change_speed(idev, idev->io.baudrate); + irport_start(self, iobase); + irport_change_speed(self, self->io.speed ); dev->trans_start = jiffies; } - spin_lock_irqsave(&idev->lock, flags); + /* Check if we need to change the speed */ + if ((speed = irda_get_speed(skb)) != self->io.speed) + irport_change_speed(self, speed); + + spin_lock_irqsave(&self->lock, flags); /* Init tx buffer */ - idev->tx_buff.data = idev->tx_buff.head; + self->tx_buff.data = self->tx_buff.head; /* Copy skb to tx_buff while wrapping, stuffing and making CRC */ - idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, - idev->tx_buff.truesize); + self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, + self->tx_buff.truesize); - idev->tx_buff.data += actual; - idev->tx_buff.len -= actual; + self->tx_buff.data += actual; + self->tx_buff.len -= actual; /* Turn on transmit finished interrupt. Will fire immediately! */ outb(UART_IER_THRI, iobase+UART_IER); - spin_unlock_irqrestore(&idev->lock, flags); + spin_unlock_irqrestore(&self->lock, flags); dev_kfree_skb(skb); @@ -465,30 +514,31 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev) } /* - * Function irport_receive (idev) + * Function irport_receive (self) * * Receive one frame from the infrared port * */ -static void irport_receive(struct irda_device *idev) +static void irport_receive(struct irport_cb *self) { int boguscount = 0; int iobase; - ASSERT(idev != NULL, return;); + ASSERT(self != NULL, return;); - iobase = idev->io.iobase2; + iobase = self->io.iobase2; /* * Receive all characters in Rx FIFO, unwrap and unstuff them. * async_unwrap_char will deliver all found frames */ do { - async_unwrap_char(idev, inb(iobase+UART_RX)); + async_unwrap_char(self->netdev, &self->rx_buff, + inb(iobase+UART_RX)); /* Make sure we don't stay here to long */ if (boguscount++ > 32) { - DEBUG(2,__FUNCTION__ "(), breaking!\n"); + IRDA_DEBUG(2,__FUNCTION__ "(), breaking!\n"); break; } } while (inb(iobase+UART_LSR) & UART_LSR_DR); @@ -501,45 +551,47 @@ static void irport_receive(struct irda_device *idev) */ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct irda_device *idev = (struct irda_device *) dev_id; + struct net_device *dev = (struct net_device *) dev_id; + struct irport_cb *self; + int boguscount = 0; int iobase; int iir, lsr; - int boguscount = 0; - if (!idev) { + if (!dev) { WARNING(__FUNCTION__ "() irq %d for unknown device.\n", irq); return; } + self = (struct irport_cb *) dev->priv; - spin_lock(&idev->lock); + spin_lock(&self->lock); - idev->netdev.interrupt = 1; + dev->interrupt = 1; - iobase = idev->io.iobase2; + iobase = self->io.iobase2; iir = inb(iobase+UART_IIR) & UART_IIR_ID; while (iir) { /* Clear interrupt */ lsr = inb(iobase+UART_LSR); - DEBUG(4, __FUNCTION__ "(), iir=%02x, lsr=%02x, iobase=%#x\n", + IRDA_DEBUG(4, __FUNCTION__ "(), iir=%02x, lsr=%02x, iobase=%#x\n", iir, lsr, iobase); switch (iir) { case UART_IIR_RLSI: - DEBUG(2, __FUNCTION__ "(), RLSI\n"); + IRDA_DEBUG(2, __FUNCTION__ "(), RLSI\n"); break; case UART_IIR_RDI: /* Receive interrupt */ - irport_receive(idev); + irport_receive(self); break; case UART_IIR_THRI: if (lsr & UART_LSR_THRE) /* Transmitter ready for data */ - irport_write_wakeup(idev); + irport_write_wakeup(self); break; default: - DEBUG(0, __FUNCTION__ "(), unhandled IIR=%#x\n", iir); + IRDA_DEBUG(0, __FUNCTION__ "(), unhandled IIR=%#x\n", iir); break; } @@ -549,9 +601,9 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs) iir = inb(iobase + UART_IIR) & UART_IIR_ID; } - idev->netdev.interrupt = 0; + dev->interrupt = 0; - spin_unlock(&idev->lock); + spin_unlock(&self->lock); } static int irport_net_init(struct net_device *dev) @@ -572,24 +624,32 @@ static int irport_net_init(struct net_device *dev) */ static int irport_net_open(struct net_device *dev) { - struct irda_device *idev; + struct irport_cb *self; int iobase; ASSERT(dev != NULL, return -1;); - idev = (struct irda_device *) dev->priv; + self = (struct irport_cb *) dev->priv; - iobase = idev->io.iobase2; + iobase = self->io.iobase2; - if (request_irq(idev->io.irq2, irport_interrupt, 0, idev->name, - (void *) idev)) + if (request_irq(self->io.irq2, irport_interrupt, 0, dev->name, + (void *) dev)) return -EAGAIN; - irport_start(idev, iobase); - irda_device_net_open(dev); + irport_start(self, iobase); + + /* Ready to play! */ + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + /* + * Open new IrLAP layer instance, now that everything should be + * initialized properly + */ + self->irlap = irlap_open(dev, &self->qos); - /* Change speed to make sure dongles follow us again */ - if (idev->change_speed) - idev->change_speed(idev, 9600); + /* FIXME: change speed of dongle */ MOD_INC_USE_COUNT; @@ -597,30 +657,37 @@ static int irport_net_open(struct net_device *dev) } /* - * Function irport_net_close (idev) + * Function irport_net_close (self) * * * */ static int irport_net_close(struct net_device *dev) { - struct irda_device *idev; + struct irport_cb *self; int iobase; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); ASSERT(dev != NULL, return -1;); - idev = (struct irda_device *) dev->priv; + self = (struct irport_cb *) dev->priv; - ASSERT(idev != NULL, return -1;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;) + ASSERT(self != NULL, return -1;); - iobase = idev->io.iobase2; + iobase = self->io.iobase2; - irda_device_net_close(dev); - irport_stop(idev, iobase); + /* Stop device */ + dev->tbusy = 1; + dev->start = 0; - free_irq(idev->io.irq2, idev); + /* Stop and remove instance of IrLAP */ + if (self->irlap) + irlap_close(self->irlap); + self->irlap = NULL; + + irport_stop(self, iobase); + + free_irq(self->io.irq2, dev); MOD_DEC_USE_COUNT; @@ -628,34 +695,36 @@ static int irport_net_close(struct net_device *dev) } /* - * Function irport_wait_until_sent (idev) + * Function irport_wait_until_sent (self) * * Delay exectution until finished transmitting * */ -void irport_wait_until_sent(struct irda_device *idev) +#if 0 +void irport_wait_until_sent(struct irport_cb *self) { int iobase; - iobase = idev->io.iobase2; + iobase = self->io.iobase2; /* Wait until Tx FIFO is empty */ while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { - DEBUG(2, __FUNCTION__ "(), waiting!\n"); + IRDA_DEBUG(2, __FUNCTION__ "(), waiting!\n"); current->state = TASK_INTERRUPTIBLE; schedule_timeout(MSECS_TO_JIFFIES(60)); } } +#endif /* - * Function irport_is_receiving (idev) + * Function irport_is_receiving (self) * * Returns true is we are currently receiving data * */ -static int irport_is_receiving(struct irda_device *idev) +static int irport_is_receiving(struct irport_cb *self) { - return (idev->rx_buff.state != OUTSIDE_FRAME); + return (self->rx_buff.state != OUTSIDE_FRAME); } /* @@ -664,14 +733,14 @@ static int irport_is_receiving(struct irda_device *idev) * This function can be used by dongles etc. to set or reset the status * of the dtr and rts lines */ -static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts) +static void irport_set_dtr_rts(struct net_device *dev, int dtr, int rts) { + struct irport_cb *self = dev->priv; int iobase; - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(self != NULL, return;); - iobase = idev->io.iobase2; + iobase = self->io.iobase2; if (dtr) dtr = UART_MCR_DTR; @@ -681,19 +750,19 @@ static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts) outb(dtr|rts|UART_MCR_OUT2, iobase+UART_MCR); } -static int irport_raw_write(struct irda_device *idev, __u8 *buf, int len) +static int irport_raw_write(struct net_device *dev, __u8 *buf, int len) { - int iobase; + struct irport_cb *self = (struct irport_cb *) dev->priv; int actual = 0; + int iobase; - ASSERT(idev != NULL, return -1;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); + ASSERT(self != NULL, return -1;); - iobase = idev->io.iobase2; + iobase = self->io.iobase2; /* Tx FIFO should be empty! */ if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { - DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n"); + IRDA_DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n"); return -1; } @@ -708,33 +777,20 @@ static int irport_raw_write(struct irda_device *idev, __u8 *buf, int len) } #ifdef MODULE - MODULE_PARM(io, "1-4i"); MODULE_PARM(irq, "1-4i"); MODULE_AUTHOR("Dag Brattli "); MODULE_DESCRIPTION("Half duplex serial driver for IrDA SIR mode"); -/* - * Function cleanup_module (void) - * - * - * - */ void cleanup_module(void) { irport_cleanup(); } -/* - * Function init_module (void) - * - * - */ int init_module(void) { return irport_init(); } - #endif /* MODULE */ diff --git a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c index 6a439a1a8..b6a9dad59 100644 --- a/drivers/net/irda/irtty.c +++ b/drivers/net/irda/irtty.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Dec 9 21:18:38 1997 - * Modified at: Tue Sep 28 08:39:29 1999 + * Modified at: Wed Oct 20 00:05:43 1999 * Modified by: Dag Brattli * Sources: slip.c by Laurence Culhane, * Fred N. van Kempen, @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include @@ -36,7 +38,6 @@ #include #include #include -#include #include #include @@ -46,27 +47,31 @@ static struct tty_ldisc irda_ldisc; static int qos_mtt_bits = 0x03; /* 5 ms or more */ +/* Network device fuction prototypes */ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev); -static void irtty_wait_until_sent(struct irda_device *driver); -static int irtty_is_receiving(struct irda_device *idev); -static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts); -static int irtty_raw_write(struct irda_device *idev, __u8 *buf, int len); -static int irtty_raw_read(struct irda_device *idev, __u8 *buf, int len, - int timeout); -static void irtty_set_raw_mode(struct irda_device *dev, int mode); static int irtty_net_init(struct net_device *dev); static int irtty_net_open(struct net_device *dev); static int irtty_net_close(struct net_device *dev); +static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); +static struct net_device_stats *irtty_net_get_stats(struct net_device *dev); +/* Line discipline function prototypes */ static int irtty_open(struct tty_struct *tty); static void irtty_close(struct tty_struct *tty); static int irtty_ioctl(struct tty_struct *, void *, int, void *); static int irtty_receive_room(struct tty_struct *tty); -static void irtty_change_speed(struct irda_device *dev, __u32 speed); static void irtty_write_wakeup(struct tty_struct *tty); - static void irtty_receive_buf(struct tty_struct *, const unsigned char *, char *, int); + +/* IrDA specific function protoctypes */ +static int irtty_is_receiving(struct irtty_cb *self); +static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts); +static int irtty_raw_write(struct net_device *dev, __u8 *buf, int len); +static int irtty_raw_read(struct net_device *dev, __u8 *buf, int len); +static int irtty_set_mode(struct net_device *dev, int mode); +static int irtty_change_speed(struct irda_task *task); + char *driver_name = "irtty"; int __init irtty_init(void) @@ -140,13 +145,16 @@ static void irtty_cleanup(void) */ static int irtty_open(struct tty_struct *tty) { + struct net_device *dev; struct irtty_cb *self; char name[16]; + int err; ASSERT(tty != NULL, return -EEXIST;); /* First make sure we're not already connected. */ self = (struct irtty_cb *) tty->disc_data; + if (self != NULL && self->magic == IRTTY_MAGIC) return -EEXIST; @@ -168,9 +176,8 @@ static int irtty_open(struct tty_struct *tty) sprintf(name, "%s%d", tty->driver.name, MINOR(tty->device) - tty->driver.minor_start + tty->driver.name_base); - - /* hashbin_insert( irtty, (QUEUE*) self, 0, self->name); */ - hashbin_insert(irtty, (QUEUE*) self, (int) self, NULL); + + hashbin_insert(irtty, (queue_t *) self, (int) self, NULL); if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); @@ -179,11 +186,7 @@ static int irtty_open(struct tty_struct *tty) tty->ldisc.flush_buffer(tty); self->magic = IRTTY_MAGIC; - - /* - * Initialize driver - */ - self->idev.rx_buff.state = OUTSIDE_FRAME; + self->rx_buff.state = OUTSIDE_FRAME; /* * Initialize QoS capabilities, we fill in all the stuff that @@ -191,40 +194,71 @@ static int irtty_open(struct tty_struct *tty) * that are not device dependent (such as link disconnect time) so * this parameter can be set by IrLAP (or the user) instead. DB */ - irda_init_max_qos_capabilies(&self->idev.qos); + irda_init_max_qos_capabilies(&self->qos); /* The only value we must override it the baudrate */ - self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| + self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| IR_115200; - self->idev.qos.min_turn_time.bits = qos_mtt_bits; - self->idev.flags = IFF_SIR | IFF_PIO; - irda_qos_bits_to_value(&self->idev.qos); - - /* Specify which buffer allocation policy we need */ - self->idev.rx_buff.flags = GFP_KERNEL; - self->idev.tx_buff.flags = GFP_KERNEL; + self->qos.min_turn_time.bits = qos_mtt_bits; + self->flags = IFF_SIR | IFF_PIO; + irda_qos_bits_to_value(&self->qos); /* Specify how much memory we want */ - self->idev.rx_buff.truesize = 4000; - self->idev.tx_buff.truesize = 4000; - - /* Initialize callbacks */ - self->idev.change_speed = irtty_change_speed; - self->idev.is_receiving = irtty_is_receiving; - self->idev.wait_until_sent = irtty_wait_until_sent; - self->idev.set_dtr_rts = irtty_set_dtr_rts; - self->idev.set_raw_mode = irtty_set_raw_mode; - self->idev.raw_write = irtty_raw_write; - self->idev.raw_read = irtty_raw_read; + self->rx_buff.truesize = 4000; + self->tx_buff.truesize = 4000; + + /* Allocate memory if needed */ + if (self->rx_buff.truesize > 0) { + self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize, + GFP_KERNEL); + if (self->rx_buff.head == NULL) + return -ENOMEM; + memset(self->rx_buff.head, 0, self->rx_buff.truesize); + } + if (self->tx_buff.truesize > 0) { + self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, + GFP_KERNEL); + if (self->tx_buff.head == NULL) { + kfree(self->rx_buff.head); + return -ENOMEM; + } + memset(self->tx_buff.head, 0, self->tx_buff.truesize); + } + + self->magic = IRTTY_MAGIC; + + self->rx_buff.in_frame = FALSE; + self->rx_buff.state = OUTSIDE_FRAME; + self->tx_buff.data = self->tx_buff.head; + self->rx_buff.data = self->rx_buff.head; + + if (!(dev = dev_alloc("irda%d", &err))) { + ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); + return -ENOMEM; + } + /* dev_alloc doesn't clear the struct */ + memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*)); + + dev->priv = (void *) self; + self->netdev = dev; /* Override the network functions we need to use */ - self->idev.netdev.init = irtty_net_init; - self->idev.netdev.hard_start_xmit = irtty_hard_xmit; - self->idev.netdev.open = irtty_net_open; - self->idev.netdev.stop = irtty_net_close; + dev->init = irtty_net_init; + dev->hard_start_xmit = irtty_hard_xmit; + dev->open = irtty_net_open; + dev->stop = irtty_net_close; + dev->get_stats = irtty_net_get_stats; + dev->do_ioctl = irtty_net_ioctl; + + rtnl_lock(); + err = register_netdevice(dev); + rtnl_unlock(); + if (err) { + ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); + return -1; + } - /* Open the IrDA device */ - irda_device_open(&self->idev, name, self); + MESSAGE("IrDA: Registered device %s\n", dev->name); MOD_INC_USE_COUNT; @@ -245,39 +279,50 @@ static void irtty_close(struct tty_struct *tty) /* First make sure we're connected. */ ASSERT(self != NULL, return;); ASSERT(self->magic == IRTTY_MAGIC, return;); - - /* Remove driver */ - irda_device_close(&self->idev); - + /* Stop tty */ tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); tty->disc_data = 0; - + + /* We are not using any dongle anymore! */ + if (self->dongle) + irda_device_dongle_cleanup(self->dongle); + self->dongle = NULL; + + /* Remove netdevice */ + if (self->netdev) { + rtnl_lock(); + unregister_netdevice(self->netdev); + rtnl_unlock(); + } + self->tty = NULL; self->magic = 0; self = hashbin_remove(irtty, (int) self, NULL); - - if (self != NULL) - kfree(self); + if (self->tx_buff.head) + kfree(self->tx_buff.head); + + if (self->rx_buff.head) + kfree(self->rx_buff.head); + + kfree(self); + MOD_DEC_USE_COUNT; } /* - * Function irtty_stop_receiver (irda_device, stop) + * Function irtty_stop_receiver (self, stop) * * * */ -static void irtty_stop_receiver(struct irda_device *idev, int stop) +static void irtty_stop_receiver(struct irtty_cb *self, int stop) { struct termios old_termios; - struct irtty_cb *self; int cflag; - self = (struct irtty_cb *) idev->priv; - old_termios = *(self->tty->termios); cflag = self->tty->termios->c_cflag; @@ -291,24 +336,16 @@ static void irtty_stop_receiver(struct irda_device *idev, int stop) } /* - * Function irtty_change_speed (self, speed) + * Function irtty_do_change_speed (self, speed) * - * Change the speed of the serial port. The driver layer must check that - * all transmission has finished using the irtty_wait_until_sent() - * function. + * Change the speed of the serial port. */ -static void irtty_change_speed(struct irda_device *idev, __u32 speed) +static void __irtty_change_speed(struct irtty_cb *self, __u32 speed) { struct termios old_termios; - struct irtty_cb *self; int cflag; - DEBUG(4, __FUNCTION__ "(), <%ld>\n", jiffies); - - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - - self = (struct irtty_cb *) idev->priv; + IRDA_DEBUG(0, __FUNCTION__ "(), <%ld>\n", jiffies); ASSERT(self != NULL, return;); ASSERT(self->magic == IRTTY_MAGIC, return;); @@ -318,7 +355,7 @@ static void irtty_change_speed(struct irda_device *idev, __u32 speed) cflag &= ~CBAUD; - DEBUG(4, __FUNCTION__ "(), Setting speed to %d\n", speed); + IRDA_DEBUG(0, __FUNCTION__ "(), Setting speed to %d\n", speed); switch (speed) { case 1200: @@ -350,6 +387,81 @@ static void irtty_change_speed(struct irda_device *idev, __u32 speed) self->tty->termios->c_cflag = cflag; self->tty->driver.set_termios(self->tty, &old_termios); + + self->io.speed = speed; +} + +/* + * Function irtty_change_speed (instance, state, param) + * + * State machine for changing speed of the device. We do it this way since + * we cannot use schedule_timeout() when we are in interrupt context + */ +static int irtty_change_speed(struct irda_task *task) +{ + struct irtty_cb *self; + __u32 speed = (__u32) task->param; + int ret = 0; + + IRDA_DEBUG(2, __FUNCTION__ "(), <%ld>\n", jiffies); + + self = (struct irtty_cb *) task->instance; + + ASSERT(self != NULL, return -1;); + + switch (task->state) { + case IRDA_TASK_INIT: + case IRDA_TASK_WAIT: + /* Are we ready to change speed yet? */ + if (self->tty->driver.chars_in_buffer(self->tty)) { + task->state = IRDA_TASK_WAIT; + + /* Try again later */ + ret = MSECS_TO_JIFFIES(20); + break; + } + + if (self->dongle) + irda_task_next_state(task, IRDA_TASK_CHILD_INIT); + else + irda_task_next_state(task, IRDA_TASK_CHILD_DONE); + break; + case IRDA_TASK_CHILD_INIT: + /* Go to default speed */ + __irtty_change_speed(self, 9600); + + /* Change speed of dongle */ + if (irda_task_execute(self->dongle, + self->dongle->issue->change_speed, + NULL, task, (void *) speed)) + { + /* Dongle need more time to change its speed */ + irda_task_next_state(task, IRDA_TASK_CHILD_WAIT); + + /* Give dongle 1 sec to finish */ + ret = MSECS_TO_JIFFIES(1000); + } else + /* Child finished immediately */ + irda_task_next_state(task, IRDA_TASK_CHILD_DONE); + break; + case IRDA_TASK_CHILD_WAIT: + WARNING(__FUNCTION__ + "(), changing speed of dongle timed out!\n"); + ret = -1; + break; + case IRDA_TASK_CHILD_DONE: + /* Finally we are ready to change the speed */ + __irtty_change_speed(self, speed); + + irda_task_next_state(task, IRDA_TASK_DONE); + break; + default: + ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); + irda_task_next_state(task, IRDA_TASK_DONE); + ret = -1; + break; + } + return ret; } /* @@ -360,9 +472,11 @@ static void irtty_change_speed(struct irda_device *idev, __u32 speed) */ static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg) { + dongle_t *dongle; + struct irtty_info info; struct irtty_cb *self; - int err = 0; int size = _IOC_SIZE(cmd); + int err = 0; self = (struct irtty_cb *) tty->disc_data; @@ -370,13 +484,13 @@ static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg) ASSERT(self->magic == IRTTY_MAGIC, return -EBADR;); if (_IOC_DIR(cmd) & _IOC_READ) - err = verify_area( VERIFY_WRITE, (void *) arg, size); + err = verify_area(VERIFY_WRITE, (void *) arg, size); else if (_IOC_DIR(cmd) & _IOC_WRITE) - err = verify_area( VERIFY_READ, (void *) arg, size); + err = verify_area(VERIFY_READ, (void *) arg, size); if (err) return err; - switch(cmd) { + switch (cmd) { case TCGETS: case TCGETA: return n_tty_ioctl(tty, (struct file *) file, cmd, @@ -384,7 +498,34 @@ static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg) break; case IRTTY_IOCTDONGLE: /* Initialize dongle */ - irda_device_init_dongle(&self->idev, (int) arg); + dongle = irda_device_dongle_init(self->netdev, (int) arg); + if (!dongle) + break; + + /* Initialize callbacks */ + dongle->set_mode = irtty_set_mode; + dongle->read = irtty_raw_read; + dongle->write = irtty_raw_write; + dongle->set_dtr_rts = irtty_set_dtr_rts; + + /* Bind dongle */ + self->dongle = dongle; + + /* Now initialize the dongle! */ + dongle->issue->open(dongle, &self->qos); + + /* Reset dongle */ + irda_task_execute(dongle, dongle->issue->reset, NULL, NULL, + NULL); + break; + case IRTTY_IOCGET: + ASSERT(self->netdev != NULL, return -1;); + + memset(&info, 0, sizeof(struct irtty_info)); + strncpy(info.name, self->netdev->name, 5); + + if (copy_to_user(arg, &info, sizeof(struct irtty_info))) + return -EFAULT; break; default: return -ENOIOCTLCMD; @@ -405,34 +546,61 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp, { struct irtty_cb *self = (struct irtty_cb *) tty->disc_data; - DEBUG(5, __FUNCTION__ "(,,,count=%d)\n", count); /* Read the characters out of the buffer */ while (count--) { /* * Characters received with a parity error, etc? */ if (fp && *fp++) { - DEBUG( 0, "Framing or parity error!\n"); - irda_device_set_media_busy(&self->idev.netdev, TRUE); - + IRDA_DEBUG(0, "Framing or parity error!\n"); + irda_device_set_media_busy(self->netdev, TRUE); + cp++; continue; } + + switch (self->mode) { + case IRDA_IRLAP: + /* Unwrap and destuff one byte */ + async_unwrap_char(self->netdev, &self->rx_buff, *cp++); + break; + case IRDA_RAW: + /* What should we do when the buffer is full? */ + if (self->rx_buff.len == self->rx_buff.truesize) + self->rx_buff.len = 0; + + self->rx_buff.data[self->rx_buff.len++] = *cp++; + break; + default: + break; + } + } +} - DEBUG(6, __FUNCTION__ " char=0x%02x\n", *cp); - if (self->idev.raw_mode) { - struct irda_device *idev = &self->idev; +/* + * Function irtty_change_speed_complete (task) + * + * Called when the change speed operation completes + * + */ +static int irtty_change_speed_complete(struct irda_task *task) +{ + struct irtty_cb *self; - /* What should we do when the buffer is full? */ - if (idev->rx_buff.len == idev->rx_buff.truesize) - idev->rx_buff.len = 0; + IRDA_DEBUG(0, __FUNCTION__ "()\n"); - idev->rx_buff.data[idev->rx_buff.len++] = *cp++; - } else { - /* Unwrap and destuff one byte */ - async_unwrap_char(&self->idev, *cp++); - } - } + self = (struct irtty_cb *) task->instance; + + ASSERT(self != NULL, return -1;); + ASSERT(self->netdev != NULL, return -1;); + + /* Finished changing speed, so we are not busy any longer */ + self->netdev->tbusy = 0; + + /* Signal network layer so it can try to send the frame */ + mark_bh(NET_BH); + + return 0; } /* @@ -444,29 +612,34 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp, static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev) { struct irtty_cb *self; - struct irda_device *idev; int actual = 0; + __u32 speed; - idev = (struct irda_device *) dev->priv; - - ASSERT(idev != NULL, return 0;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); - - self = (struct irtty_cb *) idev->priv; - + self = (struct irtty_cb *) dev->priv; ASSERT(self != NULL, return 0;); - ASSERT(self->magic == IRTTY_MAGIC, return 0;); /* Lock transmit buffer */ if (irda_lock((void *) &dev->tbusy) == FALSE) return -EBUSY; + + /* Check if we need to change the speed */ + if ((speed = irda_get_speed(skb)) != self->io.speed) { + if (irda_task_execute(self, irtty_change_speed, + irtty_change_speed_complete, NULL, + (void *) speed)) + /* + * Task not finished yet, so make the netdevice + * layer requeue the frame + */ + return -EBUSY; + } /* Init tx buffer*/ - idev->tx_buff.data = idev->tx_buff.head; + self->tx_buff.data = self->tx_buff.head; /* Copy skb to tx_buff while wrapping, stuffing and making CRC */ - idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, - idev->tx_buff.truesize); + self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, + self->tx_buff.truesize); self->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); @@ -474,22 +647,22 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev) if (self->tty->driver.write) actual = self->tty->driver.write(self->tty, 0, - idev->tx_buff.data, - idev->tx_buff.len); + self->tx_buff.data, + self->tx_buff.len); /* Hide the part we just transmitted */ - idev->tx_buff.data += actual; - idev->tx_buff.len -= actual; + self->tx_buff.data += actual; + self->tx_buff.len -= actual; - idev->stats.tx_packets++; - idev->stats.tx_bytes += idev->tx_buff.len; + self->stats.tx_packets++; + self->stats.tx_bytes += self->tx_buff.len; #if 0 /* * Did we transmit the whole frame? Commented out for now since * I must check if this optimalization really works. DB. */ - if ((idev->tx_buff.len) == 0) { - DEBUG( 4, "irtty_xmit_buf: finished with frame!\n"); + if ((self->tx_buff.len) == 0) { + IRDA_DEBUG( 4, "irtty_xmit_buf: finished with frame!\n"); self->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); irda_unlock( &self->tbusy); } @@ -507,7 +680,7 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev) */ static int irtty_receive_room(struct tty_struct *tty) { - DEBUG(0, __FUNCTION__ "()\n"); + IRDA_DEBUG(0, __FUNCTION__ "()\n"); return 65536; /* We can handle an infinite amount of data. :-) */ } @@ -521,7 +694,6 @@ static int irtty_receive_room(struct tty_struct *tty) static void irtty_write_wakeup(struct tty_struct *tty) { struct irtty_cb *self = (struct irtty_cb *) tty->disc_data; - struct irda_device *idev; int actual = 0; /* @@ -530,26 +702,24 @@ static void irtty_write_wakeup(struct tty_struct *tty) ASSERT(self != NULL, return;); ASSERT(self->magic == IRTTY_MAGIC, return;); - idev = &self->idev; - /* Finished with frame? */ - if (idev->tx_buff.len > 0) { + if (self->tx_buff.len > 0) { /* Write data left in transmit buffer */ - actual = tty->driver.write(tty, 0, idev->tx_buff.data, - idev->tx_buff.len); + actual = tty->driver.write(tty, 0, self->tx_buff.data, + self->tx_buff.len); - idev->tx_buff.data += actual; - idev->tx_buff.len -= actual; + self->tx_buff.data += actual; + self->tx_buff.len -= actual; } else { /* * Now serial buffer is almost free & we can start * transmission of another packet */ - DEBUG(5, __FUNCTION__ "(), finished with frame!\n"); + IRDA_DEBUG(5, __FUNCTION__ "(), finished with frame!\n"); tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); - idev->netdev.tbusy = 0; /* Unlock */ + self->netdev->tbusy = 0; /* Unlock */ /* Tell network layer that we want more frames */ mark_bh(NET_BH); @@ -557,34 +727,14 @@ static void irtty_write_wakeup(struct tty_struct *tty) } /* - * Function irtty_is_receiving (idev) + * Function irtty_is_receiving (self) * * Return TRUE is we are currently receiving a frame * */ -static int irtty_is_receiving(struct irda_device *idev) +static int irtty_is_receiving(struct irtty_cb *self) { - return (idev->rx_buff.state != OUTSIDE_FRAME); -} - -/* - * Function irtty_change_speed_ready (idev) - * - * Are we completely finished with transmitting frames so its possible - * to change the speed of the serial port. Warning this function must - * be called with a process context! - */ -static void irtty_wait_until_sent(struct irda_device *idev) -{ - struct irtty_cb *self = (struct irtty_cb *) idev->priv; - - ASSERT(self != NULL, return;); - ASSERT(self->magic == IRTTY_MAGIC, return;); - - DEBUG(4, "Chars in buffer %d\n", - self->tty->driver.chars_in_buffer(self->tty)); - - tty_wait_until_sent(self->tty, 0); + return (self->rx_buff.state != OUTSIDE_FRAME); } /* @@ -593,15 +743,14 @@ static void irtty_wait_until_sent(struct irda_device *idev) * This function can be used by dongles etc. to set or reset the status * of the dtr and rts lines */ -static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts) +static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts) { - struct tty_struct *tty; struct irtty_cb *self; + struct tty_struct *tty; mm_segment_t fs; int arg = 0; - self = (struct irtty_cb *) idev->priv; - + self = (struct irtty_cb *) dev->priv; tty = self->tty; #ifdef TIOCM_OUT2 /* Not defined for ARM */ @@ -627,52 +776,62 @@ static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts) ERROR(__FUNCTION__ "(), error doing ioctl!\n"); } set_fs(fs); + + return 0; } /* - * Function irtty_set_raw_mode (idev, status) + * Function irtty_set_mode (self, status) * * For the airport dongle, we need support for reading raw characters * from the IrDA device. This function switches between those modes. * FALSE is the default mode, and will then treat incoming data as IrDA * packets. */ -void irtty_set_raw_mode(struct irda_device *idev, int status) +int irtty_set_mode(struct net_device *dev, int mode) { struct irtty_cb *self; - DEBUG(2, __FUNCTION__ "(), status=%s\n", status ? "TRUE" : "FALSE"); + self = (struct irtty_cb *) dev->priv; - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - - self = (struct irtty_cb *) idev->priv; + ASSERT(self != NULL, return -1;); + IRDA_DEBUG(2, __FUNCTION__ "(), mode=%s\n", infrared_mode[mode]); + /* save status for driver */ - self->idev.raw_mode = status; + self->mode = mode; /* reset the buffer state */ - idev->rx_buff.data = idev->rx_buff.head; - idev->rx_buff.len = 0; - idev->rx_buff.state = OUTSIDE_FRAME; + self->rx_buff.data = self->rx_buff.head; + self->rx_buff.len = 0; + self->rx_buff.state = OUTSIDE_FRAME; + + return 0; } /* - * Function irtty_raw_read (idev, buf, len) + * Function irtty_raw_read (self, buf, len) * * Receive incomming data. This function sleeps, so it must only be * called with a process context. Timeout is currently defined to be * a multiple of 10 ms. */ -static int irtty_raw_read(struct irda_device *idev, __u8 *buf, int len, - int timeout) +static int irtty_raw_read(struct net_device *dev, __u8 *buf, int len) { + struct irtty_cb *self; int count; - buf = idev->rx_buff.data; + self = (struct irtty_cb *) dev->priv; + + ASSERT(self != NULL, return 0;); + ASSERT(self->magic == IRTTY_MAGIC, return 0;); + + return 0; +#if 0 + buf = self->rx_buff.data; /* Wait for the requested amount of data to arrive */ - while (len < idev->rx_buff.len) { + while (len < self->rx_buff.len) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(MSECS_TO_JIFFIES(10)); @@ -680,30 +839,27 @@ static int irtty_raw_read(struct irda_device *idev, __u8 *buf, int len, break; } - count = idev->rx_buff.len < len ? idev->rx_buff.len : len; + count = self->rx_buff.len < len ? self->rx_buff.len : len; /* * Reset the state, this mean that a raw read is sort of a * datagram read, and _not_ a stream style read. Be aware of the * difference. Implementing it the other way will just be painful ;-) */ - idev->rx_buff.data = idev->rx_buff.head; - idev->rx_buff.len = 0; - idev->rx_buff.state = OUTSIDE_FRAME; - + self->rx_buff.data = self->rx_buff.head; + self->rx_buff.len = 0; + self->rx_buff.state = OUTSIDE_FRAME; +#endif /* Return the amount we were able to get */ return count; } -static int irtty_raw_write(struct irda_device *idev, __u8 *buf, int len) +static int irtty_raw_write(struct net_device *dev, __u8 *buf, int len) { struct irtty_cb *self; int actual = 0; - ASSERT(idev != NULL, return 0;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); - - self = (struct irtty_cb *) idev->priv; + self = (struct irtty_cb *) dev->priv; ASSERT(self != NULL, return 0;); ASSERT(self->magic == IRTTY_MAGIC, return 0;); @@ -714,8 +870,6 @@ static int irtty_raw_write(struct irda_device *idev, __u8 *buf, int len) return actual; } - - static int irtty_net_init(struct net_device *dev) { /* Set up to be a normal IrDA network device driver */ @@ -728,12 +882,26 @@ static int irtty_net_init(struct net_device *dev) static int irtty_net_open(struct net_device *dev) { - struct irda_device *idev = dev->priv; + struct irtty_cb *self = (struct irtty_cb *) dev->priv; - irda_device_net_open(dev); + ASSERT(self != NULL, return -1;); + ASSERT(self->magic == IRTTY_MAGIC, return -1;); + + IRDA_DEBUG(0, __FUNCTION__ "()\n"); + + /* Ready to play! */ + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; /* Make sure we can receive more data */ - irtty_stop_receiver(idev, FALSE); + irtty_stop_receiver(self, FALSE); + + /* + * Open new IrLAP layer instance, now that everything should be + * initialized properly + */ + self->irlap = irlap_open(dev, &self->qos); MOD_INC_USE_COUNT; @@ -742,18 +910,105 @@ static int irtty_net_open(struct net_device *dev) static int irtty_net_close(struct net_device *dev) { - struct irda_device *idev = dev->priv; + struct irtty_cb *self = (struct irtty_cb *) dev->priv; + + ASSERT(self != NULL, return -1;); + ASSERT(self->magic == IRTTY_MAGIC, return -1;); /* Make sure we don't receive more data */ - irtty_stop_receiver(idev, TRUE); + irtty_stop_receiver(self, TRUE); - irda_device_net_close(dev); + /* Stop device */ + dev->tbusy = 1; + dev->start = 0; + + /* Stop and remove instance of IrLAP */ + if (self->irlap) + irlap_close(self->irlap); + self->irlap = NULL; MOD_DEC_USE_COUNT; return 0; } +/* + * Function irtty_net_ioctl (dev, rq, cmd) + * + * Process IOCTL commands for this device + * + */ +static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct if_irda_req *irq = (struct if_irda_req *) rq; + struct irtty_cb *self; + dongle_t *dongle; + unsigned long flags; + int ret = 0; + + ASSERT(dev != NULL, return -1;); + + self = dev->priv; + + ASSERT(self != NULL, return -1;); + ASSERT(self->magic == IRTTY_MAGIC, return -1;); + + IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); + + /* Disable interrupts & save flags */ + save_flags(flags); + cli(); + + switch (cmd) { + case SIOCSBANDWIDTH: /* Set bandwidth */ + irda_task_execute(self, irtty_change_speed, NULL, NULL, + (void *) irq->ifr_baudrate); + break; + case SIOCSDONGLE: /* Set dongle */ + /* Initialize dongle */ + dongle = irda_device_dongle_init(dev, irq->ifr_dongle); + if (!dongle) + break; + + dongle->set_mode = irtty_set_mode; + dongle->read = irtty_raw_read; + dongle->write = irtty_raw_write; + dongle->set_dtr_rts = irtty_set_dtr_rts; + + self->dongle = dongle; + + /* Now initialize the dongle! */ + dongle->issue->open(dongle, &self->qos); + + /* Reset dongle */ + irda_task_execute(dongle, dongle->issue->reset, NULL, NULL, + NULL); + break; + case SIOCSMEDIABUSY: /* Set media busy */ + irda_device_set_media_busy(self->netdev, TRUE); + break; + case SIOCGRECEIVING: /* Check if we are receiving right now */ + irq->ifr_receiving = irtty_is_receiving(self); + break; + case SIOCSDTRRTS: + irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts); + break; + default: + ret = -EOPNOTSUPP; + } + + restore_flags(flags); + + return ret; +} + +static struct net_device_stats *irtty_net_get_stats(struct net_device *dev) +{ + struct irtty_cb *self = (struct irtty_cb *) dev->priv; + + return &self->stats; +} + #ifdef MODULE MODULE_AUTHOR("Dag Brattli "); diff --git a/drivers/net/irda/litelink.c b/drivers/net/irda/litelink.c index 203838cea..f5da3faf6 100644 --- a/drivers/net/irda/litelink.c +++ b/drivers/net/irda/litelink.c @@ -6,7 +6,7 @@ * Status: Stable * Author: Dag Brattli * Created at: Fri May 7 12:50:33 1999 - * Modified at: Sat Jun 26 17:01:05 1999 + * Modified at: Mon Oct 18 12:45:51 1999 * Modified by: Dag Brattli * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -37,27 +37,25 @@ #include #include #include -#include #define MIN_DELAY 25 /* 15 us, but wait a little more to be sure */ #define MAX_DELAY 10000 /* 1 ms */ -static void litelink_open(struct irda_device *idev, int type); -static void litelink_close(struct irda_device *dev); -static void litelink_change_speed(struct irda_device *dev, __u32); -static void litelink_reset(struct irda_device *dev); -static void litelink_init_qos(struct irda_device *idev, struct qos_info *qos); +static void litelink_open(dongle_t *self, struct qos_info *qos); +static void litelink_close(dongle_t *self); +static int litelink_change_speed(struct irda_task *task); +static int litelink_reset(struct irda_task *task); /* These are the baudrates supported */ static __u32 baud_rates[] = { 115200, 57600, 38400, 19200, 9600 }; -static struct dongle dongle = { - LITELINK_DONGLE, +static struct dongle_reg dongle = { + Q_NULL, + IRDA_LITELINK_DONGLE, litelink_open, litelink_close, litelink_reset, litelink_change_speed, - litelink_init_qos, }; int __init litelink_init(void) @@ -70,114 +68,102 @@ void litelink_cleanup(void) irda_device_unregister_dongle(&dongle); } -static void litelink_open(struct irda_device *idev, int type) +static void litelink_open(dongle_t *self, struct qos_info *qos) { - strcat(idev->description, " <-> litelink"); - - idev->io.dongle_id = type; - idev->flags |= IFF_DONGLE; + qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; + qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */ MOD_INC_USE_COUNT; } -static void litelink_close(struct irda_device *idev) +static void litelink_close(dongle_t *self) { /* Power off dongle */ - irda_device_set_dtr_rts(idev, FALSE, FALSE); + self->set_dtr_rts(self->dev, FALSE, FALSE); MOD_DEC_USE_COUNT; } /* - * Function litelink_change_speed (idev, speed) + * Function litelink_change_speed (task) * * Change speed of the Litelink dongle. To cycle through the available * baud rates, pulse RTS low for a few ms. */ -static void litelink_change_speed(struct irda_device *idev, __u32 speed) +static int litelink_change_speed(struct irda_task *task) { + dongle_t *self = (dongle_t *) task->instance; + __u32 speed = (__u32) task->param; int i; - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - /* Clear RTS to reset dongle */ - irda_device_set_dtr_rts(idev, TRUE, FALSE); + self->set_dtr_rts(self->dev, TRUE, FALSE); /* Sleep a minimum of 15 us */ udelay(MIN_DELAY); /* Go back to normal mode */ - irda_device_set_dtr_rts(idev, TRUE, TRUE); + self->set_dtr_rts(self->dev, TRUE, TRUE); /* Sleep a minimum of 15 us */ udelay(MIN_DELAY); /* Cycle through avaiable baudrates until we reach the correct one */ for (i=0; i<5 && baud_rates[i] != speed; i++) { - /* Set DTR, clear RTS */ - irda_device_set_dtr_rts(idev, FALSE, TRUE); + self->set_dtr_rts(self->dev, FALSE, TRUE); /* Sleep a minimum of 15 us */ udelay(MIN_DELAY); /* Set DTR, Set RTS */ - irda_device_set_dtr_rts(idev, TRUE, TRUE); + self->set_dtr_rts(self->dev, TRUE, TRUE); /* Sleep a minimum of 15 us */ udelay(MIN_DELAY); } + + irda_task_next_state(task, IRDA_TASK_DONE); + + return 0; } /* - * Function litelink_reset (dev) + * Function litelink_reset (task) * * Reset the Litelink type dongle. Warning, this function must only be * called with a process context! * */ -static void litelink_reset(struct irda_device *idev) +static int litelink_reset(struct irda_task *task) { - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - + dongle_t *self = (dongle_t *) task->instance; + /* Power on dongle */ - irda_device_set_dtr_rts(idev, TRUE, TRUE); + self->set_dtr_rts(self->dev, TRUE, TRUE); /* Sleep a minimum of 15 us */ udelay(MIN_DELAY); /* Clear RTS to reset dongle */ - irda_device_set_dtr_rts(idev, TRUE, FALSE); + self->set_dtr_rts(self->dev, TRUE, FALSE); /* Sleep a minimum of 15 us */ udelay(MIN_DELAY); /* Go back to normal mode */ - irda_device_set_dtr_rts(idev, TRUE, TRUE); + self->set_dtr_rts(self->dev, TRUE, TRUE); /* Sleep a minimum of 15 us */ udelay(MIN_DELAY); /* This dongles speed defaults to 115200 bps */ - idev->qos.baud_rate.value = 115200; -} + self->speed = 115200; -/* - * Function litelink_init_qos (qos) - * - * Initialize QoS capabilities - * - */ -static void litelink_init_qos(struct irda_device *idev, struct qos_info *qos) -{ - qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; - qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */ + return 0; } #ifdef MODULE - MODULE_AUTHOR("Dag Brattli "); MODULE_DESCRIPTION("Parallax Litelink dongle driver"); @@ -202,5 +188,4 @@ void cleanup_module(void) { litelink_cleanup(); } - -#endif +#endif /* MODULE */ diff --git a/drivers/net/irda/pc87108.c b/drivers/net/irda/pc87108.c index 3b575d01e..fae329ac9 100644 --- a/drivers/net/irda/pc87108.c +++ b/drivers/net/irda/pc87108.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Nov 7 21:43:15 1998 - * Modified at: Wed Aug 11 09:26:26 1999 + * Modified at: Wed Oct 20 00:08:41 1999 * Modified by: Dag Brattli * * Copyright (c) 1998-1999 Dag Brattli @@ -29,11 +29,11 @@ * * __u8 bank; * - * bank = inb( iobase+BSR); + * bank = inb(iobase+BSR); * * do_your_stuff_here(); * - * outb( bank, iobase+BSR); + * outb(bank, iobase+BSR); * * If you find bugs in this file, its very likely that the same bug * will also be in w83977af_ir.c since the implementations is quite @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -101,19 +102,19 @@ static char *dongle_types[] = { static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr, unsigned int irq, unsigned int dma); #ifdef MODULE -static int pc87108_close(struct irda_device *idev); +static int pc87108_close(struct pc87108 *self); #endif /* MODULE */ static int pc87108_probe(int iobase, int board_addr, int irq, int dma); -static void pc87108_pio_receive(struct irda_device *idev); -static int pc87108_dma_receive(struct irda_device *idev); -static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase); +static void pc87108_pio_receive(struct pc87108 *self); +static int pc87108_dma_receive(struct pc87108 *self); +static int pc87108_dma_receive_complete(struct pc87108 *self, int iobase); static int pc87108_hard_xmit(struct sk_buff *skb, struct net_device *dev); static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size); -static void pc87108_dma_write(struct irda_device *idev, int iobase); -static void pc87108_change_speed(struct irda_device *idev, __u32 baud); +static void pc87108_dma_write(struct pc87108 *self, int iobase); +static void pc87108_change_speed(struct pc87108 *self, __u32 baud); static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void pc87108_wait_until_sent(struct irda_device *idev); -static int pc87108_is_receiving(struct irda_device *idev); +static void pc87108_wait_until_sent(struct pc87108 *self); +static int pc87108_is_receiving(struct pc87108 *self); static int pc87108_read_dongle_id (int iobase); static void pc87108_init_dongle_interface (int iobase, int dongle_id); @@ -152,11 +153,11 @@ static void pc87108_cleanup(void) { int i; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); for (i=0; i < 4; i++) { if (dev_self[i]) - pc87108_close(&(dev_self[i]->idev)); + pc87108_close(dev_self[i]); } } #endif /* MODULE */ @@ -170,12 +171,13 @@ static void pc87108_cleanup(void) static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr, unsigned int irq, unsigned int dma) { + struct net_device *dev; struct pc87108 *self; - struct irda_device *idev; - int ret; int dongle_id; + int ret; + int err; - DEBUG(0, __FUNCTION__ "()\n"); + IRDA_DEBUG(0, __FUNCTION__ "()\n"); if ((dongle_id = pc87108_probe(iobase, board_addr, irq, dma)) == -1) return -1; @@ -194,90 +196,127 @@ static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr, /* Need to store self somewhere */ dev_self[i] = self; - idev = &self->idev; - /* Initialize IO */ - idev->io.iobase = iobase; - idev->io.irq = irq; - idev->io.io_ext = CHIP_IO_EXTENT; - idev->io.dma = dma; - idev->io.fifo_size = 32; + self->io.iobase = iobase; + self->io.irq = irq; + self->io.io_ext = CHIP_IO_EXTENT; + self->io.dma = dma; + self->io.fifo_size = 32; /* Lock the port that we need */ - ret = check_region(idev->io.iobase, idev->io.io_ext); + ret = check_region(self->io.iobase, self->io.io_ext); if (ret < 0) { - DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", - idev->io.iobase); - /* pc87108_cleanup( self->idev); */ + IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", + self->io.iobase); + /* pc87108_cleanup(self->self); */ return -ENODEV; } - request_region(idev->io.iobase, idev->io.io_ext, idev->name); + request_region(self->io.iobase, self->io.io_ext, driver_name); /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&idev->qos); + irda_init_max_qos_capabilies(&self->qos); /* The only value we must override it the baudrate */ - idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| + self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8); - idev->qos.min_turn_time.bits = qos_mtt_bits; - irda_qos_bits_to_value(&idev->qos); + self->qos.min_turn_time.bits = qos_mtt_bits; + irda_qos_bits_to_value(&self->qos); - idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE; - - /* Specify which buffer allocation policy we need */ - idev->rx_buff.flags = GFP_KERNEL | GFP_DMA; - idev->tx_buff.flags = GFP_KERNEL | GFP_DMA; + self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE; /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ - idev->rx_buff.truesize = 14384; - idev->tx_buff.truesize = 4000; + self->rx_buff.truesize = 14384; + self->tx_buff.truesize = 4000; + + /* Allocate memory if needed */ + if (self->rx_buff.truesize > 0) { + self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize, + GFP_KERNEL|GFP_DMA); + if (self->rx_buff.head == NULL) + return -ENOMEM; + memset(self->rx_buff.head, 0, self->rx_buff.truesize); + } + if (self->tx_buff.truesize > 0) { + self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, + GFP_KERNEL|GFP_DMA); + if (self->tx_buff.head == NULL) { + kfree(self->rx_buff.head); + return -ENOMEM; + } + memset(self->tx_buff.head, 0, self->tx_buff.truesize); + } + + self->rx_buff.in_frame = FALSE; + self->rx_buff.state = OUTSIDE_FRAME; + self->tx_buff.data = self->tx_buff.head; + self->rx_buff.data = self->rx_buff.head; - /* Initialize callbacks */ - idev->change_speed = pc87108_change_speed; - idev->wait_until_sent = pc87108_wait_until_sent; - idev->is_receiving = pc87108_is_receiving; - + if (!(dev = dev_alloc("irda%d", &err))) { + ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); + return -ENOMEM; + } + /* dev_alloc doesn't clear the struct, so lets do a little hack */ + memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*)); + + dev->priv = (void *) self; + self->netdev = dev; + /* Override the network functions we need to use */ - idev->netdev.init = pc87108_net_init; - idev->netdev.hard_start_xmit = pc87108_hard_xmit; - idev->netdev.open = pc87108_net_open; - idev->netdev.stop = pc87108_net_close; + dev->init = pc87108_net_init; + dev->hard_start_xmit = pc87108_hard_xmit; + dev->open = pc87108_net_open; + dev->stop = pc87108_net_close; + + rtnl_lock(); + err = register_netdevice(dev); + rtnl_unlock(); + if (err) { + ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); + return -1; + } - idev->io.dongle_id = dongle_id; + MESSAGE("IrDA: Registered device %s\n", dev->name); + + self->io.dongle_id = dongle_id; pc87108_init_dongle_interface(iobase, dongle_id); - /* Open the IrDA device */ - irda_device_open(idev, driver_name, self); - return 0; } #ifdef MODULE /* - * Function pc87108_close (idev) + * Function pc87108_close (self) * * Close driver instance * */ -static int pc87108_close(struct irda_device *idev) +static int pc87108_close(struct pc87108 *self) { - struct pc87108 *self; int iobase; - DEBUG( 4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); + + ASSERT(self != NULL, return -1;); - ASSERT(idev != NULL, return -1;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); + iobase = self->io.iobase; - iobase = idev->io.iobase; - self = (struct pc87108 *) idev->priv; + /* Remove netdevice */ + if (self->netdev) { + rtnl_lock(); + unregister_netdev(self->netdev); + rtnl_unlock(); + } /* Release the PORT that this driver is using */ - DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase); - release_region(idev->io.iobase, idev->io.io_ext); + IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", self->io.iobase); + release_region(self->io.iobase, self->io.io_ext); - irda_device_close(idev); + if (self->tx_buff.head) + kfree(self->tx_buff.head); + + if (self->rx_buff.head) + kfree(self->rx_buff.head); kfree(self); @@ -297,7 +336,7 @@ static int pc87108_probe(int iobase, int board_addr, int irq, int dma) __u8 temp=0; int dongle_id; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); /* Base Address and Interrupt Control Register BAIC */ outb(0, board_addr); @@ -326,7 +365,7 @@ static int pc87108_probe(int iobase, int board_addr, int irq, int dma) case 0: outb(0x08+temp, board_addr+1); break; case 1: outb(0x10+temp, board_addr+1); break; case 3: outb(0x18+temp, board_addr+1); break; - default: DEBUG( 0, __FUNCTION__ "(), invalid dma"); + default: IRDA_DEBUG(0, __FUNCTION__ "(), invalid dma"); } /* Mode Control Register MCTL */ @@ -344,13 +383,13 @@ static int pc87108_probe(int iobase, int board_addr, int irq, int dma) } /* Switch to advanced mode */ - switch_bank( iobase, BANK2); + switch_bank(iobase, BANK2); outb(ECR1_EXT_SL, iobase+ECR1); switch_bank(iobase, BANK0); dongle_id = pc87108_read_dongle_id(iobase); - DEBUG(0, __FUNCTION__ "(), Found dongle: %s\n", - dongle_types[ dongle_id]); + IRDA_DEBUG(0, __FUNCTION__ "(), Found dongle: %s\n", + dongle_types[dongle_id]); /* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */ switch_bank(iobase, BANK0); @@ -380,7 +419,7 @@ static int pc87108_probe(int iobase, int board_addr, int irq, int dma) outb(2048 & 0xff, iobase+4); outb((2048 >> 8) & 0x1f, iobase+5); - DEBUG(0, "PC87108 driver loaded. Version: 0x%02x\n", version); + IRDA_DEBUG(0, "PC87108 driver loaded. Version: 0x%02x\n", version); /* Enable receive interrupts */ switch_bank(iobase, BANK0); @@ -397,14 +436,14 @@ static int pc87108_probe(int iobase, int board_addr, int irq, int dma) * that the user may have plugged/unplugged the IrDA Dongle. * */ -static int pc87108_read_dongle_id ( int iobase) +static int pc87108_read_dongle_id (int iobase) { int dongle_id; __u8 bank; - DEBUG( 4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); - bank = inb( iobase+BSR); + bank = inb(iobase+BSR); /* Select Bank 7 */ switch_bank(iobase, BANK7); @@ -416,7 +455,7 @@ static int pc87108_read_dongle_id ( int iobase) udelay(50); /* IRCFG1: read the ID bits */ - dongle_id = inb( iobase+4) & 0x0f; + dongle_id = inb(iobase+4) & 0x0f; #ifdef BROKEN_DONGLE_ID if (dongle_id == 0x0a) @@ -426,7 +465,7 @@ static int pc87108_read_dongle_id ( int iobase) /* Go back to bank 0 before returning */ switch_bank(iobase, BANK0); - DEBUG(0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id); + IRDA_DEBUG(0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id); outb(bank, iobase+BSR); @@ -446,49 +485,49 @@ static void pc87108_init_dongle_interface (int iobase, int dongle_id) int bank; /* Save current bank */ - bank = inb( iobase+BSR); + bank = inb(iobase+BSR); /* Select Bank 7 */ - switch_bank( iobase, BANK7); + switch_bank(iobase, BANK7); /* IRCFG4: set according to dongle_id */ switch (dongle_id) { case 0x00: /* same as */ case 0x01: /* Differential serial interface */ - DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", dongle_types[dongle_id]); break; case 0x02: /* same as */ case 0x03: /* Reserved */ - DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", dongle_types[dongle_id]); break; case 0x04: /* Sharp RY5HD01 */ - DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n", dongle_types[dongle_id]); break; case 0x05: /* Reserved */ - DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet", + IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet", dongle_types[dongle_id]); break; case 0x06: /* Single-ended serial interface */ - DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", dongle_types[dongle_id]); break; case 0x07: /* Consumer-IR only */ - DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n", dongle_types[dongle_id]); break; case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */ - DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n", dongle_types[dongle_id]); break; case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */ - outb_p( 0x28, iobase+7); /* Set irsl[0-2] as output */ + outb_p(0x28, iobase+7); /* Set irsl[0-2] as output */ break; case 0x0A: /* same as */ case 0x0B: /* Reserved */ - DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", dongle_types[dongle_id]); break; case 0x0C: /* same as */ @@ -497,28 +536,28 @@ static void pc87108_init_dongle_interface (int iobase, int dongle_id) * Set irsl0 as input, irsl[1-2] as output, and separate * inputs are used for SIR and MIR/FIR */ - outb( 0x48, iobase+7); + outb(0x48, iobase+7); break; case 0x0E: /* Supports SIR Mode only */ - outb( 0x28, iobase+7); /* Set irsl[0-2] as output */ + outb(0x28, iobase+7); /* Set irsl[0-2] as output */ break; case 0x0F: /* No dongle connected */ - DEBUG( 0, __FUNCTION__ "(), %s\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s\n", dongle_types[dongle_id]); - DEBUG( 0, "***\n"); + IRDA_DEBUG(0, "***\n"); - switch_bank( iobase, BANK0); - outb( 0x62, iobase+MCR); + switch_bank(iobase, BANK0); + outb(0x62, iobase+MCR); break; default: - DEBUG( 0, __FUNCTION__ "(), invalid dongle_id %#x", dongle_id); + IRDA_DEBUG(0, __FUNCTION__ "(), invalid dongle_id %#x", dongle_id); } /* IRCFG1: IRSL1 and 2 are set to IrDA mode */ - outb( 0x00, iobase+4); + outb(0x00, iobase+4); /* Restore bank register */ - outb( bank, iobase+BSR); + outb(bank, iobase+BSR); } /* set_up_dongle_interface */ @@ -528,66 +567,66 @@ static void pc87108_init_dongle_interface (int iobase, int dongle_id) * Change speed of the attach dongle * */ -static void pc87108_change_dongle_speed( int iobase, int speed, int dongle_id) +static void pc87108_change_dongle_speed(int iobase, int speed, int dongle_id) { unsigned long flags; __u8 bank; - DEBUG( 4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); /* Save current bank */ - bank = inb( iobase+BSR); + bank = inb(iobase+BSR); /* Select Bank 7 */ - switch_bank( iobase, BANK7); + switch_bank(iobase, BANK7); /* IRCFG1: set according to dongle_id */ switch (dongle_id) { case 0x00: /* same as */ case 0x01: /* Differential serial interface */ - DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", dongle_types[dongle_id]); break; case 0x02: /* same as */ case 0x03: /* Reserved */ - DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", dongle_types[dongle_id]); break; case 0x04: /* Sharp RY5HD01 */ - DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n", dongle_types[dongle_id]); case 0x05: /* Reserved */ - DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", dongle_types[dongle_id]); break; case 0x06: /* Single-ended serial interface */ - DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", dongle_types[dongle_id]); break; case 0x07: /* Consumer-IR only */ - DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n", dongle_types[dongle_id]); break; case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */ - DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n", dongle_types[dongle_id]); case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */ - switch_bank( iobase, BANK7); - outb_p( 0x01, iobase+4); + switch_bank(iobase, BANK7); + outb_p(0x01, iobase+4); - if ( speed == 4000000) { + if (speed == 4000000) { save_flags(flags); cli(); - outb( 0x81, iobase+4); - outb( 0x80, iobase+4); + outb(0x81, iobase+4); + outb(0x80, iobase+4); restore_flags(flags); } else - outb_p( 0x00, iobase+4); + outb_p(0x00, iobase+4); break; case 0x0A: /* same as */ case 0x0B: /* Reserved */ - DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", dongle_types[dongle_id]); break; case 0x0C: /* same as */ @@ -596,78 +635,77 @@ static void pc87108_change_dongle_speed( int iobase, int speed, int dongle_id) case 0x0E: /* Supports SIR Mode only */ break; case 0x0F: /* No dongle connected */ - DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n", + IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n", dongle_types[dongle_id]); - switch_bank( iobase, BANK0); - outb( 0x62, iobase+MCR); + switch_bank(iobase, BANK0); + outb(0x62, iobase+MCR); break; default: - DEBUG( 0, __FUNCTION__ "(), invalid data_rate\n"); + IRDA_DEBUG(0, __FUNCTION__ "(), invalid data_rate\n"); } /* Restore bank register */ - outb( bank, iobase+BSR); + outb(bank, iobase+BSR); } /* - * Function pc87108_change_speed (idev, baud) + * Function pc87108_change_speed (self, baud) * * Change the speed of the device * */ -static void pc87108_change_speed(struct irda_device *idev, __u32 speed) +static void pc87108_change_speed(struct pc87108 *self, __u32 speed) { __u8 mcr = MCR_SIR; __u8 bank; int iobase; - DEBUG( 4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( idev != NULL, return;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(self != NULL, return;); - iobase = idev->io.iobase; + iobase = self->io.iobase; /* Update accounting for new speed */ - idev->io.baudrate = speed; + self->io.speed = speed; /* Save current bank */ - bank = inb( iobase+BSR); + bank = inb(iobase+BSR); /* Disable interrupts */ - switch_bank( iobase, BANK0); - outb( 0, iobase+IER); + switch_bank(iobase, BANK0); + outb(0, iobase+IER); /* Select Bank 2 */ - switch_bank( iobase, BANK2); - - outb( 0x00, iobase+BGDH); - switch ( speed) { - case 9600: outb( 0x0c, iobase+BGDL); break; - case 19200: outb( 0x06, iobase+BGDL); break; - case 37600: outb( 0x03, iobase+BGDL); break; - case 57600: outb( 0x02, iobase+BGDL); break; - case 115200: outb( 0x01, iobase+BGDL); break; + switch_bank(iobase, BANK2); + + outb(0x00, iobase+BGDH); + switch (speed) { + case 9600: outb(0x0c, iobase+BGDL); break; + case 19200: outb(0x06, iobase+BGDL); break; + case 37600: outb(0x03, iobase+BGDL); break; + case 57600: outb(0x02, iobase+BGDL); break; + case 115200: outb(0x01, iobase+BGDL); break; case 576000: - switch_bank( iobase, BANK5); + switch_bank(iobase, BANK5); /* IRCR2: MDRS is set */ - outb( inb( iobase+4) | 0x04, iobase+4); + outb(inb(iobase+4) | 0x04, iobase+4); mcr = MCR_MIR; - DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n"); + IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n"); break; case 1152000: mcr = MCR_MIR; - DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n"); + IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n"); break; case 4000000: mcr = MCR_FIR; - DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n"); + IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n"); break; default: mcr = MCR_FIR; - DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed); + IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed); break; } @@ -676,34 +714,34 @@ static void pc87108_change_speed(struct irda_device *idev, __u32 speed) outb(mcr | MCR_TX_DFR, iobase+MCR); /* Give some hits to the transceiver */ - pc87108_change_dongle_speed( iobase, speed, idev->io.dongle_id); + pc87108_change_dongle_speed(iobase, speed, self->io.dongle_id); /* Set FIFO threshold to TX17, RX16 */ - switch_bank( iobase, BANK0); - outb( FCR_RXTH| /* Set Rx FIFO threshold */ + switch_bank(iobase, BANK0); + outb(FCR_RXTH| /* Set Rx FIFO threshold */ FCR_TXTH| /* Set Tx FIFO threshold */ FCR_TXSR| /* Reset Tx FIFO */ FCR_RXSR| /* Reset Rx FIFO */ FCR_FIFO_EN, /* Enable FIFOs */ iobase+FCR); - /* outb( 0xa7, iobase+FCR); */ + /* outb(0xa7, iobase+FCR); */ /* Set FIFO size to 32 */ - switch_bank( iobase, BANK2); - outb( EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2); + switch_bank(iobase, BANK2); + outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2); - idev->netdev.tbusy = 0; + self->netdev->tbusy = 0; /* Enable some interrupts so we can receive frames */ - switch_bank( iobase, BANK0); - if ( speed > 115200) { - outb( IER_SFIF_IE, iobase+IER); - pc87108_dma_receive( idev); + switch_bank(iobase, BANK0); + if (speed > 115200) { + outb(IER_SFIF_IE, iobase+IER); + pc87108_dma_receive(self); } else - outb( IER_RXHDL_IE, iobase+IER); + outb(IER_RXHDL_IE, iobase+IER); /* Restore BSR */ - outb( bank, iobase+BSR); + outb(bank, iobase+BSR); } /* @@ -712,107 +750,106 @@ static void pc87108_change_speed(struct irda_device *idev, __u32 speed) * Transmit the frame! * */ -static int pc87108_hard_xmit( struct sk_buff *skb, struct net_device *dev) +static int pc87108_hard_xmit(struct sk_buff *skb, struct net_device *dev) { - struct irda_device *idev; + struct pc87108 *self; int iobase; __u8 bank; int mtt; - idev = (struct irda_device *) dev->priv; + self = (struct pc87108 *) dev->priv; - ASSERT( idev != NULL, return 0;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;); + ASSERT(self != NULL, return 0;); - iobase = idev->io.iobase; + iobase = self->io.iobase; - DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len); + IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len); /* Lock transmit buffer */ - if ( irda_lock( (void *) &dev->tbusy) == FALSE) + if (irda_lock((void *) &dev->tbusy) == FALSE) return -EBUSY; /* Save current bank */ - bank = inb( iobase+BSR); + bank = inb(iobase+BSR); /* Decide if we should use PIO or DMA transfer */ - if ( idev->io.baudrate > 115200) { - idev->tx_buff.data = idev->tx_buff.head; - memcpy(idev->tx_buff.data, skb->data, skb->len); - idev->tx_buff.len = skb->len; + if (self->io.speed > 115200) { + self->tx_buff.data = self->tx_buff.head; + memcpy(self->tx_buff.data, skb->data, skb->len); + self->tx_buff.len = skb->len; - mtt = irda_get_mtt( skb); - if ( mtt > 50) { + mtt = irda_get_mtt(skb); + if (mtt > 50) { /* Adjust for timer resolution */ mtt = mtt / 125 + 1; /* Setup timer */ - switch_bank( iobase, BANK4); - outb( mtt & 0xff, iobase+TMRL); - outb(( mtt >> 8) & 0x0f, iobase+TMRH); + switch_bank(iobase, BANK4); + outb(mtt & 0xff, iobase+TMRL); + outb((mtt >> 8) & 0x0f, iobase+TMRH); /* Start timer */ - outb( IRCR1_TMR_EN, iobase+IRCR1); - idev->io.direction = IO_XMIT; + outb(IRCR1_TMR_EN, iobase+IRCR1); + self->io.direction = IO_XMIT; /* Enable timer interrupt */ - switch_bank( iobase, BANK0); - outb( IER_TMR_IE, iobase+IER); + switch_bank(iobase, BANK0); + outb(IER_TMR_IE, iobase+IER); } else { /* Use udelay for delays less than 50 us. */ if (mtt) - udelay( mtt); + udelay(mtt); /* Enable DMA interrupt */ - switch_bank( iobase, BANK0); - outb( IER_DMA_IE, iobase+IER); - pc87108_dma_write( idev, iobase); + switch_bank(iobase, BANK0); + outb(IER_DMA_IE, iobase+IER); + pc87108_dma_write(self, iobase); } } else { - idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, - idev->tx_buff.truesize); + self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, + self->tx_buff.truesize); - idev->tx_buff.data = idev->tx_buff.head; + self->tx_buff.data = self->tx_buff.head; /* Add interrupt on tx low level (will fire immediately) */ - switch_bank( iobase, BANK0); - outb( IER_TXLDL_IE, iobase+IER); + switch_bank(iobase, BANK0); + outb(IER_TXLDL_IE, iobase+IER); } - dev_kfree_skb( skb); + dev_kfree_skb(skb); /* Restore bank register */ - outb( bank, iobase+BSR); + outb(bank, iobase+BSR); return 0; } /* - * Function pc87108_dma_xmit (idev, iobase) + * Function pc87108_dma_xmit (self, iobase) * * Transmit data using DMA * */ -static void pc87108_dma_write( struct irda_device *idev, int iobase) +static void pc87108_dma_write(struct pc87108 *self, int iobase) { int bsr; - DEBUG( 4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); /* Save current bank */ - bsr = inb( iobase+BSR); + bsr = inb(iobase+BSR); /* Disable DMA */ switch_bank(iobase, BANK0); - outb( inb( iobase+MCR) & ~MCR_DMA_EN, iobase+MCR); + outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR); - setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, + setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, DMA_MODE_WRITE); - idev->io.direction = IO_XMIT; + self->io.direction = IO_XMIT; /* Choose transmit DMA channel */ switch_bank(iobase, BANK2); - outb( inb( iobase+ECR1) | ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, + outb(inb(iobase+ECR1) | ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1); /* Enable DMA */ @@ -824,7 +861,7 @@ static void pc87108_dma_write( struct irda_device *idev, int iobase) } /* - * Function pc87108_pio_xmit (idev, iobase) + * Function pc87108_pio_xmit (self, iobase) * * Transmit data using PIO. Returns the number of bytes that actually * got transfered @@ -835,17 +872,17 @@ static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size) int actual = 0; __u8 bank; - DEBUG( 4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); /* Save current bank */ - bank = inb( iobase+BSR); + bank = inb(iobase+BSR); - switch_bank( iobase, BANK0); - if (!(inb_p( iobase+LSR) & LSR_TXEMP)) { - DEBUG( 4, __FUNCTION__ "(), warning, FIFO not empty yet!\n"); + switch_bank(iobase, BANK0); + if (!(inb_p(iobase+LSR) & LSR_TXEMP)) { + IRDA_DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n"); fifo_size -= 17; - DEBUG( 4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size); + IRDA_DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size); } /* Fill FIFO with current frame */ @@ -854,7 +891,7 @@ static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size) outb(buf[actual++], iobase+TXD); } - DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", + IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", fifo_size, actual, len); /* Restore bank */ @@ -864,74 +901,69 @@ static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size) } /* - * Function pc87108_dma_xmit_complete (idev) + * Function pc87108_dma_xmit_complete (self) * * The transfer of a frame in finished. This function will only be called * by the interrupt handler * */ -static void pc87108_dma_xmit_complete( struct irda_device *idev) +static void pc87108_dma_xmit_complete(struct pc87108 *self) { int iobase; __u8 bank; - DEBUG( 4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( idev != NULL, return;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(self != NULL, return;); - iobase = idev->io.iobase; + iobase = self->io.iobase; /* Save current bank */ - bank = inb( iobase+BSR); + bank = inb(iobase+BSR); /* Disable DMA */ - switch_bank( iobase, BANK0); - outb( inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR); + switch_bank(iobase, BANK0); + outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR); /* Check for underrrun! */ - if ( inb( iobase+ASCR) & ASCR_TXUR) { - idev->stats.tx_errors++; - idev->stats.tx_fifo_errors++; + if (inb(iobase+ASCR) & ASCR_TXUR) { + self->stats.tx_errors++; + self->stats.tx_fifo_errors++; /* Clear bit, by writing 1 into it */ - outb( ASCR_TXUR, iobase+ASCR); + outb(ASCR_TXUR, iobase+ASCR); } else { - idev->stats.tx_packets++; - idev->stats.tx_bytes += idev->tx_buff.len; + self->stats.tx_packets++; + self->stats.tx_bytes += self->tx_buff.len; } /* Unlock tx_buff and request another frame */ - idev->netdev.tbusy = 0; /* Unlock */ - idev->media_busy = FALSE; + self->netdev->tbusy = 0; /* Unlock */ /* Tell the network layer, that we can accept more frames */ - mark_bh( NET_BH); + mark_bh(NET_BH); /* Restore bank */ - outb( bank, iobase+BSR); + outb(bank, iobase+BSR); } /* - * Function pc87108_dma_receive (idev) + * Function pc87108_dma_receive (self) * * Get ready for receiving a frame. The device will initiate a DMA * if it starts to receive a frame. * */ -static int pc87108_dma_receive(struct irda_device *idev) +static int pc87108_dma_receive(struct pc87108 *self) { - struct pc87108 *self; int iobase; __u8 bsr; - ASSERT(idev != NULL, return -1;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); + ASSERT(self != NULL, return -1;); - DEBUG(4, __FUNCTION__ "\n"); + IRDA_DEBUG(4, __FUNCTION__ "\n"); - self = idev->priv; - iobase = idev->io.iobase; + iobase = self->io.iobase; /* Save current bank */ bsr = inb(iobase+BSR); @@ -940,12 +972,12 @@ static int pc87108_dma_receive(struct irda_device *idev) switch_bank(iobase, BANK0); outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR); - setup_dma(idev->io.dma, idev->rx_buff.data, - idev->rx_buff.truesize, DMA_MODE_READ); + setup_dma(self->io.dma, self->rx_buff.data, + self->rx_buff.truesize, DMA_MODE_READ); /* driver->media_busy = FALSE; */ - idev->io.direction = IO_RECV; - idev->rx_buff.data = idev->rx_buff.head; + self->io.direction = IO_RECV; + self->rx_buff.data = self->rx_buff.head; /* Reset Rx FIFO. This will also flush the ST_FIFO */ outb(FCR_RXTH|FCR_TXTH|FCR_RXSR|FCR_FIFO_EN, iobase+FCR); @@ -953,7 +985,7 @@ static int pc87108_dma_receive(struct irda_device *idev) /* Choose DMA Rx, DMA Fairness, and Advanced mode */ switch_bank(iobase, BANK2); - outb((inb( iobase+ECR1) & ~ECR1_DMASWP)|ECR1_DMANF|ECR1_EXT_SL, + outb((inb(iobase+ECR1) & ~ECR1_DMASWP)|ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1); /* enable DMA */ @@ -963,40 +995,38 @@ static int pc87108_dma_receive(struct irda_device *idev) /* Restore bank register */ outb(bsr, iobase+BSR); - DEBUG(4, __FUNCTION__ "(), done!\n"); + IRDA_DEBUG(4, __FUNCTION__ "(), done!\n"); return 0; } /* - * Function pc87108_dma_receive_complete (idev) + * Function pc87108_dma_receive_complete (self) * * Finished with receiving frames * * */ -static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase) +static int pc87108_dma_receive_complete(struct pc87108 *self, int iobase) { struct sk_buff *skb; - struct pc87108 *self; struct st_fifo *st_fifo; - int len; __u8 bank; __u8 status; + int len; - self = idev->priv; st_fifo = &self->st_fifo; /* Save current bank */ - bank = inb( iobase+BSR); + bank = inb(iobase+BSR); /* Read status FIFO */ switch_bank(iobase, BANK5); - while (( status = inb( iobase+FRM_ST)) & FRM_ST_VLD) { - st_fifo->entries[ st_fifo->tail].status = status; + while ((status = inb(iobase+FRM_ST)) & FRM_ST_VLD) { + st_fifo->entries[st_fifo->tail].status = status; - st_fifo->entries[ st_fifo->tail].len = inb(iobase+RFLFL); - st_fifo->entries[ st_fifo->tail].len |= inb(iobase+RFLFH) << 8; + st_fifo->entries[st_fifo->tail].len = inb(iobase+RFLFL); + st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8; st_fifo->tail++; st_fifo->len++; @@ -1016,28 +1046,28 @@ static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase) if (status & FRM_ST_ERR_MSK) { if (status & FRM_ST_LOST_FR) { /* Add number of lost frames to stats */ - idev->stats.rx_errors += len; + self->stats.rx_errors += len; } else { /* Skip frame */ - idev->stats.rx_errors++; + self->stats.rx_errors++; - idev->rx_buff.data += len; + self->rx_buff.data += len; if (status & FRM_ST_MAX_LEN) - idev->stats.rx_length_errors++; + self->stats.rx_length_errors++; if (status & FRM_ST_PHY_ERR) - idev->stats.rx_frame_errors++; + self->stats.rx_frame_errors++; if (status & FRM_ST_BAD_CRC) - idev->stats.rx_crc_errors++; + self->stats.rx_crc_errors++; } /* The errors below can be reported in both cases */ if (status & FRM_ST_OVR1) - idev->stats.rx_fifo_errors++; + self->stats.rx_fifo_errors++; if (status & FRM_ST_OVR2) - idev->stats.rx_fifo_errors++; + self->stats.rx_fifo_errors++; } else { /* Check if we have transfered all data to memory */ @@ -1057,10 +1087,10 @@ static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase) /* Should be OK then */ skb = dev_alloc_skb(len+1); if (skb == NULL) { - printk( KERN_INFO __FUNCTION__ + printk(KERN_INFO __FUNCTION__ "(), memory squeeze, dropping frame.\n"); /* Restore bank register */ - outb( bank, iobase+BSR); + outb(bank, iobase+BSR); return FALSE; } @@ -1069,22 +1099,22 @@ static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase) skb_reserve(skb, 1); /* Copy frame without CRC */ - if (idev->io.baudrate < 4000000) { + if (self->io.speed < 4000000) { skb_put(skb, len-2); - memcpy(skb->data, idev->rx_buff.data, len-2); + memcpy(skb->data, self->rx_buff.data, len-2); } else { skb_put(skb, len-4); - memcpy(skb->data, idev->rx_buff.data, len-4); + memcpy(skb->data, self->rx_buff.data, len-4); } /* Move to next frame */ - idev->rx_buff.data += len; - idev->stats.rx_packets++; + self->rx_buff.data += len; + self->stats.rx_packets++; - skb->dev = &idev->netdev; + skb->dev = self->netdev; skb->mac.raw = skb->data; skb->protocol = htons(ETH_P_IRDA); - netif_rx( skb); + netif_rx(skb); } } /* Restore bank register */ @@ -1094,60 +1124,59 @@ static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase) } /* - * Function pc87108_pio_receive (idev) + * Function pc87108_pio_receive (self) * * Receive all data in receiver FIFO * */ -static void pc87108_pio_receive( struct irda_device *idev) +static void pc87108_pio_receive(struct pc87108 *self) { __u8 byte = 0x00; int iobase; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(self != NULL, return;); - iobase = idev->io.iobase; + iobase = self->io.iobase; /* Receive all characters in Rx FIFO */ do { byte = inb(iobase+RXD); - async_unwrap_char(idev, byte); + async_unwrap_char(self->netdev, &self->rx_buff, byte); } while (inb(iobase+LSR) & LSR_RXDA); /* Data available */ } /* - * Function pc87108_sir_interrupt (idev, eir) + * Function pc87108_sir_interrupt (self, eir) * * Handle SIR interrupt * */ -static __u8 pc87108_sir_interrupt(struct irda_device *idev, int eir) +static __u8 pc87108_sir_interrupt(struct pc87108 *self, int eir) { int actual; __u8 new_ier = 0; /* Transmit FIFO low on data */ - if ( eir & EIR_TXLDL_EV) { + if (eir & EIR_TXLDL_EV) { /* Write data left in transmit buffer */ - actual = pc87108_pio_write(idev->io.iobase, - idev->tx_buff.data, - idev->tx_buff.len, - idev->io.fifo_size); - idev->tx_buff.data += actual; - idev->tx_buff.len -= actual; + actual = pc87108_pio_write(self->io.iobase, + self->tx_buff.data, + self->tx_buff.len, + self->io.fifo_size); + self->tx_buff.data += actual; + self->tx_buff.len -= actual; - idev->io.direction = IO_XMIT; + self->io.direction = IO_XMIT; /* Check if finished */ - if (idev->tx_buff.len > 0) + if (self->tx_buff.len > 0) new_ier |= IER_TXLDL_IE; else { - idev->netdev.tbusy = 0; /* Unlock */ - idev->stats.tx_packets++; + self->netdev->tbusy = 0; /* Unlock */ + self->stats.tx_packets++; mark_bh(NET_BH); @@ -1156,16 +1185,16 @@ static __u8 pc87108_sir_interrupt(struct irda_device *idev, int eir) } /* Check if transmission has completed */ - if ( eir & EIR_TXEMP_EV) { + if (eir & EIR_TXEMP_EV) { /* Turn around and get ready to receive some data */ - idev->io.direction = IO_RECV; + self->io.direction = IO_RECV; new_ier |= IER_RXHDL_IE; } /* Rx FIFO threshold or timeout */ - if ( eir & EIR_RXHDL_EV) { - pc87108_pio_receive( idev); + if (eir & EIR_RXHDL_EV) { + pc87108_pio_receive(self); /* Keep receiving */ new_ier |= IER_RXHDL_IE; @@ -1174,22 +1203,22 @@ static __u8 pc87108_sir_interrupt(struct irda_device *idev, int eir) } /* - * Function pc87108_fir_interrupt (idev, eir) + * Function pc87108_fir_interrupt (self, eir) * * Handle MIR/FIR interrupt * */ -static __u8 pc87108_fir_interrupt( struct irda_device *idev, int iobase, - int eir) +static __u8 pc87108_fir_interrupt(struct pc87108 *self, int iobase, + int eir) { __u8 new_ier = 0; __u8 bank; - bank = inb( iobase+BSR); + bank = inb(iobase+BSR); /* Status event, or end of frame detected in FIFO */ if (eir & (EIR_SFIF_EV|EIR_LS_EV)) { - if (pc87108_dma_receive_complete( idev, iobase)) { + if (pc87108_dma_receive_complete(self, iobase)) { /* Wait for next status FIFO interrupt */ new_ier |= IER_SFIF_IE; @@ -1197,52 +1226,52 @@ static __u8 pc87108_fir_interrupt( struct irda_device *idev, int iobase, /* DMA not finished yet */ /* Set timer value, resolution 125 us */ - switch_bank( iobase, BANK4); - outb( 0x0f, iobase+TMRL); /* 125 us */ - outb( 0x00, iobase+TMRH); + switch_bank(iobase, BANK4); + outb(0x0f, iobase+TMRL); /* 125 us */ + outb(0x00, iobase+TMRH); /* Start timer */ - outb( IRCR1_TMR_EN, iobase+IRCR1); + outb(IRCR1_TMR_EN, iobase+IRCR1); new_ier |= IER_TMR_IE; } } /* Timer finished */ - if ( eir & EIR_TMR_EV) { + if (eir & EIR_TMR_EV) { /* Disable timer */ - switch_bank( iobase, BANK4); - outb( 0, iobase+IRCR1); + switch_bank(iobase, BANK4); + outb(0, iobase+IRCR1); /* Clear timer event */ switch_bank(iobase, BANK0); - outb( ASCR_CTE, iobase+ASCR); + outb(ASCR_CTE, iobase+ASCR); /* Check if this is a TX timer interrupt */ - if ( idev->io.direction == IO_XMIT) { - pc87108_dma_write( idev, iobase); + if (self->io.direction == IO_XMIT) { + pc87108_dma_write(self, iobase); /* Interrupt on DMA */ new_ier |= IER_DMA_IE; } else { /* Check if DMA has now finished */ - pc87108_dma_receive_complete( idev, iobase); + pc87108_dma_receive_complete(self, iobase); new_ier |= IER_SFIF_IE; } } /* Finished with transmission */ - if ( eir & EIR_DMA_EV) { - pc87108_dma_xmit_complete( idev); + if (eir & EIR_DMA_EV) { + pc87108_dma_xmit_complete(self); /* Check if there are more frames to be transmitted */ - if ( irda_device_txqueue_empty( idev)) { + if (irda_device_txqueue_empty(self->netdev)) { /* Prepare for receive */ - pc87108_dma_receive( idev); + pc87108_dma_receive(self); new_ier = IER_LS_IE|IER_SFIF_IE; } } - outb( bank, iobase+BSR); + outb(bank, iobase+BSR); return new_ier; } @@ -1255,51 +1284,52 @@ static __u8 pc87108_fir_interrupt( struct irda_device *idev, int iobase, */ static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + struct net_device *dev = (struct net_device *) dev_id; + struct pc87108 *self; __u8 bsr, eir, ier; int iobase; - struct irda_device *idev = (struct irda_device *) dev_id; - - if (idev == NULL) { - printk( KERN_WARNING "%s: irq %d for unknown device.\n", + if (!dev) { + printk(KERN_WARNING "%s: irq %d for unknown device.\n", driver_name, irq); return; } + self = (struct pc87108 *) dev->priv; - idev->netdev.interrupt = 1; + dev->interrupt = 1; - iobase = idev->io.iobase; + iobase = self->io.iobase; /* Save current bank */ - bsr = inb( iobase+BSR); + bsr = inb(iobase+BSR); - switch_bank( iobase, BANK0); - ier = inb( iobase+IER); - eir = inb( iobase+EIR) & ier; /* Mask out the interesting ones */ + switch_bank(iobase, BANK0); + ier = inb(iobase+IER); + eir = inb(iobase+EIR) & ier; /* Mask out the interesting ones */ - outb( 0, iobase+IER); /* Disable interrupts */ + outb(0, iobase+IER); /* Disable interrupts */ - if ( eir) { + if (eir) { /* Dispatch interrupt handler for the current speed */ - if ( idev->io.baudrate > 115200) - ier = pc87108_fir_interrupt( idev, iobase, eir); + if (self->io.speed > 115200) + ier = pc87108_fir_interrupt(self, iobase, eir); else - ier = pc87108_sir_interrupt( idev, eir); + ier = pc87108_sir_interrupt(self, eir); } - outb( ier, iobase+IER); /* Restore interrupts */ - outb( bsr, iobase+BSR); /* Restore bank register */ + outb(ier, iobase+IER); /* Restore interrupts */ + outb(bsr, iobase+BSR); /* Restore bank register */ - idev->netdev.interrupt = 0; + dev->interrupt = 0; } /* - * Function pc87108_wait_until_sent (idev) + * Function pc87108_wait_until_sent (self) * * This function should put the current thread to sleep until all data * have been sent, so it is safe to f.eks. change the speed. */ -static void pc87108_wait_until_sent( struct irda_device *idev) +static void pc87108_wait_until_sent(struct pc87108 *self) { /* Just delay 60 ms */ current->state = TASK_INTERRUPTIBLE; @@ -1307,33 +1337,32 @@ static void pc87108_wait_until_sent( struct irda_device *idev) } /* - * Function pc87108_is_receiving (idev) + * Function pc87108_is_receiving (self) * * Return TRUE is we are currently receiving a frame * */ -static int pc87108_is_receiving( struct irda_device *idev) +static int pc87108_is_receiving(struct pc87108 *self) { int status = FALSE; int iobase; __u8 bank; - ASSERT( idev != NULL, return FALSE;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;); + ASSERT(self != NULL, return FALSE;); - if ( idev->io.baudrate > 115200) { - iobase = idev->io.iobase; + if (self->io.speed > 115200) { + iobase = self->io.iobase; /* Check if rx FIFO is not empty */ - bank = inb( iobase+BSR); - switch_bank( iobase, BANK2); - if (( inb( iobase+RXFLV) & 0x3f) != 0) { + bank = inb(iobase+BSR); + switch_bank(iobase, BANK2); + if ((inb(iobase+RXFLV) & 0x3f) != 0) { /* We are receiving something */ status = TRUE; } - outb( bank, iobase+BSR); + outb(bank, iobase+BSR); } else - status = ( idev->rx_buff.state != OUTSIDE_FRAME); + status = (self->rx_buff.state != OUTSIDE_FRAME); return status; } @@ -1344,12 +1373,12 @@ static int pc87108_is_receiving( struct irda_device *idev) * Initialize network device * */ -static int pc87108_net_init( struct net_device *dev) +static int pc87108_net_init(struct net_device *dev) { - DEBUG( 4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); /* Setup to be a normal IrDA network device driver */ - irda_device_setup( dev); + irda_device_setup(dev); /* Insert overrides below this line! */ @@ -1363,46 +1392,54 @@ static int pc87108_net_init( struct net_device *dev) * Start the device * */ -static int pc87108_net_open( struct net_device *dev) +static int pc87108_net_open(struct net_device *dev) { - struct irda_device *idev; + struct pc87108 *self; int iobase; __u8 bank; - DEBUG( 4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( dev != NULL, return -1;); - idev = (struct irda_device *) dev->priv; + ASSERT(dev != NULL, return -1;); + self = (struct pc87108 *) dev->priv; - ASSERT( idev != NULL, return 0;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;); + ASSERT(self != NULL, return 0;); - iobase = idev->io.iobase; + iobase = self->io.iobase; - if (request_irq( idev->io.irq, pc87108_interrupt, 0, idev->name, - (void *) idev)) { + if (request_irq(self->io.irq, pc87108_interrupt, 0, dev->name, + (void *) dev)) { return -EAGAIN; } /* * Always allocate the DMA channel after the IRQ, * and clean up on failure. */ - if (request_dma(idev->io.dma, idev->name)) { - free_irq( idev->io.irq, idev); + if (request_dma(self->io.dma, dev->name)) { + free_irq(self->io.irq, self); return -EAGAIN; } /* Save current bank */ - bank = inb( iobase+BSR); + bank = inb(iobase+BSR); /* turn on interrupts */ - switch_bank( iobase, BANK0); - outb( IER_LS_IE | IER_RXHDL_IE, iobase+IER); + switch_bank(iobase, BANK0); + outb(IER_LS_IE | IER_RXHDL_IE, iobase+IER); /* Restore bank register */ - outb( bank, iobase+BSR); + outb(bank, iobase+BSR); - irda_device_net_open(dev); + /* Ready to play! */ + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + /* + * Open new IrLAP layer instance, now that everything should be + * initialized properly + */ + self->irlap = irlap_open(dev, &self->qos); MOD_INC_USE_COUNT; @@ -1417,23 +1454,29 @@ static int pc87108_net_open( struct net_device *dev) */ static int pc87108_net_close(struct net_device *dev) { - struct irda_device *idev; + struct pc87108 *self; int iobase; __u8 bank; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); - irda_device_net_close(dev); - ASSERT(dev != NULL, return -1;); - idev = (struct irda_device *) dev->priv; + self = (struct pc87108 *) dev->priv; - ASSERT(idev != NULL, return 0;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;); + ASSERT(self != NULL, return 0;); + + /* Stop device */ + dev->tbusy = 1; + dev->start = 0; + + /* Stop and remove instance of IrLAP */ + if (self->irlap) + irlap_close(self->irlap); + self->irlap = NULL; - iobase = idev->io.iobase; + iobase = self->io.iobase; - disable_dma(idev->io.dma); + disable_dma(self->io.dma); /* Save current bank */ bank = inb(iobase+BSR); @@ -1442,8 +1485,8 @@ static int pc87108_net_close(struct net_device *dev) switch_bank(iobase, BANK0); outb(0, iobase+IER); - free_irq(idev->io.irq, idev); - free_dma(idev->io.dma); + free_irq(self->io.irq, self); + free_dma(self->io.dma); /* Restore bank register */ outb(bank, iobase+BSR); diff --git a/drivers/net/irda/smc-ircc.c b/drivers/net/irda/smc-ircc.c index 00ab408d6..06b2af81b 100644 --- a/drivers/net/irda/smc-ircc.c +++ b/drivers/net/irda/smc-ircc.c @@ -106,7 +106,7 @@ int __init ircc_init(void) { int i; - DEBUG(ircc_debug, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); for ( i=0; (io[i] < 2000) && (i < 4); i++) { int ioaddr = io[i]; if (check_region(ioaddr, CHIP_IO_EXTENT)) @@ -114,7 +114,7 @@ int __init ircc_init(void) if (ircc_open( i, io[i], io2[i]) == 0) return 0; } - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); return -ENODEV; } @@ -130,13 +130,13 @@ static void ircc_cleanup(void) { int i; - DEBUG(ircc_debug, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); for ( i=0; i < 4; i++) { if ( dev_self[i]) ircc_close( &(dev_self[i]->idev)); } - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); } #endif /* MODULE */ @@ -153,10 +153,10 @@ static int ircc_open( int i, unsigned int iobase, unsigned int iobase2) int ret; int config; - DEBUG( ircc_debug, __FUNCTION__ " -->\n"); + IRDA_DEBUG( ircc_debug, __FUNCTION__ " -->\n"); if ((config = ircc_probe( iobase, iobase2)) == -1) { - DEBUG(ircc_debug, + IRDA_DEBUG(ircc_debug, __FUNCTION__ ": addr 0x%04x - no device found!\n", iobase); return -1; } @@ -199,14 +199,14 @@ static int ircc_open( int i, unsigned int iobase, unsigned int iobase2) /* Lock the port that we need */ ret = check_region( idev->io.iobase, idev->io.io_ext); if ( ret < 0) { - DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n", + IRDA_DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n", idev->io.iobase); /* ircc_cleanup( self->idev); */ return -ENODEV; } ret = check_region( idev->io.iobase2, idev->io.io_ext2); if ( ret < 0) { - DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n", + IRDA_DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n", idev->io.iobase2); /* ircc_cleanup( self->idev); */ return -ENODEV; @@ -256,7 +256,7 @@ static int ircc_open( int i, unsigned int iobase, unsigned int iobase2) /* Open the IrDA device */ irda_device_open( idev, driver_name, self); - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); return 0; } @@ -271,7 +271,7 @@ static int ircc_close( struct irda_device *idev) { int iobase; - DEBUG(ircc_debug, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); ASSERT( idev != NULL, return -1;); ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;); @@ -291,20 +291,20 @@ static int ircc_close( struct irda_device *idev) serial_out(iobase, UART_SCE_CFGB, UART_CFGB_IR); /* Release the PORT that this driver is using */ - DEBUG( ircc_debug, + IRDA_DEBUG( ircc_debug, __FUNCTION__ ": releasing 0x%03x\n", idev->io.iobase); release_region( idev->io.iobase, idev->io.io_ext); if ( idev->io.iobase2) { - DEBUG( ircc_debug, __FUNCTION__ ": releasing 0x%03x\n", + IRDA_DEBUG( ircc_debug, __FUNCTION__ ": releasing 0x%03x\n", idev->io.iobase2); release_region( idev->io.iobase2, idev->io.io_ext2); } irda_device_close( idev); - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); return 0; } #endif /* MODULE */ @@ -320,7 +320,7 @@ static int ircc_probe(int iobase, int iobase2) int version = 1; int low, high, chip, config, dma, irq; - DEBUG(ircc_debug, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); register_bank(iobase, 3); high = serial_in(iobase, UART_ID_HIGH); @@ -332,7 +332,7 @@ static int ircc_probe(int iobase, int iobase2) dma = config & 0x0f; if (high == 0x10 && low == 0xb8 && (chip == 0xf1 || chip == 0xf2)) { - DEBUG(0, "SMC IrDA Controller found; IrCC version %d.%d, " + IRDA_DEBUG(0, "SMC IrDA Controller found; IrCC version %d.%d, " "port 0x%04x, dma %d, interrupt %d\n", chip & 0x0f, version, iobase, dma, irq); } else { @@ -341,7 +341,7 @@ static int ircc_probe(int iobase, int iobase2) serial_out(iobase, UART_MASTER, 0); - DEBUG(ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n"); return config; } @@ -357,7 +357,7 @@ static void ircc_change_speed( struct irda_device *idev, __u32 speed) struct ircc_cb *self; int iobase, ir_mode, select, fast; - DEBUG(ircc_debug+1, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n"); ASSERT(idev != NULL, return;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); @@ -374,7 +374,7 @@ static void ircc_change_speed( struct irda_device *idev, __u32 speed) case 37600: case 57600: case 115200: - DEBUG(ircc_debug+1, + IRDA_DEBUG(ircc_debug+1, __FUNCTION__ ": using irport to change speed to %d\n", speed); register_bank(iobase, 0); @@ -390,22 +390,22 @@ static void ircc_change_speed( struct irda_device *idev, __u32 speed) ir_mode = UART_CFGA_IRDA_HDLC; select = 0; fast = 0; - DEBUG( ircc_debug, __FUNCTION__ ": handling baud of 576000\n"); + IRDA_DEBUG( ircc_debug, __FUNCTION__ ": handling baud of 576000\n"); break; case 1152000: ir_mode = UART_CFGA_IRDA_HDLC; select = UART_1152; fast = 0; - DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 1152000\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 1152000\n"); break; case 4000000: ir_mode = UART_CFGA_IRDA_4PPM; select = 0; fast = UART_LCR_A_FAST; - DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 4000000\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 4000000\n"); break; default: - DEBUG( 0, __FUNCTION__ ": unknown baud rate of %d\n", speed); + IRDA_DEBUG( 0, __FUNCTION__ ": unknown baud rate of %d\n", speed); return; } @@ -443,7 +443,7 @@ static void ircc_change_speed( struct irda_device *idev, __u32 speed) serial_out(iobase, UART_LCR_A, fast); - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); } /* @@ -458,7 +458,7 @@ static int ircc_hard_xmit( struct sk_buff *skb, struct net_device *dev) int iobase; int mtt; - DEBUG(ircc_debug+1, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n"); idev = (struct irda_device *) dev->priv; ASSERT( idev != NULL, return 0;); @@ -466,15 +466,15 @@ static int ircc_hard_xmit( struct sk_buff *skb, struct net_device *dev) iobase = idev->io.iobase; - DEBUG(ircc_debug+1, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len); + IRDA_DEBUG(ircc_debug+1, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len); /* Use irport for SIR speeds */ if (idev->io.baudrate <= 115200) { - DEBUG(ircc_debug+1, __FUNCTION__ ": calling irport_hard_xmit\n"); + IRDA_DEBUG(ircc_debug+1, __FUNCTION__ ": calling irport_hard_xmit\n"); return irport_hard_xmit(skb, dev); } - DEBUG(ircc_debug, __FUNCTION__ ": using dma; len=%d\n", skb->len); + IRDA_DEBUG(ircc_debug, __FUNCTION__ ": using dma; len=%d\n", skb->len); /* Lock transmit buffer */ if (irda_lock((void *) &dev->tbusy) == FALSE) @@ -502,7 +502,7 @@ static int ircc_hard_xmit( struct sk_buff *skb, struct net_device *dev) dev_kfree_skb( skb); - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); return 0; } @@ -516,7 +516,7 @@ static void ircc_dma_write( struct irda_device *idev, int iobase) { struct ircc_cb *self; - DEBUG(ircc_debug, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); ASSERT( idev != NULL, return;); ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); @@ -557,7 +557,7 @@ static void ircc_dma_write( struct irda_device *idev, int iobase) serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN); - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); } /* @@ -572,7 +572,7 @@ static void ircc_dma_xmit_complete( struct irda_device *idev, int underrun) struct ircc_cb *self; int iobase, d; - DEBUG(ircc_debug, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); ASSERT( idev != NULL, return;); ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); @@ -585,7 +585,7 @@ static void ircc_dma_xmit_complete( struct irda_device *idev, int underrun) d = get_dma_residue(idev->io.dma); - DEBUG(ircc_debug, __FUNCTION__ ": dma residue = %d, len=%d, sent=%d\n", + IRDA_DEBUG(ircc_debug, __FUNCTION__ ": dma residue = %d, len=%d, sent=%d\n", d, idev->tx_buff.len, idev->tx_buff.len - d); self = idev->priv; @@ -608,7 +608,7 @@ static void ircc_dma_xmit_complete( struct irda_device *idev, int underrun) /* Tell the network layer, that we can accept more frames */ mark_bh( NET_BH); - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); } /* @@ -623,7 +623,7 @@ static int ircc_dma_receive( struct irda_device *idev) struct ircc_cb *self; int iobase; - DEBUG(ircc_debug, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); ASSERT( idev != NULL, return -1;); ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;); @@ -660,7 +660,7 @@ static int ircc_dma_receive( struct irda_device *idev) serial_in(iobase, UART_SCE_CFGB) | UART_CFGB_DMA_ENABLE | UART_CFGB_DMA_BURST); - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); return 0; } @@ -677,18 +677,18 @@ static int ircc_dma_receive_complete( struct irda_device *idev, int iobase) struct ircc_cb *self; int len, msgcnt; - DEBUG(ircc_debug, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); self = idev->priv; msgcnt = serial_in(idev->io.iobase, UART_LCR_B) & 0x08; - DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n", + IRDA_DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n", get_dma_residue(idev->io.dma)); len = idev->rx_buff.truesize - get_dma_residue(idev->io.dma) - 4; - DEBUG(ircc_debug, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len); + IRDA_DEBUG(ircc_debug, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len); skb = dev_alloc_skb( len+1); @@ -715,7 +715,7 @@ static int ircc_dma_receive_complete( struct irda_device *idev, int iobase) serial_in(idev->io.iobase, UART_SCE_CFGB) & ~UART_CFGB_DMA_ENABLE); - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); return TRUE; } @@ -731,7 +731,7 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs) struct irda_device *idev = (struct irda_device *) dev_id; - DEBUG(ircc_debug+1, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n"); if (idev == NULL) { printk( KERN_WARNING "%s: irq %d for unknown device.\n", @@ -740,7 +740,7 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs) } if (idev->io.baudrate <= 115200) { - DEBUG(ircc_debug+1, __FUNCTION__ + IRDA_DEBUG(ircc_debug+1, __FUNCTION__ ": routing interrupt to irport_interrupt\n"); return irport_interrupt( irq, dev_id, regs); } @@ -757,10 +757,10 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs) serial_out(iobase, UART_IER, 0); - DEBUG(ircc_debug, __FUNCTION__ ": iir = 0x%02x\n", iir); + IRDA_DEBUG(ircc_debug, __FUNCTION__ ": iir = 0x%02x\n", iir); if (iir & UART_IIR_EOM) { - DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_EOM\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_EOM\n"); if (idev->io.direction == IO_RECV) { ircc_dma_receive_complete(idev, iobase); } else { @@ -770,7 +770,7 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs) } if (iir & UART_IIR_ACTIVE_FRAME) { - DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_ACTIVE_FRAME\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_ACTIVE_FRAME\n"); idev->rx_buff.state = INSIDE_FRAME; #if 0 ircc_dma_receive(idev); @@ -778,7 +778,7 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs) } if (iir & UART_IIR_RAW_MODE) { - DEBUG(ircc_debug, __FUNCTION__ ": IIR RAW mode interrupt.\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ ": IIR RAW mode interrupt.\n"); } idev->netdev.interrupt = 0; @@ -787,7 +787,7 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs) serial_out(iobase, UART_IER, UART_IER_ACTIVE_FRAME|UART_IER_EOM); serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN); - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); } /* @@ -798,13 +798,13 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs) */ static void ircc_wait_until_sent( struct irda_device *idev) { - DEBUG(ircc_debug, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); /* Just delay 60 ms */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(MSECS_TO_JIFFIES(60)); - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); } /* @@ -818,17 +818,17 @@ static int ircc_is_receiving( struct irda_device *idev) int status = FALSE; /* int iobase; */ - DEBUG(ircc_debug, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); ASSERT( idev != NULL, return FALSE;); ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;); - DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n", + IRDA_DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n", get_dma_residue(idev->io.dma)); status = ( idev->rx_buff.state != OUTSIDE_FRAME); - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); return status; } @@ -841,14 +841,14 @@ static int ircc_is_receiving( struct irda_device *idev) */ static int ircc_net_init( struct net_device *dev) { - DEBUG(ircc_debug, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); /* Setup to be a normal IrDA network device driver */ irda_device_setup( dev); /* Insert overrides below this line! */ - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); return 0; } @@ -864,7 +864,7 @@ static int ircc_net_open( struct net_device *dev) struct irda_device *idev; int iobase; - DEBUG(ircc_debug, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); ASSERT( dev != NULL, return -1;); idev = (struct irda_device *) dev->priv; @@ -894,7 +894,7 @@ static int ircc_net_open( struct net_device *dev) MOD_INC_USE_COUNT; - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); return 0; } @@ -909,7 +909,7 @@ static int ircc_net_close(struct net_device *dev) struct irda_device *idev; int iobase; - DEBUG(ircc_debug, __FUNCTION__ " -->\n"); + IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n"); ASSERT( dev != NULL, return -1;); idev = (struct irda_device *) dev->priv; @@ -930,7 +930,7 @@ static int ircc_net_close(struct net_device *dev) MOD_DEC_USE_COUNT; - DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); + IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n"); return 0; } diff --git a/drivers/net/irda/tekram.c b/drivers/net/irda/tekram.c index 6f3c49f6f..35504cfd3 100644 --- a/drivers/net/irda/tekram.c +++ b/drivers/net/irda/tekram.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Wed Oct 21 20:02:35 1998 - * Modified at: Thu Jul 15 01:17:53 1999 + * Modified at: Mon Oct 18 23:25:44 1999 * Modified by: Dag Brattli * * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. @@ -29,15 +29,14 @@ #include #include +#include #include #include -#include -static void tekram_reset(struct irda_device *dev); -static void tekram_open(struct irda_device *dev, int type); -static void tekram_close(struct irda_device *dev); -static void tekram_change_speed(struct irda_device *dev, __u32 speed); -static void tekram_init_qos(struct irda_device *idev, struct qos_info *qos); +static void tekram_open(dongle_t *self, struct qos_info *qos); +static void tekram_close(dongle_t *self); +static int tekram_change_speed(struct irda_task *task); +static int tekram_reset(struct irda_task *task); #define TEKRAM_115200 0x00 #define TEKRAM_57600 0x01 @@ -47,13 +46,13 @@ static void tekram_init_qos(struct irda_device *idev, struct qos_info *qos); #define TEKRAM_PW 0x10 /* Pulse select bit */ -static struct dongle dongle = { - TEKRAM_DONGLE, +static struct dongle_reg dongle = { + Q_NULL, + IRDA_TEKRAM_DONGLE, tekram_open, tekram_close, tekram_reset, tekram_change_speed, - tekram_init_qos, }; int __init tekram_init(void) @@ -66,26 +65,29 @@ void tekram_cleanup(void) irda_device_unregister_dongle(&dongle); } -static void tekram_open(struct irda_device *idev, int type) +static void tekram_open(dongle_t *self, struct qos_info *qos) { - strcat(idev->description, " <-> tekram"); + IRDA_DEBUG(2, __FUNCTION__ "()\n"); + + qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; + qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */ + irda_qos_bits_to_value(qos); - idev->io.dongle_id = type; - idev->flags |= IFF_DONGLE; - MOD_INC_USE_COUNT; } -static void tekram_close(struct irda_device *idev) -{ +static void tekram_close(dongle_t *self) +{ + IRDA_DEBUG(2, __FUNCTION__ "()\n"); + /* Power off dongle */ - irda_device_set_dtr_rts(idev, FALSE, FALSE); + self->set_dtr_rts(self->dev, FALSE, FALSE); MOD_DEC_USE_COUNT; } /* - * Function tekram_change_speed (tty, speed) + * Function tekram_change_speed (dev, state, speed) * * Set the speed for the Tekram IRMate 210 type dongle. Warning, this * function must be called with a process context! @@ -100,14 +102,16 @@ static void tekram_close(struct irda_device *idev) * 6. wait at least 50 us, new setting (baud rate, etc) takes effect here * after */ -static void tekram_change_speed(struct irda_device *idev, __u32 speed) +static int tekram_change_speed(struct irda_task *task) { + dongle_t *self = (dongle_t *) task->instance; + __u32 speed = (__u32) task->param; __u8 byte; + int ret = 0; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(2, __FUNCTION__ "()\n"); - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(task != NULL, return -1;); switch (speed) { default: @@ -128,24 +132,65 @@ static void tekram_change_speed(struct irda_device *idev, __u32 speed) break; } - /* Need to reset the dongle and go to 9600 bps before programming */ - tekram_reset(idev); - - /* Set DTR, Clear RTS */ - irda_device_set_dtr_rts(idev, TRUE, FALSE); - - /* Wait at least 7us */ - udelay(10); + switch (task->state) { + case IRDA_TASK_INIT: + /* Lock dongle */ + if (irda_lock((void *) &self->busy) == FALSE) { + IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n"); + return MSECS_TO_JIFFIES(100); + } + irda_task_next_state(task, IRDA_TASK_CHILD_INIT); + break; + case IRDA_TASK_CHILD_INIT: + /* + * Need to reset the dongle and go to 9600 bps before + * programming + */ + if (irda_task_execute(self, tekram_reset, NULL, task, + (void *) speed)) + { + /* Dongle need more time to reset */ + irda_task_next_state(task, IRDA_TASK_CHILD_WAIT); - /* Write control byte */ - irda_device_raw_write(idev, &byte, 1); + /* Give reset 1 sec to finish */ + ret = MSECS_TO_JIFFIES(1000); + } else + irda_task_next_state(task, IRDA_TASK_CHILD_DONE); + break; + case IRDA_TASK_CHILD_WAIT: + WARNING(__FUNCTION__ "(), resetting dongle timed out!\n"); + ret = -1; + break; + case IRDA_TASK_CHILD_DONE: + /* Set DTR, Clear RTS */ + self->set_dtr_rts(self->dev, TRUE, FALSE); - /* Wait at least 100 ms */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(MSECS_TO_JIFFIES(100)); - - /* Set DTR, Set RTS */ - irda_device_set_dtr_rts(idev, TRUE, TRUE); + /* Wait at least 7us */ + udelay(10); + + /* Write control byte */ + self->write(self->dev, &byte, 1); + + irda_task_next_state(task, IRDA_TASK_WAIT); + + /* Wait at least 100 ms */ + ret = MSECS_TO_JIFFIES(100); + break; + case IRDA_TASK_WAIT: + /* Set DTR, Set RTS */ + self->set_dtr_rts(self->dev, TRUE, TRUE); + + irda_task_next_state(task, IRDA_TASK_DONE); + self->busy = 0; + break; + default: + ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); + irda_task_next_state(task, IRDA_TASK_DONE); + self->busy = 0; + ret = -1; + break; + } + return ret; } /* @@ -161,50 +206,52 @@ static void tekram_change_speed(struct irda_device *idev, __u32 speed) * 3. clear DTR to SPACE state, wait at least 50 us for further * operation */ -void tekram_reset(struct irda_device *idev) +int tekram_reset(struct irda_task *task) { - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + dongle_t *self = (dongle_t *) task->instance; + int ret = 0; + + IRDA_DEBUG(2, __FUNCTION__ "()\n"); + + ASSERT(task != NULL, return -1;); /* Power off dongle */ - irda_device_set_dtr_rts(idev, FALSE, FALSE); - - /* Sleep 50 ms */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(MSECS_TO_JIFFIES(50)); + self->set_dtr_rts(self->dev, FALSE, FALSE); - /* Clear DTR, Set RTS */ - irda_device_set_dtr_rts(idev, FALSE, TRUE); + switch (task->state) { + case IRDA_TASK_INIT: + irda_task_next_state(task, IRDA_TASK_WAIT1); - /* Should sleep 1 ms, but 10-20 should not do any harm */ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(MSECS_TO_JIFFIES(20)); + /* Sleep 50 ms */ + ret = MSECS_TO_JIFFIES(50); + break; + case IRDA_TASK_WAIT1: + /* Clear DTR, Set RTS */ + self->set_dtr_rts(self->dev, FALSE, TRUE); - /* Set DTR, Set RTS */ - irda_device_set_dtr_rts(idev, TRUE, TRUE); - - udelay(50); + irda_task_next_state(task, IRDA_TASK_WAIT2); + + /* Should sleep 1 ms, but 10 should not do any harm */ + ret = MSECS_TO_JIFFIES(10); + break; + case IRDA_TASK_WAIT2: + /* Set DTR, Set RTS */ + self->set_dtr_rts(self->dev, TRUE, TRUE); - /* Make sure the IrDA chip also goes to defalt speed */ - if (idev->change_speed) - idev->change_speed(idev, 9600); -} + udelay(50); -/* - * Function tekram_init_qos (qos) - * - * Initialize QoS capabilities - * - */ -static void tekram_init_qos(struct irda_device *idev, struct qos_info *qos) -{ - qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; - qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */ - irda_qos_bits_to_value(qos); + irda_task_next_state(task, IRDA_TASK_DONE); + break; + default: + ERROR(__FUNCTION__ "(), unknown state %d\n", task->state); + irda_task_next_state(task, IRDA_TASK_DONE); + + ret = -1; + } + return ret; } #ifdef MODULE - MODULE_AUTHOR("Dag Brattli "); MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver"); @@ -229,5 +276,4 @@ void cleanup_module(void) { tekram_cleanup(); } - #endif /* MODULE */ diff --git a/drivers/net/irda/toshoboe.c b/drivers/net/irda/toshoboe.c index d0dbaa4f7..55e0e5b84 100644 --- a/drivers/net/irda/toshoboe.c +++ b/drivers/net/irda/toshoboe.c @@ -95,6 +95,7 @@ static char *rcsid = "$Id: toshoboe.c,v 1.9 1999/06/29 14:21:06 root Exp $"; #include #include #include +#include #include #include @@ -122,7 +123,7 @@ static int max_baud = 4000000; static void toshoboe_stopchip (struct toshoboe_cb *self) { - DEBUG (4, __FUNCTION__ "()\n"); + IRDA_DEBUG (4, __FUNCTION__ "()\n"); outb_p (0x0e, OBOE_REG_11); @@ -143,7 +144,7 @@ static void toshoboe_setbaud (struct toshoboe_cb *self, int baud) { unsigned long flags; - DEBUG (4, __FUNCTION__ "()\n"); + IRDA_DEBUG (4, __FUNCTION__ "()\n"); printk (KERN_WARNING "ToshOboe: seting baud to %d\n", baud); @@ -212,7 +213,7 @@ toshoboe_startchip (struct toshoboe_cb *self) { __u32 physaddr; - DEBUG (4, __FUNCTION__ "()\n"); + IRDA_DEBUG (4, __FUNCTION__ "()\n"); outb_p (0, OBOE_LOCK); @@ -241,7 +242,7 @@ toshoboe_startchip (struct toshoboe_cb *self) static void toshoboe_enablebm (struct toshoboe_cb *self) { - DEBUG (4, __FUNCTION__ "()\n"); + IRDA_DEBUG (4, __FUNCTION__ "()\n"); pci_set_master (self->pdev); } @@ -250,7 +251,7 @@ static void toshoboe_disablebm (struct toshoboe_cb *self) { __u8 command; - DEBUG (4, __FUNCTION__ "()\n"); + IRDA_DEBUG (4, __FUNCTION__ "()\n"); pci_read_config_byte (self->pdev, PCI_COMMAND, &command); command &= ~PCI_COMMAND_MASTER; @@ -265,7 +266,7 @@ toshoboe_initbuffs (struct toshoboe_cb *self) int i; unsigned long flags; - DEBUG (4, __FUNCTION__ "()\n"); + IRDA_DEBUG (4, __FUNCTION__ "()\n"); save_flags (flags); cli (); @@ -287,29 +288,27 @@ toshoboe_initbuffs (struct toshoboe_cb *self) restore_flags (flags); } - - - /*Transmit something */ static int toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev) { - struct irda_device *idev; struct toshoboe_cb *self; + __u32 speed; int mtt, len; - idev = (struct irda_device *) dev->priv; - ASSERT (idev != NULL, return 0; - ); - ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0; - ); + self = (struct toshoboe_cb *) dev->priv; - self = idev->priv; ASSERT (self != NULL, return 0; ); - if (self->stopped) + /* Check if we need to change the speed */ + if ((speed = irda_get_speed(skb)) != self->io.speed) + toshoboe_setbaud (self, speed); + + if (self->stopped) { + dev_kfree_skb(skb); return 0; + } #ifdef ONETASK if (self->txpending) @@ -376,24 +375,18 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev) static void toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs) { - struct irda_device *idev = (struct irda_device *) dev_id; - struct toshoboe_cb *self; + struct toshoboe_cb *self = (struct toshoboe_cb *) dev_id; __u8 irqstat; struct sk_buff *skb; - if (idev == NULL) + if (self == NULL) { printk (KERN_WARNING "%s: irq %d for unknown device.\n", driver_name, irq); return; } - self = idev->priv; - - if (!self) - return; - - DEBUG (4, __FUNCTION__ "()\n"); + IRDA_DEBUG (4, __FUNCTION__ "()\n"); irqstat = inb_p (OBOE_ISR); @@ -409,10 +402,10 @@ toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs) { self->txpending--; - idev->stats.tx_packets++; + self->stats.tx_packets++; - idev->media_busy = FALSE; - idev->netdev.tbusy = 0; + /* idev->media_busy = FALSE; */ + self->netdev->tbusy = 0; mark_bh (NET_BH); } @@ -441,8 +434,8 @@ toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs) skb_put (skb, len); memcpy (skb->data, self->recv_bufs[self->rxs], len); - idev->stats.rx_packets++; - skb->dev = &idev->netdev; + self->stats.rx_packets++; + skb->dev = self->netdev; skb->mac.raw = skb->data; skb->protocol = htons (ETH_P_IRDA); } @@ -479,79 +472,18 @@ toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs) { /*FIXME: I think this is a TX or RX error of some sort */ - idev->stats.tx_errors++; - idev->stats.rx_errors++; + self->stats.tx_errors++; + self->stats.rx_errors++; } } - - -/* Change the baud rate */ -static void -toshoboe_change_speed (struct irda_device *idev, __u32 speed) -{ - struct toshoboe_cb *self; - DEBUG (4, __FUNCTION__ "()\n"); - - ASSERT (idev != NULL, return; - ); - ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return; - ); - - self = idev->priv; - ASSERT (self != NULL, return; - ); - - - idev->io.baudrate = speed; - - if (self->stopped) - return; - - toshoboe_setbaud (self, speed); - -} - - -/* Check all xmit_tasks finished */ -static void -toshoboe_wait_until_sent (struct irda_device *idev) -{ - struct toshoboe_cb *self; - int i; - - DEBUG (4, __FUNCTION__ "()\n"); - - ASSERT (idev != NULL, return; - ); - ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return; - ); - - self = idev->priv; - ASSERT (self != NULL, return; - ); - - if (self->stopped) - return; - - for (i = 0; i < TX_SLOTS; ++i) - { - while (self->taskfile->xmit[i].control) - { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout (MSECS_TO_JIFFIES(60)); - } - } - -} - static int -toshoboe_is_receiving (struct irda_device *idev) +toshoboe_is_receiving (struct toshoboe_cb *self) { - DEBUG (4, __FUNCTION__ "()\n"); + IRDA_DEBUG (4, __FUNCTION__ "()\n"); /*FIXME Can't tell! */ return (FALSE); @@ -561,7 +493,7 @@ toshoboe_is_receiving (struct irda_device *idev) static int toshoboe_net_init (struct net_device *dev) { - DEBUG (4, __FUNCTION__ "()\n"); + IRDA_DEBUG (4, __FUNCTION__ "()\n"); /* Setup to be a normal IrDA network device driver */ irda_device_setup (dev); @@ -607,30 +539,22 @@ toshoboe_initptrs (struct toshoboe_cb *self) static int toshoboe_net_open (struct net_device *dev) { - struct irda_device *idev; struct toshoboe_cb *self; - DEBUG (4, __FUNCTION__ "()\n"); + IRDA_DEBUG (4, __FUNCTION__ "()\n"); ASSERT (dev != NULL, return -1; ); - idev = (struct irda_device *) dev->priv; - - ASSERT (idev != NULL, return 0; - ); - ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0; - ); + self = (struct toshoboe_cb *) dev->priv; - self = idev->priv; ASSERT (self != NULL, return 0; ); if (self->stopped) return 0; - - if (request_irq (idev->io.irq, toshoboe_interrupt, - SA_SHIRQ | SA_INTERRUPT, idev->name, (void *) idev)) + if (request_irq (self->io.irq, toshoboe_interrupt, + SA_SHIRQ | SA_INTERRUPT, dev->name, (void *) self)) { return -EAGAIN; @@ -641,8 +565,17 @@ toshoboe_net_open (struct net_device *dev) toshoboe_startchip (self); toshoboe_initptrs (self); - irda_device_net_open(dev); - + /* Ready to play! */ + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + /* + * Open new IrLAP layer instance, now that everything should be + * initialized properly + */ + self->irlap = irlap_open(dev, &self->qos); + self->open = 1; MOD_INC_USE_COUNT; @@ -654,30 +587,26 @@ toshoboe_net_open (struct net_device *dev) static int toshoboe_net_close (struct net_device *dev) { - struct irda_device *idev; struct toshoboe_cb *self; - DEBUG (4, __FUNCTION__ "()\n"); + IRDA_DEBUG (4, __FUNCTION__ "()\n"); ASSERT (dev != NULL, return -1; ); - idev = (struct irda_device *) dev->priv; + self = (struct toshoboe_cb *) dev->priv; - ASSERT (idev != NULL, return 0; - ); - ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0; - ); - - irda_device_net_close(dev); - - self = idev->priv; - - ASSERT (self != NULL, return 0; - ); + /* Stop device */ + dev->tbusy = 1; + dev->start = 0; + + /* Stop and remove instance of IrLAP */ + if (self->irlap) + irlap_close(self->irlap); + self->irlap = NULL; self->open = 0; - free_irq (idev->io.irq, (void *) idev); + free_irq (self->io.irq, (void *) self); if (!self->stopped) { @@ -698,19 +627,11 @@ toshoboe_net_close (struct net_device *dev) MODULE_PARM (max_baud, "i"); static int -toshoboe_close (struct irda_device *idev) +toshoboe_close (struct toshoboe_cb *self) { - struct toshoboe_cb *self; int i; - DEBUG (4, __FUNCTION__ "()\n"); - - ASSERT (idev != NULL, return -1; - ); - ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return -1; - ); - - self = idev->priv; + IRDA_DEBUG (4, __FUNCTION__ "()\n"); ASSERT (self != NULL, return -1; ); @@ -721,7 +642,7 @@ toshoboe_close (struct irda_device *idev) toshoboe_disablebm (self); } - release_region (idev->io.iobase, idev->io.io_ext); + release_region (self->io.iobase, self->io.io_ext); for (i = 0; i < TX_SLOTS; ++i) @@ -736,14 +657,17 @@ toshoboe_close (struct irda_device *idev) self->recv_bufs[i] = NULL; } + if (self->netdev) { + /* Remove netdevice */ + rtnl_lock(); + unregister_netdevice(self->netdev); + rtnl_unlock(); + } kfree (self->taskfilebuf); self->taskfilebuf = NULL; self->taskfile = NULL; - - irda_device_close (idev); - return (0); } @@ -756,12 +680,12 @@ static int toshoboe_open (struct pci_dev *pci_dev) { struct toshoboe_cb *self; - struct irda_device *idev; + struct net_device *dev; int i = 0; int ok = 0; + int err; - - DEBUG (4, __FUNCTION__ "()\n"); + IRDA_DEBUG (4, __FUNCTION__ "()\n"); while (dev_self[i]) i++; @@ -790,21 +714,17 @@ toshoboe_open (struct pci_dev *pci_dev) self->pdev = pci_dev; self->base = pci_dev->resource[0].start; - idev = &self->idev; - - /*Setup idev */ - - idev->io.iobase = self->base; - idev->io.irq = pci_dev->irq; - idev->io.io_ext = CHIP_IO_EXTENT; - idev->io.baudrate = 9600; + self->io.iobase = self->base; + self->io.irq = pci_dev->irq; + self->io.io_ext = CHIP_IO_EXTENT; + self->io.speed = 9600; /* Lock the port that we need */ - i = check_region (idev->io.iobase, idev->io.io_ext); + i = check_region (self->io.iobase, self->io.io_ext); if (i < 0) { - DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", - idev->io.iobase); + IRDA_DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", + self->io.iobase); dev_self[i] = NULL; kfree (self); @@ -813,57 +733,39 @@ toshoboe_open (struct pci_dev *pci_dev) } - irda_init_max_qos_capabilies (&idev->qos); - idev->qos.baud_rate.bits = 0; + irda_init_max_qos_capabilies (&self->qos); + self->qos.baud_rate.bits = 0; if (max_baud >= 2400) - idev->qos.baud_rate.bits |= IR_2400; + self->qos.baud_rate.bits |= IR_2400; /*if (max_baud>=4800) idev->qos.baud_rate.bits|=IR_4800; */ if (max_baud >= 9600) - idev->qos.baud_rate.bits |= IR_9600; + self->qos.baud_rate.bits |= IR_9600; if (max_baud >= 19200) - idev->qos.baud_rate.bits |= IR_19200; + self->qos.baud_rate.bits |= IR_19200; if (max_baud >= 115200) - idev->qos.baud_rate.bits |= IR_115200; + self->qos.baud_rate.bits |= IR_115200; #ifdef ENABLE_FAST if (max_baud >= 576000) - idev->qos.baud_rate.bits |= IR_576000; + self->qos.baud_rate.bits |= IR_576000; if (max_baud >= 1152000) - idev->qos.baud_rate.bits |= IR_1152000; + self->qos.baud_rate.bits |= IR_1152000; if (max_baud >= 4000000) - idev->qos.baud_rate.bits |= (IR_4000000 << 8); + self->qos.baud_rate.bits |= (IR_4000000 << 8); #endif - idev->qos.min_turn_time.bits = 0xff; /*FIXME: what does this do? */ + self->qos.min_turn_time.bits = 0xff; /*FIXME: what does this do? */ - irda_qos_bits_to_value (&idev->qos); + irda_qos_bits_to_value (&self->qos); - idev->flags = IFF_SIR | IFF_DMA | IFF_PIO; + self->flags = IFF_SIR | IFF_DMA | IFF_PIO; #ifdef ENABLE_FAST if (max_baud >= 576000) - idev->flags |= IFF_FIR; + self->flags |= IFF_FIR; #endif - /* These aren't much use as we need to have a whole panoply of - * buffers running */ - - idev->rx_buff.flags = 0; - idev->tx_buff.flags = 0; - idev->rx_buff.truesize = 0; - idev->rx_buff.truesize = 0; - - idev->change_speed = toshoboe_change_speed; - idev->wait_until_sent = toshoboe_wait_until_sent; - idev->is_receiving = toshoboe_is_receiving; - - idev->netdev.init = toshoboe_net_init; - idev->netdev.hard_start_xmit = toshoboe_hard_xmit; - idev->netdev.open = toshoboe_net_open; - idev->netdev.stop = toshoboe_net_close; - - /* Now setup the endless buffers we need */ self->txs = 0; @@ -922,9 +824,32 @@ toshoboe_open (struct pci_dev *pci_dev) } - request_region (idev->io.iobase, idev->io.io_ext, driver_name); + request_region (self->io.iobase, self->io.io_ext, driver_name); - irda_device_open (idev, driver_name, self); + if (!(dev = dev_alloc("irda%d", &err))) { + ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); + return -ENOMEM; + } + /* dev_alloc doesn't clear the struct, so lets do a little hack */ + memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*)); + + dev->priv = (void *) self; + self->netdev = dev; + + MESSAGE("IrDA: Registered device %s\n", dev->name); + + dev->init = toshoboe_net_init; + dev->hard_start_xmit = toshoboe_hard_xmit; + dev->open = toshoboe_net_open; + dev->stop = toshoboe_net_close; + + rtnl_lock(); + err = register_netdevice(dev); + rtnl_unlock(); + if (err) { + ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); + return -1; + } printk (KERN_WARNING "ToshOboe: Using "); #ifdef ONETASK @@ -969,8 +894,7 @@ toshoboe_gotosleep (struct toshoboe_cb *self) static void toshoboe_wakeup (struct toshoboe_cb *self) { - struct irda_device *idev = &self->idev; - struct net_device *dev = &idev->netdev; + struct net_device *dev = self->netdev; unsigned long flags; if (!self->stopped) @@ -989,12 +913,10 @@ toshoboe_wakeup (struct toshoboe_cb *self) toshoboe_enablebm (self); toshoboe_startchip (self); - toshoboe_setbaud (self, idev->io.baudrate); + toshoboe_setbaud (self, self->io.speed); toshoboe_initptrs (self); - - dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; @@ -1093,12 +1015,12 @@ toshoboe_cleanup (void) { int i; - DEBUG (4, __FUNCTION__ "()\n"); + IRDA_DEBUG (4, __FUNCTION__ "()\n"); for (i = 0; i < 4; i++) { if (dev_self[i]) - toshoboe_close (&(dev_self[i]->idev)); + toshoboe_close (dev_self[i]); } #ifdef CONFIG_APM diff --git a/drivers/net/irda/uircc.c b/drivers/net/irda/uircc.c index 869ccd5d6..2726700bb 100644 --- a/drivers/net/irda/uircc.c +++ b/drivers/net/irda/uircc.c @@ -113,7 +113,7 @@ static void uircc_cleanup(void) { int i; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); for (i=0; i < 4; i++) { if (dev_self[i]) @@ -135,7 +135,7 @@ static int uircc_open(int i, unsigned int iobase, unsigned int iobase2, struct irda_device *idev; int ret; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); if ((uircc_probe(iobase, iobase2, irq, dma)) == -1) return -1; @@ -168,14 +168,14 @@ static int uircc_open(int i, unsigned int iobase, unsigned int iobase2, /* Lock the port that we need */ ret = check_region(idev->io.iobase, idev->io.io_ext); if (ret < 0) { - DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", + IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", idev->io.iobase); /* uircc_cleanup( self->idev); */ return -ENODEV; } ret = check_region(idev->io.iobase2, idev->io.io_ext2); if (ret < 0) { - DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", + IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", idev->io.iobase2); /* uircc_cleanup( self->idev); */ return -ENODEV; @@ -235,7 +235,7 @@ static int uircc_close(struct irda_device *idev) int iobase; int status; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); ASSERT(idev != NULL, return -1;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); @@ -252,11 +252,11 @@ static int uircc_close(struct irda_device *idev) irport_stop(idev, idev->io.iobase2); /* Release the PORT that this driver is using */ - DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase); + IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase); release_region(idev->io.iobase, idev->io.io_ext); if (idev->io.iobase2) { - DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", + IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase2); release_region(idev->io.iobase2, idev->io.io_ext2); } @@ -278,13 +278,13 @@ static int uircc_probe(int iobase, int iobase2, int irq, int dma) { int version; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); /* read the chip version, should be 0x03 */ version = inb(iobase+UIRCC_SR8); if (version != 0x03) { - DEBUG(0, __FUNCTION__ "(), Wrong chip version"); + IRDA_DEBUG(0, __FUNCTION__ "(), Wrong chip version"); return -1; } printk(KERN_INFO "Sharp UIRCC IrDA driver loaded. Version: 0x%02x\n", @@ -298,7 +298,7 @@ static int uircc_probe(int iobase, int iobase2, int irq, int dma) outb(0, iobase+UIRCC_CR11); outb(0, iobase+UIRCC_CR9); - DEBUG(0, __FUNCTION__ "(), sr15=%#x\n", inb(iobase+UIRCC_SR15)); + IRDA_DEBUG(0, __FUNCTION__ "(), sr15=%#x\n", inb(iobase+UIRCC_SR15)); /* Enable DMA single mode */ outb(UIRCC_CR1_RX_DMA|UIRCC_CR1_TX_DMA|UIRCC_CR1_MUST_SET, @@ -325,7 +325,7 @@ static void uircc_change_speed(struct irda_device *idev, __u32 speed) int modem = UIRCC_CR10_SIR; int status; - DEBUG(0, __FUNCTION__ "()\n"); + IRDA_DEBUG(0, __FUNCTION__ "()\n"); /* Just test the high speed stuff */ /*speed = 4000000;*/ @@ -358,11 +358,11 @@ static void uircc_change_speed(struct irda_device *idev, __u32 speed) break; case 576000: - DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n"); + IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n"); break; case 1152000: - DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n"); + IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n"); break; case 4000000: irport_stop(idev, idev->io.iobase2); @@ -371,7 +371,7 @@ static void uircc_change_speed(struct irda_device *idev, __u32 speed) uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0001); modem = UIRCC_CR10_FIR; - DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n"); + IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n"); /* Set self pole address */ //outb(0xfe, iobase+UIRCC_CR8); @@ -379,7 +379,7 @@ static void uircc_change_speed(struct irda_device *idev, __u32 speed) /* outb(0x10, iobase+UIRCC_CR11); */ break; default: - DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed); + IRDA_DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed); break; } @@ -419,7 +419,7 @@ static int uircc_hard_xmit(struct sk_buff *skb, struct net_device *dev) iobase = idev->io.iobase; - DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len); + IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len); /* Reset carrier latch */ /*outb(0x02, iobase+UIRCC_CR0);*/ @@ -429,7 +429,7 @@ static int uircc_hard_xmit(struct sk_buff *skb, struct net_device *dev) return irport_hard_xmit(skb, dev); } - DEBUG(0, __FUNCTION__ "(), sr0=%#x, sr1=%#x, sr2=%#x, sr3=%#x, sr10=%#x, sr11=%#x\n", + IRDA_DEBUG(0, __FUNCTION__ "(), sr0=%#x, sr1=%#x, sr2=%#x, sr3=%#x, sr10=%#x, sr11=%#x\n", inb(iobase+UIRCC_SR0), inb(iobase+UIRCC_SR3), inb(iobase+UIRCC_SR2), inb(iobase+UIRCC_SR3), inb(iobase+UIRCC_SR10), inb(iobase+UIRCC_SR11)); @@ -473,7 +473,7 @@ static void uircc_dma_write(struct irda_device *idev, int iobase) { struct uircc_cb *self; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); ASSERT(idev != NULL, return;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); @@ -519,7 +519,7 @@ static void uircc_dma_xmit_complete( struct irda_device *idev, int underrun) int iobase; int len; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); ASSERT(idev != NULL, return;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); @@ -535,7 +535,7 @@ static void uircc_dma_xmit_complete( struct irda_device *idev, int underrun) len = inb(iobase+UIRCC_SR4); /* Low byte */ len |= inb(iobase+UIRCC_SR5) << 8; /* High byte */ - DEBUG(4, __FUNCTION__ "(), sent %d bytes\n", len); + IRDA_DEBUG(4, __FUNCTION__ "(), sent %d bytes\n", len); /* Disable transmit */ self->cr3 &= ~UIRCC_CR3_XMIT_EN; @@ -576,7 +576,7 @@ static int uircc_dma_receive(struct irda_device *idev) ASSERT(idev != NULL, return -1;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); - DEBUG(4, __FUNCTION__ "\n"); + IRDA_DEBUG(4, __FUNCTION__ "\n"); self = idev->priv; iobase= idev->io.iobase; @@ -614,7 +614,7 @@ static int uircc_dma_receive(struct irda_device *idev) self->cr3 = (UIRCC_CR3_RECV_EN|UIRCC_CR3_RX_CRC_EN); outb(self->cr3, iobase+UIRCC_CR3); #endif - DEBUG(4, __FUNCTION__ "(), cr3=%#x\n", self->cr3); + IRDA_DEBUG(4, __FUNCTION__ "(), cr3=%#x\n", self->cr3); /* Address check? */ @@ -636,11 +636,11 @@ static int uircc_dma_receive_complete(struct irda_device *idev, int iobase) self = idev->priv; - DEBUG(0, __FUNCTION__ "()\n"); + IRDA_DEBUG(0, __FUNCTION__ "()\n"); /* Check for CRC or framing error */ if (inb(iobase+UIRCC_SR0) & UIRCC_SR0_RX_CRCFRM) { - DEBUG(0, __FUNCTION__ "(), CRC or FRAME error\n"); + IRDA_DEBUG(0, __FUNCTION__ "(), CRC or FRAME error\n"); return -1; } @@ -651,7 +651,7 @@ static int uircc_dma_receive_complete(struct irda_device *idev, int iobase) len = inb(iobase+UIRCC_SR4); /* Low byte */ len |= inb(iobase+UIRCC_SR5) << 8; /* High byte */ - DEBUG(0, __FUNCTION__ "(), len=%d\n", len); + IRDA_DEBUG(0, __FUNCTION__ "(), len=%d\n", len); /* Receiving disable */ self->cr3 &= ~UIRCC_CR3_RECV_EN; @@ -716,12 +716,12 @@ static void uircc_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* Read interrupt status */ sr3 = inb( iobase+UIRCC_SR3); if (!sr3) { - DEBUG(4,"**\n"); + IRDA_DEBUG(4,"**\n"); return; } idev->netdev.interrupt = 1; - DEBUG(4, __FUNCTION__ "(), sr3=%#x, sr2=%#x, sr10=%#x\n", + IRDA_DEBUG(4, __FUNCTION__ "(), sr3=%#x, sr2=%#x, sr10=%#x\n", inb( iobase+UIRCC_SR3), inb( iobase+UIRCC_SR2), inb( iobase+UIRCC_SR10)); @@ -750,7 +750,7 @@ static void uircc_interrupt(int irq, void *dev_id, struct pt_regs *regs) iobase+UIRCC_CR11); break; default: - DEBUG(0, __FUNCTION__ "(), unknown interrupt status=%#x\n", + IRDA_DEBUG(0, __FUNCTION__ "(), unknown interrupt status=%#x\n", sr3); break; } @@ -800,7 +800,7 @@ static int uircc_is_receiving( struct irda_device *idev) */ static int uircc_net_init( struct net_device *dev) { - DEBUG( 4, __FUNCTION__ "()\n"); + IRDA_DEBUG( 4, __FUNCTION__ "()\n"); /* Setup to be a normal IrDA network device driver */ irda_device_setup(dev); @@ -822,7 +822,7 @@ static int uircc_net_open(struct net_device *dev) struct irda_device *idev; int iobase; - DEBUG( 4, __FUNCTION__ "()\n"); + IRDA_DEBUG( 4, __FUNCTION__ "()\n"); ASSERT(dev != NULL, return -1;); idev = (struct irda_device *) dev->priv; @@ -866,7 +866,7 @@ static int uircc_net_close(struct net_device *dev) struct irda_device *idev; int iobase; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); ASSERT(dev != NULL, return -1;); idev = (struct irda_device *) dev->priv; diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c index 32e965275..422f691ab 100644 --- a/drivers/net/irda/w83977af_ir.c +++ b/drivers/net/irda/w83977af_ir.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Paul VanderSpek * Created at: Wed Nov 4 11:46:16 1998 - * Modified at: Wed Aug 11 09:27:54 1999 + * Modified at: Wed Oct 20 00:08:30 1999 * Modified by: Dag Brattli * * Copyright (c) 1998-1999 Dag Brattli @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -83,17 +84,16 @@ static struct w83977af_ir *dev_self[] = { NULL, NULL, NULL, NULL}; /* Some prototypes */ static int w83977af_open(int i, unsigned int iobase, unsigned int irq, unsigned int dma); -static int w83977af_close(struct irda_device *idev); +static int w83977af_close(struct w83977af_ir *self); static int w83977af_probe(int iobase, int irq, int dma); -static int w83977af_dma_receive(struct irda_device *idev); -static int w83977af_dma_receive_complete(struct irda_device *idev); +static int w83977af_dma_receive(struct w83977af_ir *self); +static int w83977af_dma_receive_complete(struct w83977af_ir *self); static int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev); static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size); -static void w83977af_dma_write(struct irda_device *idev, int iobase); -static void w83977af_change_speed(struct irda_device *idev, __u32 speed); +static void w83977af_dma_write(struct w83977af_ir *self, int iobase); +static void w83977af_change_speed(struct w83977af_ir *self, __u32 speed); static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void w83977af_wait_until_sent(struct irda_device *idev); -static int w83977af_is_receiving(struct irda_device *idev); +static int w83977af_is_receiving(struct w83977af_ir *self); static int w83977af_net_init(struct net_device *dev); static int w83977af_net_open(struct net_device *dev); @@ -109,13 +109,13 @@ int __init w83977af_init(void) { int i; - DEBUG(0, __FUNCTION__ "()\n"); + IRDA_DEBUG(0, __FUNCTION__ "()\n"); for (i=0; (io[i] < 2000) && (i < 4); i++) { int ioaddr = io[i]; if (check_region(ioaddr, CHIP_IO_EXTENT) < 0) continue; - if (w83977af_open( i, io[i], irq[i], dma[i]) == 0) + if (w83977af_open(i, io[i], irq[i], dma[i]) == 0) return 0; } return -ENODEV; @@ -132,11 +132,11 @@ void w83977af_cleanup(void) { int i; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); for (i=0; i < 4; i++) { if (dev_self[i]) - w83977af_close(&(dev_self[i]->idev)); + w83977af_close(dev_self[i]); } } #endif /* MODULE */ @@ -147,14 +147,15 @@ void w83977af_cleanup(void) * Open driver instance * */ -int w83977af_open( int i, unsigned int iobase, unsigned int irq, - unsigned int dma) +int w83977af_open(int i, unsigned int iobase, unsigned int irq, + unsigned int dma) { - struct irda_device *idev; + struct net_device *dev; struct w83977af_ir *self; int ret; + int err; - DEBUG( 0, __FUNCTION__ "()\n"); + IRDA_DEBUG(0, __FUNCTION__ "()\n"); if (w83977af_probe(iobase, irq, dma) == -1) return -1; @@ -173,83 +174,107 @@ int w83977af_open( int i, unsigned int iobase, unsigned int irq, /* Need to store self somewhere */ dev_self[i] = self; - idev = &self->idev; - /* Initialize IO */ - idev->io.iobase = iobase; - idev->io.irq = irq; - idev->io.io_ext = CHIP_IO_EXTENT; - idev->io.dma = dma; - idev->io.fifo_size = 32; + self->io.iobase = iobase; + self->io.irq = irq; + self->io.io_ext = CHIP_IO_EXTENT; + self->io.dma = dma; + self->io.fifo_size = 32; /* Lock the port that we need */ - ret = check_region(idev->io.iobase, idev->io.io_ext); + ret = check_region(self->io.iobase, self->io.io_ext); if (ret < 0) { - DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", - idev->io.iobase); - /* w83977af_cleanup( self->idev); */ + IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", + self->io.iobase); + /* w83977af_cleanup( self); */ return -ENODEV; } - request_region(idev->io.iobase, idev->io.io_ext, idev->name); + request_region(self->io.iobase, self->io.io_ext, driver_name); /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&idev->qos); + irda_init_max_qos_capabilies(&self->qos); /* The only value we must override it the baudrate */ /* FIXME: The HP HDLS-1100 does not support 1152000! */ - idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| + self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8); /* The HP HDLS-1100 needs 1 ms according to the specs */ - idev->qos.min_turn_time.bits = qos_mtt_bits; - irda_qos_bits_to_value(&idev->qos); + self->qos.min_turn_time.bits = qos_mtt_bits; + irda_qos_bits_to_value(&self->qos); - idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO; - - /* Specify which buffer allocation policy we need */ - idev->rx_buff.flags = GFP_KERNEL | GFP_DMA; - idev->tx_buff.flags = GFP_KERNEL | GFP_DMA; + self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO; /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ - idev->rx_buff.truesize = 14384; - idev->tx_buff.truesize = 4000; + self->rx_buff.truesize = 14384; + self->tx_buff.truesize = 4000; - /* Initialize callbacks */ - idev->change_speed = w83977af_change_speed; - idev->wait_until_sent = w83977af_wait_until_sent; - idev->is_receiving = w83977af_is_receiving; + /* Allocate memory if needed */ + if (self->rx_buff.truesize > 0) { + self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize, + GFP_KERNEL|GFP_DMA); + if (self->rx_buff.head == NULL) + return -ENOMEM; + memset(self->rx_buff.head, 0, self->rx_buff.truesize); + } + if (self->tx_buff.truesize > 0) { + self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize, + GFP_KERNEL|GFP_DMA); + if (self->tx_buff.head == NULL) { + kfree(self->rx_buff.head); + return -ENOMEM; + } + memset(self->tx_buff.head, 0, self->tx_buff.truesize); + } + + self->rx_buff.in_frame = FALSE; + self->rx_buff.state = OUTSIDE_FRAME; + self->tx_buff.data = self->tx_buff.head; + self->rx_buff.data = self->rx_buff.head; + + if (!(dev = dev_alloc("irda%d", &err))) { + ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); + return -ENOMEM; + } + /* dev_alloc doesn't clear the struct, so lets do a little hack */ + memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*)); + + dev->priv = (void *) self; + self->netdev = dev; /* Override the network functions we need to use */ - idev->netdev.init = w83977af_net_init; - idev->netdev.hard_start_xmit = w83977af_hard_xmit; - idev->netdev.open = w83977af_net_open; - idev->netdev.stop = w83977af_net_close; + dev->init = w83977af_net_init; + dev->hard_start_xmit = w83977af_hard_xmit; + dev->open = w83977af_net_open; + dev->stop = w83977af_net_close; + + rtnl_lock(); + err = register_netdev(dev); + rtnl_unlock(); + if (err) { + ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); + return -1; + } - /* Open the IrDA device */ - irda_device_open(idev, driver_name, self); + MESSAGE("IrDA: Registered device %s\n", dev->name); return 0; } /* - * Function w83977af_close (idev) + * Function w83977af_close (self) * * Close driver instance * */ -static int w83977af_close( struct irda_device *idev) +static int w83977af_close(struct w83977af_ir *self) { - struct w83977af_ir *self; int iobase; - DEBUG(0, __FUNCTION__ "()\n"); - - ASSERT(idev != NULL, return -1;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); + IRDA_DEBUG(0, __FUNCTION__ "()\n"); - iobase = idev->io.iobase; - self = (struct w83977af_ir *) idev->priv; + iobase = self->io.iobase; #ifdef CONFIG_USE_W977_PNP /* enter PnP configuration mode */ @@ -262,12 +287,24 @@ static int w83977af_close( struct irda_device *idev) w977_efm_exit(); #endif /* CONFIG_USE_W977_PNP */ + + /* Remove netdevice */ + if (self->netdev) { + rtnl_lock(); + unregister_netdev(self->netdev); + rtnl_unlock(); + } + /* Release the PORT that this driver is using */ - DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", - idev->io.iobase); - release_region(idev->io.iobase, idev->io.io_ext); + IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", + self->io.iobase); + release_region(self->io.iobase, self->io.io_ext); - irda_device_close(idev); + if (self->tx_buff.head) + kfree(self->tx_buff.head); + + if (self->rx_buff.head) + kfree(self->rx_buff.head); kfree(self); @@ -284,7 +321,7 @@ int w83977af_probe( int iobase, int irq, int dma) { int version; - DEBUG( 0, __FUNCTION__ "()\n"); + IRDA_DEBUG( 0, __FUNCTION__ "()\n"); #ifdef CONFIG_USE_W977_PNP /* Enter PnP configuration mode */ w977_efm_enter(); @@ -333,7 +370,7 @@ int w83977af_probe( int iobase, int irq, int dma) /* Should be 0x1? */ if (0x10 != (version & 0xf0)) { - DEBUG( 0, __FUNCTION__ "(), Wrong chip version"); + IRDA_DEBUG( 0, __FUNCTION__ "(), Wrong chip version"); return -1; } @@ -365,30 +402,21 @@ int w83977af_probe( int iobase, int irq, int dma) switch_bank(iobase, SET7); outb(0x40, iobase+7); - DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version); + IRDA_DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version); return 0; } -/* - * Function w83977af_change_speed (idev, baud) - * - * Change the speed of the device - * - */ -void w83977af_change_speed(struct irda_device *idev, __u32 speed) +void w83977af_change_speed(struct w83977af_ir *self, __u32 speed) { int ir_mode = HCR_SIR; int iobase; __u8 set; - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - - iobase = idev->io.iobase; + iobase = self->io.iobase; /* Update accounting for new speed */ - idev->io.baudrate = speed; + self->io.speed = speed; /* Save current bank */ set = inb(iobase+SSR); @@ -409,19 +437,19 @@ void w83977af_change_speed(struct irda_device *idev, __u32 speed) case 115200: outb(0x01, iobase+ABLL); break; case 576000: ir_mode = HCR_MIR_576; - DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n"); + IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n"); break; case 1152000: ir_mode = HCR_MIR_1152; - DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n"); + IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n"); break; case 4000000: ir_mode = HCR_FIR; - DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n"); + IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n"); break; default: ir_mode = HCR_FIR; - DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed); + IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed); break; } @@ -440,13 +468,13 @@ void w83977af_change_speed(struct irda_device *idev, __u32 speed) outb(UFR_EN_FIFO, iobase+UFR); /* First we must enable FIFO */ outb(0xa7, iobase+UFR); - idev->netdev.tbusy = 0; + self->netdev->tbusy = 0; /* Enable some interrupts so we can receive frames */ switch_bank(iobase, SET0); if (speed > PIO_MAX_SPEED) { outb(ICR_EFSFI, iobase+ICR); - w83977af_dma_receive(idev); + w83977af_dma_receive(self); } else outb(ICR_ERBRI, iobase+ICR); @@ -462,32 +490,34 @@ void w83977af_change_speed(struct irda_device *idev, __u32 speed) */ int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev) { - struct irda_device *idev; + struct w83977af_ir *self; + __u32 speed; int iobase; __u8 set; int mtt; - idev = (struct irda_device *) dev->priv; + self = (struct w83977af_ir *) dev->priv; - ASSERT(idev != NULL, return 0;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;); + iobase = self->io.iobase; - iobase = idev->io.iobase; - - DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len); + IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len); /* Lock transmit buffer */ if (irda_lock((void *) &dev->tbusy) == FALSE) return -EBUSY; + /* Check if we need to change the speed */ + if ((speed = irda_get_speed(skb)) != self->io.speed) + w83977af_change_speed(self, speed); + /* Save current set */ set = inb(iobase+SSR); /* Decide if we should use PIO or DMA transfer */ - if (idev->io.baudrate > PIO_MAX_SPEED) { - idev->tx_buff.data = idev->tx_buff.head; - memcpy(idev->tx_buff.data, skb->data, skb->len); - idev->tx_buff.len = skb->len; + if (self->io.speed > PIO_MAX_SPEED) { + self->tx_buff.data = self->tx_buff.head; + memcpy(self->tx_buff.data, skb->data, skb->len); + self->tx_buff.len = skb->len; mtt = irda_get_mtt(skb); #ifdef CONFIG_USE_INTERNAL_TIMER @@ -502,28 +532,28 @@ int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev) /* Start timer */ outb(IR_MSL_EN_TMR, iobase+IR_MSL); - idev->io.direction = IO_XMIT; + self->io.direction = IO_XMIT; /* Enable timer interrupt */ switch_bank(iobase, SET0); outb(ICR_ETMRI, iobase+ICR); } else { #endif - DEBUG(4,__FUNCTION__ "(%ld), mtt=%d\n", jiffies, mtt); + IRDA_DEBUG(4,__FUNCTION__ "(%ld), mtt=%d\n", jiffies, mtt); if (mtt) udelay(mtt); /* Enable DMA interrupt */ switch_bank(iobase, SET0); outb(ICR_EDMAI, iobase+ICR); - w83977af_dma_write(idev, iobase); + w83977af_dma_write(self, iobase); #ifdef CONFIG_USE_INTERNAL_TIMER } #endif } else { - idev->tx_buff.data = idev->tx_buff.head; - idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, - idev->tx_buff.truesize); + self->tx_buff.data = self->tx_buff.head; + self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, + self->tx_buff.truesize); /* Add interrupt on tx low level (will fire immediately) */ switch_bank(iobase, SET0); @@ -538,19 +568,19 @@ int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev) } /* - * Function w83977af_dma_write (idev, iobase) + * Function w83977af_dma_write (self, iobase) * * Send frame using DMA * */ -static void w83977af_dma_write(struct irda_device *idev, int iobase) +static void w83977af_dma_write(struct w83977af_ir *self, int iobase) { __u8 set; #ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS unsigned long flags; __u8 hcr; #endif - DEBUG(4, __FUNCTION__ "(), len=%d\n", idev->tx_buff.len); + IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", self->tx_buff.len); /* Save current set */ set = inb(iobase+SSR); @@ -566,23 +596,23 @@ static void w83977af_dma_write(struct irda_device *idev, int iobase) save_flags(flags); cli(); - disable_dma(idev->io.dma); - clear_dma_ff(idev->io.dma); - set_dma_mode(idev->io.dma, DMA_MODE_READ); - set_dma_addr(idev->io.dma, virt_to_bus(idev->tx_buff.data)); - set_dma_count(idev->io.dma, idev->tx_buff.len); + disable_dma(self->io.dma); + clear_dma_ff(self->io.dma); + set_dma_mode(self->io.dma, DMA_MODE_READ); + set_dma_addr(self->io.dma, virt_to_bus(self->tx_buff.data)); + set_dma_count(self->io.dma, self->tx_buff.len); #else - setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, + setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, DMA_MODE_WRITE); #endif - idev->io.direction = IO_XMIT; + self->io.direction = IO_XMIT; /* Enable DMA */ switch_bank(iobase, SET0); #ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS hcr = inb(iobase+HCR); outb(hcr | HCR_EN_DMA, iobase+HCR); - enable_dma(idev->io.dma); + enable_dma(self->io.dma); restore_flags(flags); #else outb(inb(iobase+HCR) | HCR_EN_DMA | HCR_TX_WT, iobase+HCR); @@ -603,17 +633,17 @@ static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size) int actual = 0; __u8 set; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); /* Save current bank */ set = inb(iobase+SSR); switch_bank(iobase, SET0); if (!(inb_p(iobase+USR) & USR_TSRE)) { - DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n"); + IRDA_DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n"); fifo_size -= 17; - DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size); + IRDA_DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size); } /* Fill FIFO with current frame */ @@ -622,7 +652,7 @@ static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size) outb(buf[actual++], iobase+TBR); } - DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", + IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", fifo_size, actual, len); /* Restore bank */ @@ -632,23 +662,22 @@ static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size) } /* - * Function w83977af_dma_xmit_complete (idev) + * Function w83977af_dma_xmit_complete (self) * * The transfer of a frame in finished. So do the necessary things * * */ -void w83977af_dma_xmit_complete(struct irda_device *idev) +void w83977af_dma_xmit_complete(struct w83977af_ir *self) { int iobase; __u8 set; - DEBUG(4, __FUNCTION__ "(%ld)\n", jiffies); + IRDA_DEBUG(4, __FUNCTION__ "(%ld)\n", jiffies); - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(self != NULL, return;); - iobase = idev->io.iobase; + iobase = self->io.iobase; /* Save current set */ set = inb(iobase+SSR); @@ -659,19 +688,18 @@ void w83977af_dma_xmit_complete(struct irda_device *idev) /* Check for underrrun! */ if (inb(iobase+AUDR) & AUDR_UNDR) { - DEBUG(0, __FUNCTION__ "(), Transmit underrun!\n"); + IRDA_DEBUG(0, __FUNCTION__ "(), Transmit underrun!\n"); - idev->stats.tx_errors++; - idev->stats.tx_fifo_errors++; + self->stats.tx_errors++; + self->stats.tx_fifo_errors++; /* Clear bit, by writing 1 to it */ outb(AUDR_UNDR, iobase+AUDR); } else - idev->stats.tx_packets++; + self->stats.tx_packets++; /* Unlock tx_buff and request another frame */ - idev->netdev.tbusy = 0; /* Unlock */ - idev->media_busy = FALSE; + self->netdev->tbusy = 0; /* Unlock */ /* Tell the network layer, that we want more frames */ mark_bh(NET_BH); @@ -681,15 +709,14 @@ void w83977af_dma_xmit_complete(struct irda_device *idev) } /* - * Function w83977af_dma_receive (idev) + * Function w83977af_dma_receive (self) * * Get ready for receiving a frame. The device will initiate a DMA * if it starts to receive a frame. * */ -int w83977af_dma_receive(struct irda_device *idev) +int w83977af_dma_receive(struct w83977af_ir *self) { - struct w83977af_ir *self; int iobase; __u8 set; #ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS @@ -697,13 +724,11 @@ int w83977af_dma_receive(struct irda_device *idev) __u8 hcr; #endif - ASSERT(idev != NULL, return -1;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); + ASSERT(self != NULL, return -1;); - DEBUG(4, __FUNCTION__ "\n"); + IRDA_DEBUG(4, __FUNCTION__ "\n"); - self = idev->priv; - iobase= idev->io.iobase; + iobase= self->io.iobase; /* Save current set */ set = inb(iobase+SSR); @@ -717,20 +742,20 @@ int w83977af_dma_receive(struct irda_device *idev) outb((inb(iobase+ADCR1) & ~ADCR1_D_CHSW)/*|ADCR1_DMA_F*/|ADCR1_ADV_SL, iobase+ADCR1); - idev->io.direction = IO_RECV; - idev->rx_buff.data = idev->rx_buff.head; + self->io.direction = IO_RECV; + self->rx_buff.data = self->rx_buff.head; #ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS save_flags(flags); cli(); - disable_dma(idev->io.dma); - clear_dma_ff(idev->io.dma); - set_dma_mode(idev->io.dma, DMA_MODE_READ); - set_dma_addr(idev->io.dma, virt_to_bus(idev->rx_buff.data)); - set_dma_count(idev->io.dma, idev->rx_buff.truesize); + disable_dma(self->io.dma); + clear_dma_ff(self->io.dma); + set_dma_mode(self->io.dma, DMA_MODE_READ); + set_dma_addr(self->io.dma, virt_to_bus(self->rx_buff.data)); + set_dma_count(self->io.dma, self->rx_buff.truesize); #else - setup_dma(idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize, + setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, DMA_MODE_READ); #endif /* @@ -747,7 +772,7 @@ int w83977af_dma_receive(struct irda_device *idev) #ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS hcr = inb(iobase+HCR); outb(hcr | HCR_EN_DMA, iobase+HCR); - enable_dma(idev->io.dma); + enable_dma(self->io.dma); restore_flags(flags); #else outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR); @@ -759,32 +784,30 @@ int w83977af_dma_receive(struct irda_device *idev) } /* - * Function w83977af_receive_complete (idev) + * Function w83977af_receive_complete (self) * * Finished with receiving a frame * */ -int w83977af_dma_receive_complete(struct irda_device *idev) +int w83977af_dma_receive_complete(struct w83977af_ir *self) { struct sk_buff *skb; - struct w83977af_ir *self; struct st_fifo *st_fifo; int len; int iobase; __u8 set; __u8 status; - DEBUG(4, __FUNCTION__ "\n"); + IRDA_DEBUG(4, __FUNCTION__ "\n"); - self = idev->priv; st_fifo = &self->st_fifo; - iobase = idev->io.iobase; + iobase = self->io.iobase; /* Save current set */ set = inb(iobase+SSR); - iobase = idev->io.iobase; + iobase = self->io.iobase; /* Read status FIFO */ switch_bank(iobase, SET5); @@ -809,28 +832,28 @@ int w83977af_dma_receive_complete(struct irda_device *idev) if (status & FS_FO_ERR_MSK) { if (status & FS_FO_LST_FR) { /* Add number of lost frames to stats */ - idev->stats.rx_errors += len; + self->stats.rx_errors += len; } else { /* Skip frame */ - idev->stats.rx_errors++; + self->stats.rx_errors++; - idev->rx_buff.data += len; + self->rx_buff.data += len; if (status & FS_FO_MX_LEX) - idev->stats.rx_length_errors++; + self->stats.rx_length_errors++; if (status & FS_FO_PHY_ERR) - idev->stats.rx_frame_errors++; + self->stats.rx_frame_errors++; if (status & FS_FO_CRC_ERR) - idev->stats.rx_crc_errors++; + self->stats.rx_crc_errors++; } /* The errors below can be reported in both cases */ if (status & FS_FO_RX_OV) - idev->stats.rx_fifo_errors++; + self->stats.rx_fifo_errors++; if (status & FS_FO_FSF_OV) - idev->stats.rx_fifo_errors++; + self->stats.rx_fifo_errors++; } else { /* Check if we have transfered all data to memory */ @@ -866,19 +889,19 @@ int w83977af_dma_receive_complete(struct irda_device *idev) skb_reserve(skb, 1); /* Copy frame without CRC */ - if (idev->io.baudrate < 4000000) { + if (self->io.speed < 4000000) { skb_put(skb, len-2); - memcpy(skb->data, idev->rx_buff.data, len-2); + memcpy(skb->data, self->rx_buff.data, len-2); } else { skb_put(skb, len-4); - memcpy(skb->data, idev->rx_buff.data, len-4); + memcpy(skb->data, self->rx_buff.data, len-4); } /* Move to next frame */ - idev->rx_buff.data += len; - idev->stats.rx_packets++; + self->rx_buff.data += len; + self->stats.rx_packets++; - skb->dev = &idev->netdev; + skb->dev = self->netdev; skb->mac.raw = skb->data; skb->protocol = htons(ETH_P_IRDA); netif_rx(skb); @@ -891,61 +914,60 @@ int w83977af_dma_receive_complete(struct irda_device *idev) } /* - * Function pc87108_pio_receive (idev) + * Function pc87108_pio_receive (self) * * Receive all data in receiver FIFO * */ -static void w83977af_pio_receive(struct irda_device *idev) +static void w83977af_pio_receive(struct w83977af_ir *self) { __u8 byte = 0x00; int iobase; - DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(4, __FUNCTION__ "()\n"); - ASSERT(idev != NULL, return;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(self != NULL, return;); - iobase = idev->io.iobase; + iobase = self->io.iobase; /* Receive all characters in Rx FIFO */ do { byte = inb(iobase+RBR); - async_unwrap_char(idev, byte); + async_unwrap_char(self->netdev, &self->rx_buff, byte); } while (inb(iobase+USR) & USR_RDR); /* Data available */ } /* - * Function w83977af_sir_interrupt (idev, eir) + * Function w83977af_sir_interrupt (self, eir) * * Handle SIR interrupt * */ -static __u8 w83977af_sir_interrupt(struct irda_device *idev, int isr) +static __u8 w83977af_sir_interrupt(struct w83977af_ir *self, int isr) { int actual; __u8 new_icr = 0; __u8 set; int iobase; - DEBUG(4, __FUNCTION__ "(), isr=%#x\n", isr); + IRDA_DEBUG(4, __FUNCTION__ "(), isr=%#x\n", isr); - iobase = idev->io.iobase; + iobase = self->io.iobase; /* Transmit FIFO low on data */ if (isr & ISR_TXTH_I) { /* Write data left in transmit buffer */ - actual = w83977af_pio_write(idev->io.iobase, - idev->tx_buff.data, - idev->tx_buff.len, - idev->io.fifo_size); + actual = w83977af_pio_write(self->io.iobase, + self->tx_buff.data, + self->tx_buff.len, + self->io.fifo_size); - idev->tx_buff.data += actual; - idev->tx_buff.len -= actual; + self->tx_buff.data += actual; + self->tx_buff.len -= actual; - idev->io.direction = IO_XMIT; + self->io.direction = IO_XMIT; /* Check if finished */ - if (idev->tx_buff.len > 0) { + if (self->tx_buff.len > 0) { new_icr |= ICR_ETXTHI; } else { set = inb(iobase+SSR); @@ -953,8 +975,8 @@ static __u8 w83977af_sir_interrupt(struct irda_device *idev, int isr) outb(AUDR_SFEND, iobase+AUDR); outb(set, iobase+SSR); - idev->netdev.tbusy = 0; /* Unlock */ - idev->stats.tx_packets++; + self->netdev->tbusy = 0; /* Unlock */ + self->stats.tx_packets++; /* Schedule network layer */ mark_bh(NET_BH); @@ -966,13 +988,13 @@ static __u8 w83977af_sir_interrupt(struct irda_device *idev, int isr) if (isr & ISR_TXEMP_I) { /* Turn around and get ready to receive some data */ - idev->io.direction = IO_RECV; + self->io.direction = IO_RECV; new_icr |= ICR_ERBRI; } /* Rx FIFO threshold or timeout */ if (isr & ISR_RXTH_I) { - w83977af_pio_receive(idev); + w83977af_pio_receive(self); /* Keep receiving */ new_icr |= ICR_ERBRI; @@ -981,23 +1003,23 @@ static __u8 w83977af_sir_interrupt(struct irda_device *idev, int isr) } /* - * Function pc87108_fir_interrupt (idev, eir) + * Function pc87108_fir_interrupt (self, eir) * * Handle MIR/FIR interrupt * */ -static __u8 w83977af_fir_interrupt(struct irda_device *idev, int isr) +static __u8 w83977af_fir_interrupt(struct w83977af_ir *self, int isr) { __u8 new_icr = 0; __u8 set; int iobase; - iobase = idev->io.iobase; + iobase = self->io.iobase; set = inb(iobase+SSR); /* End of frame detected in FIFO */ if (isr & (ISR_FEND_I|ISR_FSF_I)) { - if (w83977af_dma_receive_complete(idev)) { + if (w83977af_dma_receive_complete(self)) { /* Wait for next status FIFO interrupt */ new_icr |= ICR_EFSFI; @@ -1026,29 +1048,29 @@ static __u8 w83977af_fir_interrupt(struct irda_device *idev, int isr) /* outb(ASCR_CTE, iobase+ASCR); */ /* Check if this is a TX timer interrupt */ - if (idev->io.direction == IO_XMIT) { - w83977af_dma_write(idev, iobase); + if (self->io.direction == IO_XMIT) { + w83977af_dma_write(self, iobase); new_icr |= ICR_EDMAI; } else { /* Check if DMA has now finished */ - w83977af_dma_receive_complete(idev); + w83977af_dma_receive_complete(self); new_icr |= ICR_EFSFI; } } /* Finished with DMA */ if (isr & ISR_DMA_I) { - w83977af_dma_xmit_complete(idev); + w83977af_dma_xmit_complete(self); /* Check if there are more frames to be transmitted */ - /* if (irda_device_txqueue_empty(idev)) { */ + /* if (irda_device_txqueue_empty(self)) { */ /* Prepare for receive * * ** Netwinder Tx DMA likes that we do this anyway ** */ - w83977af_dma_receive(idev); + w83977af_dma_receive(self); new_icr = ICR_EFSFI; /* } */ } @@ -1067,20 +1089,21 @@ static __u8 w83977af_fir_interrupt(struct irda_device *idev, int isr) */ static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + struct net_device *dev = (struct net_device *) dev_id; + struct w83977af_ir *self; __u8 set, icr, isr; int iobase; - struct irda_device *idev = (struct irda_device *) dev_id; - - if (idev == NULL) { + if (!dev) { printk(KERN_WARNING "%s: irq %d for unknown device.\n", driver_name, irq); return; } + self = (struct w83977af_ir *) dev->priv; - idev->netdev.interrupt = 1; + dev->interrupt = 1; - iobase = idev->io.iobase; + iobase = self->io.iobase; /* Save current bank */ set = inb(iobase+SSR); @@ -1093,47 +1116,34 @@ static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (isr) { /* Dispatch interrupt handler for the current speed */ - if (idev->io.baudrate > PIO_MAX_SPEED ) - icr = w83977af_fir_interrupt(idev, isr); + if (self->io.speed > PIO_MAX_SPEED ) + icr = w83977af_fir_interrupt(self, isr); else - icr = w83977af_sir_interrupt(idev, isr); + icr = w83977af_sir_interrupt(self, isr); } outb(icr, iobase+ICR); /* Restore (new) interrupts */ outb(set, iobase+SSR); /* Restore bank register */ - idev->netdev.interrupt = 0; + self->netdev->interrupt = 0; } /* - * Function w83977af_wait_until_sent (idev) - * - * This function should put the current thread to sleep until all data - * have been sent, so it is safe to f.eks. change the speed. - */ -static void w83977af_wait_until_sent(struct irda_device *idev) -{ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(60*HZ/1000); -} - -/* - * Function w83977af_is_receiving (idev) + * Function w83977af_is_receiving (self) * * Return TRUE is we are currently receiving a frame * */ -static int w83977af_is_receiving(struct irda_device *idev) +static int w83977af_is_receiving(struct w83977af_ir *self) { int status = FALSE; int iobase; __u8 set; - ASSERT(idev != NULL, return FALSE;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return FALSE;); + ASSERT(self != NULL, return FALSE;); - if (idev->io.baudrate > 115200) { - iobase = idev->io.iobase; + if (self->io.speed > 115200) { + iobase = self->io.iobase; /* Check if rx FIFO is not empty */ set = inb(iobase+SSR); @@ -1144,7 +1154,7 @@ static int w83977af_is_receiving(struct irda_device *idev) } outb(set, iobase+SSR); } else - status = (idev->rx_buff.state != OUTSIDE_FRAME); + status = (self->rx_buff.state != OUTSIDE_FRAME); return status; } @@ -1157,7 +1167,7 @@ static int w83977af_is_receiving(struct irda_device *idev) */ static int w83977af_net_init(struct net_device *dev) { - DEBUG(0, __FUNCTION__ "()\n"); + IRDA_DEBUG(0, __FUNCTION__ "()\n"); /* Set up to be a normal IrDA network device driver */ irda_device_setup(dev); @@ -1176,30 +1186,29 @@ static int w83977af_net_init(struct net_device *dev) */ static int w83977af_net_open(struct net_device *dev) { - struct irda_device *idev; + struct w83977af_ir *self; int iobase; __u8 set; - DEBUG(0, __FUNCTION__ "()\n"); + IRDA_DEBUG(0, __FUNCTION__ "()\n"); ASSERT(dev != NULL, return -1;); - idev = (struct irda_device *) dev->priv; + self = (struct w83977af_ir *) dev->priv; - ASSERT(idev != NULL, return 0;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;); + ASSERT(self != NULL, return 0;); - iobase = idev->io.iobase; + iobase = self->io.iobase; - if (request_irq(idev->io.irq, w83977af_interrupt, 0, idev->name, - (void *) idev)) { + if (request_irq(self->io.irq, w83977af_interrupt, 0, dev->name, + (void *) dev)) { return -EAGAIN; } /* * Always allocate the DMA channel after the IRQ, * and clean up on failure. */ - if (request_dma(idev->io.dma, idev->name)) { - free_irq(idev->io.irq, idev); + if (request_dma(self->io.dma, dev->name)) { + free_irq(self->io.irq, self); return -EAGAIN; } @@ -1208,9 +1217,9 @@ static int w83977af_net_open(struct net_device *dev) /* Enable some interrupts so we can receive frames again */ switch_bank(iobase, SET0); - if (idev->io.baudrate > 115200) { + if (self->io.speed > 115200) { outb(ICR_EFSFI, iobase+ICR); - w83977af_dma_receive(idev); + w83977af_dma_receive(self); } else outb(ICR_ERBRI, iobase+ICR); @@ -1218,7 +1227,15 @@ static int w83977af_net_open(struct net_device *dev) outb(set, iobase+SSR); /* Ready to play! */ - irda_device_net_open(dev); + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + /* + * Open new IrLAP layer instance, now that everything should be + * initialized properly + */ + self->irlap = irlap_open(dev, &self->qos); MOD_INC_USE_COUNT; @@ -1233,25 +1250,30 @@ static int w83977af_net_open(struct net_device *dev) */ static int w83977af_net_close(struct net_device *dev) { - struct irda_device *idev; + struct w83977af_ir *self; int iobase; __u8 set; - DEBUG(0, __FUNCTION__ "()\n"); + IRDA_DEBUG(0, __FUNCTION__ "()\n"); ASSERT(dev != NULL, return -1;); - idev = (struct irda_device *) dev->priv; + self = (struct w83977af_ir *) dev->priv; - ASSERT(idev != NULL, return 0;); - ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;); + ASSERT(self != NULL, return 0;); - iobase = idev->io.iobase; + iobase = self->io.iobase; /* Stop device */ - irda_device_net_close(dev); + dev->tbusy = 1; + dev->start = 0; + + /* Stop and remove instance of IrLAP */ + if (self->irlap) + irlap_close(self->irlap); + self->irlap = NULL; - disable_dma(idev->io.dma); + disable_dma(self->io.dma); /* Save current set */ set = inb(iobase+SSR); @@ -1260,8 +1282,8 @@ static int w83977af_net_close(struct net_device *dev) switch_bank(iobase, SET0); outb(0, iobase+ICR); - free_irq(idev->io.irq, idev); - free_dma(idev->io.dma); + free_irq(self->io.irq, self); + free_dma(self->io.dma); /* Restore bank register */ outb(set, iobase+SSR); diff --git a/drivers/net/pcmcia/ray_cs.c b/drivers/net/pcmcia/ray_cs.c index 81bba9e60..5594f51d1 100644 --- a/drivers/net/pcmcia/ray_cs.c +++ b/drivers/net/pcmcia/ray_cs.c @@ -38,6 +38,7 @@ #include #include +#include #include #include @@ -49,6 +50,19 @@ #include #include +#ifdef HAS_WIRELESS_EXTENSIONS +#include +#if WIRELESS_EXT < 8 +#warning "Wireless extension v8 or newer required" +#endif /* WIRELESS_EXT < 8 */ +/* Warning : these stuff will slow down the driver... */ +#define WIRELESS_SPY /* Enable spying addresses */ +/* Definitions we need for spy */ +typedef struct iw_statistics iw_stats; +typedef struct iw_quality iw_qual; +typedef u_char mac_addr[ETH_ALEN]; /* Hardware address */ +#endif /* HAS_WIRELESS_EXTENSIONS */ + #include "rayctl.h" #include "ray_cs.h" @@ -72,67 +86,68 @@ MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) #endif /** Prototypes based on PCMCIA skeleton driver *******************************/ -void ray_config(dev_link_t *link); -void ray_release(u_long arg); -int ray_event(event_t event, int priority, event_callback_args_t *args); -dev_link_t *ray_attach(void); -void ray_detach(dev_link_t *); +static void ray_config(dev_link_t *link); +static void ray_release(u_long arg); +static int ray_event(event_t event, int priority, event_callback_args_t *args); +static dev_link_t *ray_attach(void); +static void ray_detach(dev_link_t *); /***** Prototypes indicated by device structure ******************************/ -int ray_dev_close(struct net_device *dev); -int ray_dev_config(struct net_device *dev, struct ifmap *map); -struct enet_statistics *ray_get_stats(struct net_device *dev); -int ray_dev_init(struct net_device *dev); -int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -int ray_open(struct net_device *dev); -int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev); +static int ray_dev_close(struct net_device *dev); +static int ray_dev_config(struct net_device *dev, struct ifmap *map); +static struct enet_statistics *ray_get_stats(struct net_device *dev); +static int ray_dev_init(struct net_device *dev); +static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); +static int ray_open(struct net_device *dev); +static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev); static void set_multicast_list(struct net_device *dev); static void ray_update_multi_list(struct net_device *dev, int all); -int encapsulate_frame(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type, - unsigned char *data, int len); -int translate_frame(ray_dev_t *local, struct tx_msg *ptx, +static int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data, int len); -void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type, +static void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type, unsigned char *data); -void untranslate(ray_dev_t *local, struct sk_buff *skb, int len); +static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len); +#if WIRELESS_EXT > 7 /* If wireless extension exist in the kernel */ +static iw_stats * ray_get_wireless_stats(struct device * dev); +#endif /* WIRELESS_EXT > 7 */ /***** Prototypes for raylink functions **************************************/ -int asc_to_int(char a); -void authenticate(ray_dev_t *local); -int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type); -void authenticate_timeout(u_long); -int get_free_ccs(ray_dev_t *local); -int get_free_tx_ccs(ray_dev_t *local); -void init_startup_params(ray_dev_t *local); -int parse_addr(char *in_str, UCHAR *out); -int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, UCHAR type); -int ray_init(struct net_device *dev); -int interrupt_ecf(ray_dev_t *local, int ccs); -void ray_reset(struct net_device *dev); -void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len); -void verify_dl_startup(u_long); +static int asc_to_int(char a); +static void authenticate(ray_dev_t *local); +static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type); +static void authenticate_timeout(u_long); +static int get_free_ccs(ray_dev_t *local); +static int get_free_tx_ccs(ray_dev_t *local); +static void init_startup_params(ray_dev_t *local); +static int parse_addr(char *in_str, UCHAR *out); +static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, UCHAR type); +static int ray_init(struct net_device *dev); +static int interrupt_ecf(ray_dev_t *local, int ccs); +static void ray_reset(struct net_device *dev); +static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len); +static void verify_dl_startup(u_long); /* Prototypes for interrpt time functions **********************************/ -void ray_interrupt(int reg, void *dev_id, struct pt_regs *regs); -void clear_interrupt(ray_dev_t *local); -void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, +static void ray_interrupt (int reg, void *dev_id, struct pt_regs *regs); +static void clear_interrupt(ray_dev_t *local); +static void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, unsigned int pkt_addr, int rx_len); -int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int len); -void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs); -void release_frag_chain(ray_dev_t *local, struct rcs *prcs); -void rx_authenticate(ray_dev_t *local, struct rcs *prcs, +static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int len); +static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs); +static void release_frag_chain(ray_dev_t *local, struct rcs *prcs); +static void rx_authenticate(ray_dev_t *local, struct rcs *prcs, unsigned int pkt_addr, int rx_len); -void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, +static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, int rx_len); -void associate(ray_dev_t *local); +static void associate(ray_dev_t *local); /* Card command functions */ -int dl_startup_params(struct net_device *dev); -void join_net(u_long local); -void start_net(u_long local); +static int dl_startup_params(struct net_device *dev); +static void join_net(u_long local); +static void start_net(u_long local); /* void start_net(ray_dev_t *local); */ -int ray_cs_proc_read(char *buf, char **start, off_t off, int len, int spare); +static int ray_cs_proc_read(char *buf, char **start, off_t off, int len, int spare); /* Create symbol table for registering with kernel in init_module */ EXPORT_SYMBOL(ray_dev_ioctl); EXPORT_SYMBOL(ray_rx); @@ -283,6 +298,14 @@ static UCHAR b4_default_startup_parms[] = { /*===========================================================================*/ static unsigned char eth2_llc[] = {0xaa, 0xaa, 3, 0, 0, 0}; +static char hop_pattern_length[] = { 1, + USA_HOP_MOD, EUROPE_HOP_MOD, + JAPAN_HOP_MOD, KOREA_HOP_MOD, + SPAIN_HOP_MOD, FRANCE_HOP_MOD, + ISRAEL_HOP_MOD, AUSTRALIA_HOP_MOD, + JAPAN_TEST_HOP_MOD +}; + static char rcsid[] = "Raylink/WebGear wireless LAN - Corey "; #ifdef CONFIG_PROC_FS @@ -298,7 +321,7 @@ struct proc_dir_entry ray_cs_proc_entry = { }; #endif /*===========================================================================*/ -void cs_error(client_handle_t handle, int func, int ret) +static void cs_error(client_handle_t handle, int func, int ret) { error_info_t err = { func, ret }; CardServices(ReportError, handle, &err); @@ -311,7 +334,7 @@ void cs_error(client_handle_t handle, int func, int ret) configure the card at this point -- we wait until we receive a card insertion event. =============================================================================*/ -dev_link_t *ray_attach(void) +static dev_link_t *ray_attach(void) { client_reg_t client_reg; dev_link_t *link; @@ -367,6 +390,9 @@ dev_link_t *ray_attach(void) dev->set_config = &ray_dev_config; dev->get_stats = &ray_get_stats; dev->do_ioctl = &ray_dev_ioctl; +#if WIRELESS_EXT > 7 /* If wireless extension exist in the kernel */ + dev->get_wireless_stats = ray_get_wireless_stats; +#endif dev->set_multicast_list = &set_multicast_list; @@ -411,7 +437,7 @@ dev_link_t *ray_attach(void) structures are freed. Otherwise, the structures will be freed when the device is released. =============================================================================*/ -void ray_detach(dev_link_t *link) +static void ray_detach(dev_link_t *link) { dev_link_t **linkp; struct net_device *dev; @@ -470,7 +496,7 @@ void ray_detach(dev_link_t *link) #define CS_CHECK(fn, args...) \ while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed #define MAX_TUPLE_SIZE 128 -void ray_config(dev_link_t *link) +static void ray_config(dev_link_t *link) { client_handle_t handle = link->handle; tuple_t tuple; @@ -585,7 +611,7 @@ cs_failed: ray_release((u_long)link); } /* ray_config */ /*===========================================================================*/ -int ray_init(struct net_device *dev) +static int ray_init(struct net_device *dev) { int i; UCHAR *p; @@ -648,7 +674,7 @@ int ray_init(struct net_device *dev) } /* ray_init */ /*===========================================================================*/ /* Download startup parameters to the card and command it to read them */ -int dl_startup_params(struct net_device *dev) +static int dl_startup_params(struct net_device *dev) { int ccsindex; ray_dev_t *local = (ray_dev_t *)dev->priv; @@ -694,16 +720,9 @@ int dl_startup_params(struct net_device *dev) return 0; } /* dl_startup_params */ /*===========================================================================*/ -void init_startup_params(ray_dev_t *local) +static void init_startup_params(ray_dev_t *local) { int i; - static char hop_pattern_length[] = { 1, - USA_HOP_MOD, EUROPE_HOP_MOD, - JAPAN_HOP_MOD, KOREA_HOP_MOD, - SPAIN_HOP_MOD, FRANCE_HOP_MOD, - ISRAEL_HOP_MOD, AUSTRALIA_HOP_MOD, - JAPAN_TEST_HOP_MOD - }; if (country > JAPAN_TEST) country = USA; else @@ -762,7 +781,7 @@ void init_startup_params(ray_dev_t *local) strncpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE); } /* init_startup_params */ /*===========================================================================*/ -void verify_dl_startup(u_long data) +static void verify_dl_startup(u_long data) { ray_dev_t *local = (ray_dev_t *)data; struct ccs *pccs = ((struct ccs *)(local->sram + CCS_BASE)) + local->dl_param_ccs; @@ -779,7 +798,7 @@ void verify_dl_startup(u_long data) printk(KERN_DEBUG "verify_dl_startup parameters sent via ccs %d:\n", local->dl_param_ccs); for (i=0; isram + HOST_TO_ECF_BASE + i)); + printk(" %2x", (unsigned int) readb(local->sram + HOST_TO_ECF_BASE + i)); } printk("\n"); } @@ -802,7 +821,7 @@ void verify_dl_startup(u_long data) } /* end verify_dl_startup */ /*===========================================================================*/ /* Command card to start a network */ -void start_net(u_long data) +static void start_net(u_long data) { ray_dev_t *local = (ray_dev_t *)data; struct ccs *pccs; @@ -828,7 +847,7 @@ void start_net(u_long data) } /* end start_net */ /*===========================================================================*/ /* Command card to join a network */ -void join_net(u_long data) +static void join_net(u_long data) { ray_dev_t *local = (ray_dev_t *)data; @@ -860,7 +879,7 @@ void join_net(u_long data) device, and release the PCMCIA configuration. If the device is still open, this will be postponed until it is closed. =============================================================================*/ -void ray_release(u_long arg) +static void ray_release(u_long arg) { dev_link_t *link = (dev_link_t *)arg; struct net_device *dev = link->priv; @@ -912,7 +931,7 @@ void ray_release(u_long arg) actually access the device should check this flag to make sure the card is still present. =============================================================================*/ -int ray_event(event_t event, int priority, +static int ray_event(event_t event, int priority, event_callback_args_t *args) { dev_link_t *link = args->client_data; @@ -991,7 +1010,7 @@ int ray_dev_init(struct net_device *dev) return 0; } /*===========================================================================*/ -int ray_dev_config(struct net_device *dev, struct ifmap *map) +static int ray_dev_config(struct net_device *dev, struct ifmap *map) { ray_dev_t *local = dev->priv; dev_link_t *link = local->finder; @@ -1005,7 +1024,7 @@ int ray_dev_config(struct net_device *dev, struct ifmap *map) return 0; } /*===========================================================================*/ -int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev) +static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev) { ray_dev_t *local = dev->priv; dev_link_t *link = local->finder; @@ -1047,7 +1066,7 @@ int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } /* ray_dev_start_xmit */ /*===========================================================================*/ -int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, +static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, UCHAR msg_type) { ray_dev_t *local = (ray_dev_t *)dev->priv; @@ -1089,7 +1108,7 @@ int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, } else { /* Encapsulate frame */ /* TBD TIB length will move address of ptx->var */ - memcpy( (UCHAR *)&ptx->var, data, len); + memcpy_toio(&ptx->var, data, len); offset = 0; } @@ -1121,7 +1140,7 @@ int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, return XMIT_OK; } /* end ray_hw_xmit */ /*===========================================================================*/ -int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data, +static int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data, int len) { unsigned short int proto = ((struct ethhdr *)data)->h_proto; @@ -1137,7 +1156,7 @@ int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data, /* Copy body of ethernet packet without ethernet header */ memcpy_toio((UCHAR *)&ptx->var + sizeof(struct snaphdr_t), \ data + ETH_HLEN, len - ETH_HLEN); - return sizeof(struct snaphdr_t) - ETH_HLEN; + return (int) sizeof(struct snaphdr_t) - ETH_HLEN; } else { /* already 802 type, and proto is length */ DEBUG(3,"ray_cs translate_frame 802\n"); @@ -1152,15 +1171,16 @@ int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data, /* TBD do other frame types */ } /* end translate_frame */ /*===========================================================================*/ -void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type, +static void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type, unsigned char *data) { writeb(PROTOCOL_VER | msg_type, &ptx->mac.frame_ctl_1); /*** IEEE 802.11 Address field assignments ************* - addr_1 addr_2 addr_3 - AP destination AP(BSSID) source - Infra Terminal AP terminal destination - Adhoc destination terminal BSSID + TODS FROMDS addr_1 addr_2 addr_3 addr_4 +Adhoc 0 0 dest src (terminal) BSSID N/A +AP to Terminal 0 1 dest AP(BSSID) source N/A +Terminal to AP 1 0 AP(BSSID) src (terminal) dest N/A +AP to AP 1 1 dest AP src AP dest source *******************************************************/ if (local->net_type == ADHOC) { writeb(0, &ptx->mac.frame_ctl_2); @@ -1186,11 +1206,14 @@ void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type, } } /* end encapsulate_frame */ /*===========================================================================*/ -int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { ray_dev_t *local = (ray_dev_t *)dev->priv; dev_link_t *link = local->finder; int err = 0; +#if WIRELESS_EXT > 7 + struct iwreq *wrq = (struct iwreq *) ifr; +#endif /* WIRELESS_EXT > 7 */ if (!(link->state & DEV_PRESENT)) { DEBUG(2,"ray_dev_ioctl - device not present\n"); @@ -1200,6 +1223,257 @@ int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) /* Validate the command */ switch (cmd) { +#if WIRELESS_EXT > 7 + /* --------------- WIRELESS EXTENSIONS --------------- */ + /* Get name */ + case SIOCGIWNAME: + strcpy(wrq->u.name, "IEEE 802.11-FH"); + break; + + /* Get frequency/channel */ + case SIOCGIWFREQ: + wrq->u.freq.m = local->sparm.b5.a_hop_pattern; + wrq->u.freq.e = 0; + break; + + /* Get current network name (ESSID) */ + case SIOCGIWESSID: + if (wrq->u.data.pointer) + { + char essid[IW_ESSID_MAX_SIZE + 1]; + /* Get the essid that was set */ + memcpy(essid, local->sparm.b5.a_current_ess_id, + IW_ESSID_MAX_SIZE); + essid[IW_ESSID_MAX_SIZE] = '\0'; + + /* Push it out ! */ + wrq->u.data.length = strlen(essid) + 1; + wrq->u.data.flags = 1; /* active */ + copy_to_user(wrq->u.data.pointer, essid, sizeof(essid)); + } + break; + + /* Get current Access Point (BSSID in our case) */ + case SIOCGIWAP: + memcpy(wrq->u.ap_addr.sa_data, local->bss_id, ETH_ALEN); + wrq->u.ap_addr.sa_family = ARPHRD_ETHER; + break; + + /* Get the current bit-rate */ + case SIOCGIWRATE: + if(local->net_default_tx_rate == 3) + wrq->u.bitrate.value = 2000000; /* Hum... */ + else + wrq->u.bitrate.value = local->net_default_tx_rate * 500000; + wrq->u.bitrate.fixed = 0; /* We are in auto mode */ + break; + + /* Set the desired bit-rate */ + case SIOCSIWRATE: + /* Check if rate is in range */ + if((wrq->u.bitrate.value != 1000000) && + (wrq->u.bitrate.value != 2000000)) + { + err = -EINVAL; + break; + } + /* Hack for 1.5 Mb/s instead of 2 Mb/s */ + if((local->fw_ver == 0x55) && /* Please check */ + (wrq->u.bitrate.value == 2000000)) + local->net_default_tx_rate = 3; + else + local->net_default_tx_rate = wrq->u.bitrate.value/500000; + break; + + /* Get the current RTS threshold */ + case SIOCGIWRTS: + wrq->u.rts.value = (local->sparm.b5.a_rts_threshold[0] << 8) + + local->sparm.b5.a_rts_threshold[1]; +#if WIRELESS_EXT > 8 + wrq->u.rts.disabled = (wrq->u.rts.value == 32767); +#endif /* WIRELESS_EXT > 8 */ + wrq->u.rts.fixed = 1; + break; + + /* Get the current fragmentation threshold */ + case SIOCGIWFRAG: + wrq->u.frag.value = (local->sparm.b5.a_frag_threshold[0] << 8) + + local->sparm.b5.a_frag_threshold[1]; +#if WIRELESS_EXT > 8 + wrq->u.frag.disabled = (wrq->u.frag.value == 32767); +#endif /* WIRELESS_EXT > 8 */ + wrq->u.frag.fixed = 1; + break; +#endif /* WIRELESS_EXT > 7 */ +#if WIRELESS_EXT > 8 + + /* Get the current mode of operation */ + case SIOCGIWMODE: + if(local->sparm.b5.a_network_type) + wrq->u.mode = IW_MODE_INFRA; + else + wrq->u.mode = IW_MODE_ADHOC; + break; +#endif /* WIRELESS_EXT > 8 */ +#if WIRELESS_EXT > 7 + /* ------------------ IWSPY SUPPORT ------------------ */ + /* Define the range (variations) of above parameters */ + case SIOCGIWRANGE: + /* Basic checking... */ + if(wrq->u.data.pointer != (caddr_t) 0) + { + struct iw_range range; + memset((char *) &range, 0, sizeof(struct iw_range)); + + /* Set the length (useless : its constant...) */ + wrq->u.data.length = sizeof(struct iw_range); + + /* Set information in the range struct */ + range.throughput = 1.1 * 1000 * 1000; /* Put the right number here */ + range.num_channels = hop_pattern_length[(int)country]; + range.num_frequency = 0; + range.max_qual.qual = 0; + range.max_qual.level = 255; /* What's the correct value ? */ + range.max_qual.noise = 255; /* Idem */ + range.num_bitrates = 2; + range.bitrate[0] = 1000000; /* 1 Mb/s */ + range.bitrate[1] = 2000000; /* 2 Mb/s */ + + /* Copy structure to the user buffer */ + if(copy_to_user(wrq->u.data.pointer, &range, + sizeof(struct iw_range))) + err = -EFAULT; + } + break; + +#ifdef WIRELESS_SPY + /* Set addresses to spy */ + case SIOCSIWSPY: + /* Check the number of addresses */ + if(wrq->u.data.length > IW_MAX_SPY) + { + err = -E2BIG; + break; + } + local->spy_number = wrq->u.data.length; + + /* If there is some addresses to copy */ + if(local->spy_number > 0) + { + struct sockaddr address[IW_MAX_SPY]; + int i; + + /* Copy addresses to the driver */ + if(copy_from_user(address, wrq->u.data.pointer, + sizeof(struct sockaddr) * local->spy_number)) + { + err = -EFAULT; + break; + } + + /* Copy addresses to the lp structure */ + for(i = 0; i < local->spy_number; i++) + memcpy(local->spy_address[i], address[i].sa_data, ETH_ALEN); + + /* Reset structure... */ + memset(local->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY); + +#ifdef DEBUG_IOCTL_INFO + printk(KERN_DEBUG "SetSpy - Set of new addresses is :\n"); + for(i = 0; i < local->spy_number; i++) + printk(KERN_DEBUG "%02X:%02X:%02X:%02X:%02X:%02X\n", + local->spy_address[i][0], + local->spy_address[i][1], + local->spy_address[i][2], + local->spy_address[i][3], + local->spy_address[i][4], + local->spy_address[i][5]); +#endif /* DEBUG_IOCTL_INFO */ + } + break; + + /* Get the spy list and spy stats */ + case SIOCGIWSPY: + /* Set the number of addresses */ + wrq->u.data.length = local->spy_number; + + /* If the user want to have the addresses back... */ + if((local->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0)) + { + struct sockaddr address[IW_MAX_SPY]; + int i; + + /* Copy addresses from the lp structure */ + for(i = 0; i < local->spy_number; i++) + { + memcpy(address[i].sa_data, local->spy_address[i], ETH_ALEN); + address[i].sa_family = ARPHRD_ETHER; + } + + /* Copy addresses to the user buffer */ + if(copy_to_user(wrq->u.data.pointer, address, + sizeof(struct sockaddr) * local->spy_number)) + { + err = -EFAULT; + break; + } + + /* Copy stats to the user buffer (just after) */ + if(copy_to_user(wrq->u.data.pointer + + (sizeof(struct sockaddr) * local->spy_number), + local->spy_stat, sizeof(iw_qual) * local->spy_number)) + { + err = -EFAULT; + break; + } + + /* Reset updated flags */ + for(i = 0; i < local->spy_number; i++) + local->spy_stat[i].updated = 0x0; + } /* if(pointer != NULL) */ + + break; +#endif /* WIRELESS_SPY */ + + /* ------------------ PRIVATE IOCTL ------------------ */ +#define SIOCSIPFRAMING SIOCDEVPRIVATE /* Set framing mode */ +#define SIOCGIPFRAMING SIOCDEVPRIVATE + 1 /* Get framing mode */ +#define SIOCGIPCOUNTRY SIOCDEVPRIVATE + 3 /* Get country code */ + case SIOCSIPFRAMING: + if(!suser()) /* For private IOCTLs, we need to check permissions */ + { + err = -EPERM; + break; + } + translate = *(wrq->u.name); /* Set framing mode */ + break; + case SIOCGIPFRAMING: + *(wrq->u.name) = translate; + break; + case SIOCGIPCOUNTRY: + *(wrq->u.name) = country; + break; + case SIOCGIWPRIV: + /* Export our "private" intercace */ + if(wrq->u.data.pointer != (caddr_t) 0) + { + struct iw_priv_args priv[] = + { /* cmd, set_args, get_args, name */ + { SIOCSIPFRAMING, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "set_framing" }, + { SIOCGIPFRAMING, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_framing" }, + { SIOCGIPCOUNTRY, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_country" }, + }; + /* Set the number of ioctl available */ + wrq->u.data.length = 3; + /* Copy structure to the user buffer */ + if(copy_to_user(wrq->u.data.pointer, (u_char *) priv, + sizeof(priv))) + err = -EFAULT; + } + break; +#endif /* WIRELESS_EXT > 7 */ + + default: DEBUG(0,"ray_dev_ioctl cmd = 0x%x\n", cmd); err = -EOPNOTSUPP; @@ -1207,7 +1481,38 @@ int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return err; } /* end ray_dev_ioctl */ /*===========================================================================*/ -int ray_open(struct net_device *dev) +#if WIRELESS_EXT > 7 /* If wireless extension exist in the kernel */ +static iw_stats * ray_get_wireless_stats(struct device * dev) +{ + ray_dev_t * local = (ray_dev_t *) dev->priv; + dev_link_t *link = local->finder; + struct status *p = (struct status *)(local->sram + STATUS_BASE); + + if(local == (ray_dev_t *) NULL) + return (iw_stats *) NULL; + + local->wstats.status = local->card_status; +#ifdef WIRELESS_SPY + if((local->spy_number > 0) && (local->sparm.b5.a_network_type == 0)) + { + /* Get it from the first node in spy list */ + local->wstats.qual.qual = local->spy_stat[0].qual; + local->wstats.qual.level = local->spy_stat[0].level; + local->wstats.qual.noise = local->spy_stat[0].noise; + local->wstats.qual.updated = local->spy_stat[0].updated; + } +#endif /* WIRELESS_SPY */ + + if((link->state & DEV_PRESENT)) { + local->wstats.qual.noise = readb(&p->rxnoise); + local->wstats.qual.updated |= 4; + } + + return &local->wstats; +} /* end ray_get_wireless_stats */ +#endif /* WIRELESS_EXT > 7 */ +/*===========================================================================*/ +static int ray_open(struct net_device *dev) { dev_link_t *link; ray_dev_t *local = (ray_dev_t *)dev->priv; @@ -1232,7 +1537,7 @@ int ray_open(struct net_device *dev) return 0; } /* end ray_open */ /*===========================================================================*/ -int ray_dev_close(struct net_device *dev) +static int ray_dev_close(struct net_device *dev) { dev_link_t *link; @@ -1255,14 +1560,14 @@ int ray_dev_close(struct net_device *dev) return 0; } /* end ray_dev_close */ /*===========================================================================*/ -void ray_reset(struct net_device *dev) { +static void ray_reset(struct net_device *dev) { DEBUG(1,"ray_reset entered\n"); return; } /*===========================================================================*/ /* Cause a firmware interrupt if it is ready for one */ /* Return nonzero if not ready */ -int interrupt_ecf(ray_dev_t *local, int ccs) +static int interrupt_ecf(ray_dev_t *local, int ccs) { int i = 50; dev_link_t *link = local->finder; @@ -1288,7 +1593,7 @@ int interrupt_ecf(ray_dev_t *local, int ccs) /*===========================================================================*/ /* Get next free transmit CCS */ /* Return - index of current tx ccs */ -int get_free_tx_ccs(ray_dev_t *local) +static int get_free_tx_ccs(ray_dev_t *local) { int i; struct ccs *pccs = (struct ccs *)(local->sram + CCS_BASE); @@ -1319,7 +1624,7 @@ int get_free_tx_ccs(ray_dev_t *local) /*===========================================================================*/ /* Get next free CCS */ /* Return - index of current ccs */ -int get_free_ccs(ray_dev_t *local) +static int get_free_ccs(ray_dev_t *local) { int i; struct ccs *pccs = (struct ccs *)(local->sram + CCS_BASE); @@ -1347,7 +1652,7 @@ int get_free_ccs(ray_dev_t *local) return ECCSFULL; } /* get_free_ccs */ /*===========================================================================*/ -void authenticate_timeout(u_long data) +static void authenticate_timeout(u_long data) { ray_dev_t *local = (ray_dev_t *)data; del_timer(&local->timer); @@ -1356,7 +1661,7 @@ void authenticate_timeout(u_long data) join_net((u_long)local); } /*===========================================================================*/ -int asc_to_int(char a) +static int asc_to_int(char a) { if (a < '0') return -1; if (a <= '9') return (a - '0'); @@ -1367,7 +1672,7 @@ int asc_to_int(char a) return -1; } /*===========================================================================*/ -int parse_addr(char *in_str, UCHAR *out) +static int parse_addr(char *in_str, UCHAR *out) { int len; int i,j,k; @@ -1395,7 +1700,7 @@ int parse_addr(char *in_str, UCHAR *out) return status; } /*===========================================================================*/ -struct enet_statistics *ray_get_stats(struct net_device *dev) +static struct enet_statistics *ray_get_stats(struct net_device *dev) { ray_dev_t *local = (ray_dev_t *)dev->priv; dev_link_t *link = local->finder; @@ -1425,7 +1730,7 @@ struct enet_statistics *ray_get_stats(struct net_device *dev) return &local->stats; } /*===========================================================================*/ -void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len) +static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len) { ray_dev_t *local = (ray_dev_t *)dev->priv; dev_link_t *link = local->finder; @@ -1542,7 +1847,7 @@ static void set_multicast_list(struct net_device *dev) /*============================================================================= * All routines below here are run at interrupt time. =============================================================================*/ -void ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) +static void ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct net_device *dev = (struct net_device *)dev_id; dev_link_t *link; @@ -1727,7 +2032,7 @@ void ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) break; default: DEBUG(1,"ray_cs Unexpected interrupt for RCS 0x%x cmd = 0x%x\n",\ - rcsindex, readb(&prcs->interrupt_id)); + rcsindex, (unsigned int) readb(&prcs->interrupt_id)); break; } writeb(CCS_BUFFER_FREE, &prcs->buffer_status); @@ -1736,7 +2041,7 @@ void ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) dev->interrupt = 0; } /* ray_interrupt */ /*===========================================================================*/ -void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs) +static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs) { int rx_len; unsigned int pkt_addr; @@ -1750,6 +2055,7 @@ void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs) rx_len = (readb(&prcs->var.rx_packet.rx_data_length[0]) << 8) + readb(&prcs->var.rx_packet.rx_data_length[1]); + local->last_rsl = readb(&prcs->var.rx_packet.rx_sig_lev); pmsg = local->rmem + pkt_addr; switch(readb(pmsg)) { @@ -1778,17 +2084,18 @@ void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs) rx_len < sizeof(struct beacon_rx) ? rx_len : sizeof(struct beacon_rx)); + local->beacon_rxed = 1; /* Get the statistics so the card counters never overflow */ ray_get_stats(dev); break; default: - DEBUG(0,"ray_cs unknown pkt type %2x\n", readb(pmsg)); + DEBUG(0,"ray_cs unknown pkt type %2x\n", (unsigned int) readb(pmsg)); break; } } /* end ray_rx */ /*===========================================================================*/ -void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, +static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, int rx_len) { struct sk_buff *skb = NULL; @@ -1797,6 +2104,10 @@ void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, UCHAR *rx_ptr; int total_len; int tmp; +#ifdef WIRELESS_SPY + int siglev = prcs->var.rx_packet.rx_sig_lev; + u_char linksrcaddr[ETH_ALEN]; /* Other end of the wireless link */ +#endif if (!sniffer) { if (translate) { @@ -1819,7 +2130,7 @@ void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, } DEBUG(4,"ray_cs rx_data packet\n"); /* If fragmented packet, verify sizes of fragments add up */ - if (prcs->var.rx_packet.next_frag_rcs_index != 0xFF) { + if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) { DEBUG(1,"ray_cs rx'ed fragment\n"); tmp = (readb(&prcs->var.rx_packet.totalpacketlength[0]) << 8) + readb(&prcs->var.rx_packet.totalpacketlength[1]); @@ -1865,7 +2176,10 @@ void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, rx_ptr = skb_put( skb, total_len); /* Copy the whole packet to sk_buff */ rx_ptr += copy_from_rx_buff(local, rx_ptr, pkt_addr & RX_BUFF_END, rx_len); - + /* Get source address */ +#ifdef WIRELESS_SPY + memcpy(linksrcaddr, ((struct mac_header *)skb->data)->addr_2, ETH_ALEN); +#endif /* Now, deal with encapsulation/translation/sniffer */ if (!sniffer) { if (!translate) { @@ -1909,9 +2223,39 @@ void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, local->stats.rx_packets++; local->stats.rx_bytes += skb->len; + + /* Gather signal strength per address */ +#ifdef WIRELESS_SPY + /* For the Access Point or the node having started the ad-hoc net + * note : ad-hoc work only in some specific configurations, but we + * kludge in ray_get_wireless_stats... */ + if(!memcmp(linksrcaddr, local->bss_id, ETH_ALEN)) + { + /* Update statistics */ + /*local->wstats.qual.qual = none ? */ + local->wstats.qual.level = siglev; + /*local->wstats.qual.noise = none ? */ + local->wstats.qual.updated = 0x2; + } + /* Now, for the addresses in the spy list */ + { + int i; + /* Look all addresses */ + for(i = 0; i < local->spy_number; i++) + /* If match */ + if(!memcmp(linksrcaddr, local->spy_address[i], ETH_ALEN)) + { + /* Update statistics */ + /*local->spy_stat[i].qual = none ? */ + local->spy_stat[i].level = siglev; + /*local->spy_stat[i].noise = none ? */ + local->spy_stat[i].updated = 0x2; + } + } +#endif /* WIRELESS_SPY */ } /* end rx_data */ /*===========================================================================*/ -void untranslate(ray_dev_t *local, struct sk_buff *skb, int len) +static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len) { snaphdr_t *psnap = (snaphdr_t *)(skb->data + RX_MAC_HEADER_LENGTH); struct mac_header *pmac = (struct mac_header *)skb->data; @@ -1923,11 +2267,23 @@ void untranslate(ray_dev_t *local, struct sk_buff *skb, int len) UCHAR srcaddr[ADDRLEN]; UCHAR destaddr[ADDRLEN]; - if (local->sparm.b5.a_acting_as_ap_status != TYPE_STA) - memcpy(destaddr, pmac->addr_3, ADDRLEN); - else - memcpy(destaddr, pmac->addr_1, ADDRLEN); - memcpy(srcaddr, pmac->addr_2, ADDRLEN); + if (pmac->frame_ctl_2 & FC2_FROM_DS) { + if (pmac->frame_ctl_2 & FC2_TO_DS) { /* AP to AP */ + memcpy(destaddr, pmac->addr_3, ADDRLEN); + memcpy(srcaddr, ((unsigned char *)pmac->addr_3) + ADDRLEN, ADDRLEN); + } else { /* AP to terminal */ + memcpy(destaddr, pmac->addr_1, ADDRLEN); + memcpy(srcaddr, pmac->addr_3, ADDRLEN); + } + } else { /* Terminal to AP */ + if (pmac->frame_ctl_2 & FC2_TO_DS) { + memcpy(destaddr, pmac->addr_3, ADDRLEN); + memcpy(srcaddr, pmac->addr_2, ADDRLEN); + } else { /* Adhoc */ + memcpy(destaddr, pmac->addr_1, ADDRLEN); + memcpy(srcaddr, pmac->addr_2, ADDRLEN); + } + } #ifdef PCMCIA_DEBUG if (pc_debug > 3) { @@ -2005,7 +2361,7 @@ void untranslate(ray_dev_t *local, struct sk_buff *skb, int len) * pkt_addr = source address in receive buffer * len = length of packet to copy */ -int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int length) +static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int length) { int wrap_bytes = (pkt_addr + length) - (RX_BUFF_END + 1); if (wrap_bytes <= 0) @@ -2020,7 +2376,7 @@ int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int length) return length; } /*===========================================================================*/ -void release_frag_chain(ray_dev_t *local, struct rcs* prcs) +static void release_frag_chain(ray_dev_t *local, struct rcs* prcs) { struct rcs *prcslink = prcs; int tmp = 17; @@ -2038,7 +2394,7 @@ void release_frag_chain(ray_dev_t *local, struct rcs* prcs) writeb(CCS_BUFFER_FREE, &prcslink->buffer_status); } /*===========================================================================*/ -void authenticate(ray_dev_t *local) +static void authenticate(ray_dev_t *local) { dev_link_t *link = local->finder; DEBUG(0,"ray_cs Starting authentication.\n"); @@ -2060,7 +2416,7 @@ void authenticate(ray_dev_t *local) local->authentication_state = AWAITING_RESPONSE; } /* end authenticate */ /*===========================================================================*/ -void rx_authenticate(ray_dev_t *local, struct rcs *prcs, +static void rx_authenticate(ray_dev_t *local, struct rcs *prcs, unsigned int pkt_addr, int rx_len) { UCHAR buff[256]; @@ -2103,7 +2459,7 @@ void rx_authenticate(ray_dev_t *local, struct rcs *prcs, } /* end rx_authenticate */ /*===========================================================================*/ -void associate(ray_dev_t *local) +static void associate(ray_dev_t *local) { struct ccs *pccs; dev_link_t *link = local->finder; @@ -2141,7 +2497,7 @@ void associate(ray_dev_t *local) } /* end associate */ /*===========================================================================*/ -void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, +static void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, unsigned int pkt_addr, int rx_len) { /* UCHAR buff[256]; @@ -2154,7 +2510,7 @@ void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, */ } /*===========================================================================*/ -void clear_interrupt(ray_dev_t *local) +static void clear_interrupt(ray_dev_t *local) { writeb(0, local->amem + CIS_OFFSET + HCS_INTR_OFFSET); } @@ -2183,7 +2539,7 @@ static char *nettype[] = {"Adhoc", "Infra "}; static char *framing[] = {"Encapsulation", "Translation"} ; /*===========================================================================*/ -int ray_cs_proc_read(char *buf, char **start, off_t offset, +static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len, int unused) { /* Print current values which are not available via other means @@ -2229,10 +2585,13 @@ int ray_cs_proc_read(char *buf, char **start, off_t offset, len += sprintf(buf + len, "Framing mode = %s\n",framing[translate]); - /* Pull some fields out of last beacon received */ - len += sprintf(buf + len, "Beacon Interval = %d Kus\n", - local->last_bcn.beacon_intvl[0] - + 256 * local->last_bcn.beacon_intvl[1]); + len += sprintf(buf + len, "Last pkt signal lvl = %d\n", local->last_rsl); + + if (local->beacon_rxed) { + /* Pull some fields out of last beacon received */ + len += sprintf(buf + len, "Beacon Interval = %d Kus\n", + local->last_bcn.beacon_intvl[0] + + 256 * local->last_bcn.beacon_intvl[1]); p = local->last_bcn.elements; if (p[0] == C_ESSID_ELEMENT_ID) p += p[1] + 2; @@ -2253,25 +2612,28 @@ int ray_cs_proc_read(char *buf, char **start, off_t offset, return len; } - if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) { - pfh = (struct freq_hop_element *)p; - len += sprintf(buf + len, "Hop dwell = %d Kus\n", - pfh->dwell_time[0] + 256 * pfh->dwell_time[1]); - len += sprintf(buf + len, "Hop set = %d \n", pfh->hop_set); - len += sprintf(buf + len, "Hop pattern = %d \n", pfh->hop_pattern); - len += sprintf(buf + len, "Hop index = %d \n", pfh->hop_index); - p += p[1] + 2; - } - else { - len += sprintf(buf + len, "Parse beacon failed at FH param element\n"); - return len; + if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) { + pfh = (struct freq_hop_element *)p; + len += sprintf(buf + len, "Hop dwell = %d Kus\n", + pfh->dwell_time[0] + 256 * pfh->dwell_time[1]); + len += sprintf(buf + len, "Hop set = %d \n", pfh->hop_set); + len += sprintf(buf + len, "Hop pattern = %d \n", pfh->hop_pattern); + len += sprintf(buf + len, "Hop index = %d \n", pfh->hop_index); + p += p[1] + 2; + } + else { + len += sprintf(buf + len, "Parse beacon failed at FH param element\n"); + return len; + } + } else { + len += sprintf(buf + len, "No beacons received\n"); } return len; } #endif /*===========================================================================*/ -int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type) +static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type) { int addr; struct ccs *pccs; diff --git a/drivers/net/pcmcia/ray_cs.h b/drivers/net/pcmcia/ray_cs.h index ae28bc71a..6f6f8e6ca 100644 --- a/drivers/net/pcmcia/ray_cs.h +++ b/drivers/net/pcmcia/ray_cs.h @@ -60,7 +60,18 @@ typedef struct ray_dev_t { UCHAR ASIC_version; UCHAR assoc_id[2]; UCHAR tib_length; + UCHAR last_rsl; + int beacon_rxed; struct beacon_rx last_bcn; +#ifdef WIRELESS_EXT + iw_stats wstats; /* Wireless specific stats */ +#endif +#ifdef WIRELESS_SPY + int spy_number; /* Number of addresses to spy */ + mac_addr spy_address[IW_MAX_SPY + 1]; /* The addresses to spy */ + iw_qual spy_stat[IW_MAX_SPY + 1]; /* Statistics gathered */ +#endif /* WIRELESS_SPY */ + } ray_dev_t; /*****************************************************************************/ diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 19b0c5819..bfe494177 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -561,6 +561,7 @@ ppp_init(struct net_device *dev) #ifndef MODULE extern struct compressor ppp_deflate, ppp_deflate_draft; extern int ppp_async_init(void); + extern int ppp_sync_init(void); #endif printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n"); @@ -571,6 +572,9 @@ ppp_init(struct net_device *dev) #ifdef CONFIG_PPP_ASYNC ppp_async_init(); #endif +#ifdef CONFIG_PPP_SYNC_TTY + ppp_sync_init(); +#endif #ifdef CONFIG_PPP_DEFLATE if (ppp_register_compressor(&ppp_deflate) == 0) printk(KERN_INFO "PPP Deflate compression module registered\n"); diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c new file mode 100644 index 000000000..5a1755b4e --- /dev/null +++ b/drivers/net/ppp_synctty.c @@ -0,0 +1,768 @@ +/* + * PPP synchronous tty channel driver for Linux. + * + * This is a ppp channel driver that can be used with tty device drivers + * that are frame oriented, such as synchronous HDLC devices. + * + * Complete PPP frames without encoding/decoding are exchanged between + * the channel driver and the device driver. + * + * The async map IOCTL codes are implemented to keep the user mode + * applications happy if they call them. Synchronous PPP does not use + * the async maps. + * + * Copyright 1999 Paul Mackerras. + * + * Also touched by the grubby hands of Paul Fulghum paulkf@microgate.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * This driver provides the encapsulation and framing for sending + * and receiving PPP frames over sync serial lines. It relies on + * the generic PPP layer to give it frames to send and to process + * received frames. It implements the PPP line discipline. + * + * Part of the code in this driver was inspired by the old sync-only + * PPP driver, written by Michael Callahan and Al Longyear, and + * subsequently hacked by Paul Mackerras. + * + * ==FILEVERSION 991014== + */ + +/* $Id: ppp_synctty.c,v 1.3 1999/09/02 05:30:10 paulus Exp $ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PPP_VERSION "2.4.0" + +/* Structure for storing local state. */ +struct syncppp { + struct tty_struct *tty; + unsigned int flags; + unsigned int rbits; + int mru; + unsigned long busy; + u32 xaccm[8]; + u32 raccm; + unsigned int bytes_sent; + unsigned int bytes_rcvd; + + struct sk_buff *tpkt; + struct sk_buff_head xq; + unsigned long last_xmit; + + struct sk_buff *rpkt; + struct sk_buff_head rq; + wait_queue_head_t rwait; + + struct ppp_channel chan; /* interface to generic ppp layer */ + int connected; +}; + +/* Bit numbers in busy */ +#define XMIT_BUSY 0 +#define RECV_BUSY 1 +#define XMIT_WAKEUP 2 +#define XMIT_FULL 3 + +/* Bits in rbits */ +#define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP) + +#define PPPSYNC_MAX_RQLEN 32 /* arbitrary */ + +/* + * Prototypes. + */ +static struct sk_buff* ppp_sync_txdequeue(struct syncppp *ap); +static int ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb); +static int ppp_sync_push(struct syncppp *ap); +static void ppp_sync_flush_output(struct syncppp *ap); +static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf, + char *flags, int count); + +struct ppp_channel_ops sync_ops = { + ppp_sync_send +}; + +/* + * Routines for locking and unlocking the transmit and receive paths. + */ +static inline void +lock_path(struct syncppp *ap, int bit) +{ + do { + while (test_bit(bit, &ap->busy)) + mb(); + } while (test_and_set_bit(bit, &ap->busy)); + mb(); +} + +static inline int +trylock_path(struct syncppp *ap, int bit) +{ + if (test_and_set_bit(bit, &ap->busy)) + return 0; + mb(); + return 1; +} + +static inline void +unlock_path(struct syncppp *ap, int bit) +{ + mb(); + clear_bit(bit, &ap->busy); +} + +#define lock_xmit_path(ap) lock_path(ap, XMIT_BUSY) +#define trylock_xmit_path(ap) trylock_path(ap, XMIT_BUSY) +#define unlock_xmit_path(ap) unlock_path(ap, XMIT_BUSY) +#define lock_recv_path(ap) lock_path(ap, RECV_BUSY) +#define trylock_recv_path(ap) trylock_path(ap, RECV_BUSY) +#define unlock_recv_path(ap) unlock_path(ap, RECV_BUSY) + +static inline void +flush_skb_queue(struct sk_buff_head *q) +{ + struct sk_buff *skb; + + while ((skb = skb_dequeue(q)) != 0) + kfree_skb(skb); +} + +/* + * Routines implementing the synchronous PPP line discipline. + */ + +/* + * Called when a tty is put into line discipline. + */ +static int +ppp_sync_open(struct tty_struct *tty) +{ + struct syncppp *ap; + + ap = kmalloc(sizeof(*ap), GFP_KERNEL); + if (ap == 0) + return -ENOMEM; + + MOD_INC_USE_COUNT; + + /* initialize the syncppp structure */ + memset(ap, 0, sizeof(*ap)); + ap->tty = tty; + ap->mru = PPP_MRU; + ap->xaccm[0] = ~0U; + ap->xaccm[3] = 0x60000000U; + ap->raccm = ~0U; + skb_queue_head_init(&ap->xq); + skb_queue_head_init(&ap->rq); + init_waitqueue_head(&ap->rwait); + + tty->disc_data = ap; + + return 0; +} + +/* + * Called when the tty is put into another line discipline + * (or it hangs up). + */ +static void +ppp_sync_close(struct tty_struct *tty) +{ + struct syncppp *ap = tty->disc_data; + + if (ap == 0) + return; + tty->disc_data = 0; + lock_xmit_path(ap); + lock_recv_path(ap); + if (ap->rpkt != 0) + kfree_skb(ap->rpkt); + flush_skb_queue(&ap->rq); + if (ap->tpkt != 0) + kfree_skb(ap->tpkt); + flush_skb_queue(&ap->xq); + if (ap->connected) + ppp_unregister_channel(&ap->chan); + kfree(ap); + MOD_DEC_USE_COUNT; +} + +/* + * Read a PPP frame. pppd can use this to negotiate over the + * channel before it joins it to a bundle. + */ +static ssize_t +ppp_sync_read(struct tty_struct *tty, struct file *file, + unsigned char *buf, size_t count) +{ + struct syncppp *ap = tty->disc_data; + DECLARE_WAITQUEUE(wait, current); + ssize_t ret; + struct sk_buff *skb = 0; + + ret = -ENXIO; + if (ap == 0) + goto out; /* should never happen */ + + add_wait_queue(&ap->rwait, &wait); + current->state = TASK_INTERRUPTIBLE; + for (;;) { + ret = -EAGAIN; + skb = skb_dequeue(&ap->rq); + if (skb) + break; + if (file->f_flags & O_NONBLOCK) + break; + ret = -ERESTARTSYS; + if (signal_pending(current)) + break; + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&ap->rwait, &wait); + + if (skb == 0) + goto out; + + ret = -EOVERFLOW; + if (skb->len > count) + goto outf; + ret = -EFAULT; + if (copy_to_user(buf, skb->data, skb->len)) + goto outf; + ret = skb->len; + + outf: + kfree_skb(skb); + out: + return ret; +} + +/* + * Write a ppp frame. pppd can use this to send frames over + * this particular channel. + */ +static ssize_t +ppp_sync_write(struct tty_struct *tty, struct file *file, + const unsigned char *buf, size_t count) +{ + struct syncppp *ap = tty->disc_data; + struct sk_buff *skb; + ssize_t ret; + + ret = -ENXIO; + if (ap == 0) + goto out; /* should never happen */ + + ret = -ENOMEM; + skb = alloc_skb(count + 2, GFP_KERNEL); + if (skb == 0) + goto out; + skb_reserve(skb, 2); + ret = -EFAULT; + if (copy_from_user(skb_put(skb, count), buf, count)) { + kfree_skb(skb); + goto out; + } + + skb_queue_tail(&ap->xq, skb); + ppp_sync_push(ap); + + ret = count; + + out: + return ret; +} + +static int +ppp_sync_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct syncppp *ap = tty->disc_data; + int err, val; + u32 accm[8]; + struct sk_buff *skb; + + err = -ENXIO; + if (ap == 0) + goto out; /* should never happen */ + err = -EPERM; + if (!capable(CAP_NET_ADMIN)) + goto out; + + err = -EFAULT; + switch (cmd) { + case PPPIOCGFLAGS: + val = ap->flags | ap->rbits; + if (put_user(val, (int *) arg)) + break; + err = 0; + break; + case PPPIOCSFLAGS: + if (get_user(val, (int *) arg)) + break; + ap->flags = val & ~SC_RCV_BITS; + ap->rbits = val & SC_RCV_BITS; + err = 0; + break; + + case PPPIOCGASYNCMAP: + if (put_user(ap->xaccm[0], (u32 *) arg)) + break; + err = 0; + break; + case PPPIOCSASYNCMAP: + if (get_user(ap->xaccm[0], (u32 *) arg)) + break; + err = 0; + break; + + case PPPIOCGRASYNCMAP: + if (put_user(ap->raccm, (u32 *) arg)) + break; + err = 0; + break; + case PPPIOCSRASYNCMAP: + if (get_user(ap->raccm, (u32 *) arg)) + break; + err = 0; + break; + + case PPPIOCGXASYNCMAP: + if (copy_to_user((void *) arg, ap->xaccm, sizeof(ap->xaccm))) + break; + err = 0; + break; + case PPPIOCSXASYNCMAP: + if (copy_from_user(accm, (void *) arg, sizeof(accm))) + break; + accm[2] &= ~0x40000000U; /* can't escape 0x5e */ + accm[3] |= 0x60000000U; /* must escape 0x7d, 0x7e */ + memcpy(ap->xaccm, accm, sizeof(ap->xaccm)); + err = 0; + break; + + case PPPIOCGMRU: + if (put_user(ap->mru, (int *) arg)) + break; + err = 0; + break; + case PPPIOCSMRU: + if (get_user(val, (int *) arg)) + break; + if (val < PPP_MRU) + val = PPP_MRU; + ap->mru = val; + err = 0; + break; + + case PPPIOCATTACH: + if (get_user(val, (int *) arg)) + break; + err = -EALREADY; + if (ap->connected) + break; + ap->chan.private = ap; + ap->chan.ops = &sync_ops; + err = ppp_register_channel(&ap->chan, val); + if (err != 0) + break; + ap->connected = 1; + break; + case PPPIOCDETACH: + err = -ENXIO; + if (!ap->connected) + break; + ppp_unregister_channel(&ap->chan); + ap->connected = 0; + err = 0; + break; + + case TCGETS: + case TCGETA: + err = n_tty_ioctl(tty, file, cmd, arg); + break; + + case TCFLSH: + /* flush our buffers and the serial port's buffer */ + if (arg == TCIFLUSH || arg == TCIOFLUSH) + flush_skb_queue(&ap->rq); + if (arg == TCIOFLUSH || arg == TCOFLUSH) + ppp_sync_flush_output(ap); + err = n_tty_ioctl(tty, file, cmd, arg); + break; + + case FIONREAD: + val = 0; + if ((skb = skb_peek(&ap->rq)) != 0) + val = skb->len; + if (put_user(val, (int *) arg)) + break; + err = 0; + break; + + default: + err = -ENOIOCTLCMD; + } + out: + return err; +} + +static unsigned int +ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait) +{ + struct syncppp *ap = tty->disc_data; + unsigned int mask; + + if (ap == 0) + return 0; /* should never happen */ + poll_wait(file, &ap->rwait, wait); + mask = POLLOUT | POLLWRNORM; + if (skb_peek(&ap->rq)) + mask |= POLLIN | POLLRDNORM; + if (test_bit(TTY_OTHER_CLOSED, &tty->flags) || tty_hung_up_p(file)) + mask |= POLLHUP; + return mask; +} + +static int +ppp_sync_room(struct tty_struct *tty) +{ + return 65535; +} + +static void +ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf, + char *flags, int count) +{ + struct syncppp *ap = tty->disc_data; + + if (ap == 0) + return; + trylock_recv_path(ap); + ppp_sync_input(ap, buf, flags, count); + unlock_recv_path(ap); + if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) + && tty->driver.unthrottle) + tty->driver.unthrottle(tty); +} + +static void +ppp_sync_wakeup(struct tty_struct *tty) +{ + struct syncppp *ap = tty->disc_data; + + clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + if (ap == 0) + return; + if (ppp_sync_push(ap) && ap->connected) + ppp_output_wakeup(&ap->chan); +} + + +static struct tty_ldisc ppp_sync_ldisc = { + magic: TTY_LDISC_MAGIC, + name: "pppsync", + open: ppp_sync_open, + close: ppp_sync_close, + read: ppp_sync_read, + write: ppp_sync_write, + ioctl: ppp_sync_ioctl, + poll: ppp_sync_poll, + receive_room: ppp_sync_room, + receive_buf: ppp_sync_receive, + write_wakeup: ppp_sync_wakeup, +}; + +int +ppp_sync_init(void) +{ + int err; + + err = tty_register_ldisc(N_SYNC_PPP, &ppp_sync_ldisc); + if (err != 0) + printk(KERN_ERR "PPP_sync: error %d registering line disc.\n", + err); + return err; +} + +/* + * Procedures for encapsulation and framing. + */ + +struct sk_buff* +ppp_sync_txdequeue(struct syncppp *ap) +{ + int proto; + unsigned char *data; + int islcp; + struct sk_buff *skb; + + while ((skb = skb_dequeue(&ap->xq)) != NULL) { + + data = skb->data; + proto = (data[0] << 8) + data[1]; + + /* LCP packets with codes between 1 (configure-request) + * and 7 (code-reject) must be sent as though no options + * have been negotiated. + */ + islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7; + + /* prepend address/control fields if necessary */ + if ((ap->flags & SC_COMP_AC) == 0 || islcp) { + if (skb_headroom(skb) < 2) { + struct sk_buff *npkt = dev_alloc_skb(skb->len + 2); + if (npkt == NULL) { + kfree_skb(skb); + continue; + } + skb_reserve(npkt,2); + memcpy(skb_put(npkt,skb->len), skb->data, skb->len); + kfree_skb(skb); + skb = npkt; + } + skb_pull(skb,2); + skb->data[0] = PPP_ALLSTATIONS; + skb->data[1] = PPP_UI; + } + + ap->last_xmit = jiffies; + break; + } + + return skb; +} + +/* + * Transmit-side routines. + */ + +/* + * Send a packet to the peer over an sync tty line. + * Returns 1 iff the packet was accepted. + * If the packet was not accepted, we will call ppp_output_wakeup + * at some later time. + */ +static int +ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb) +{ + struct syncppp *ap = chan->private; + + ppp_sync_push(ap); + + if (test_and_set_bit(XMIT_FULL, &ap->busy)) + return 0; /* already full */ + ap->tpkt = skb; + + ppp_sync_push(ap); + return 1; +} + +/* + * Push as much data as possible out to the tty. + */ +static int +ppp_sync_push(struct syncppp *ap) +{ + int sent, done = 0; + struct tty_struct *tty = ap->tty; + int tty_stuffed = 0; + + if (!trylock_xmit_path(ap)) { + set_bit(XMIT_WAKEUP, &ap->busy); + return 0; + } + for (;;) { + if (test_and_clear_bit(XMIT_WAKEUP, &ap->busy)) + tty_stuffed = 0; + if (ap->tpkt == 0) { + if ((ap->tpkt = ppp_sync_txdequeue(ap)) == 0) { + clear_bit(XMIT_FULL, &ap->busy); + done = 1; + } + } + if (!tty_stuffed && ap->tpkt != NULL) { + set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + sent = tty->driver.write(tty, 0, ap->tpkt->data, ap->tpkt->len); + if (sent < 0) + goto flush; /* error, e.g. loss of CD */ + if (sent < ap->tpkt->len) { + tty_stuffed = 1; + } else { + kfree_skb(ap->tpkt); + ap->tpkt = 0; + } + continue; + } + /* haven't made any progress */ + unlock_xmit_path(ap); + if (!(test_bit(XMIT_WAKEUP, &ap->busy) + || (!tty_stuffed && ap->tpkt != 0))) + break; + if (!trylock_xmit_path(ap)) + break; + } + return done; + +flush: + if (ap->tpkt != 0) { + kfree_skb(ap->tpkt); + ap->tpkt = 0; + clear_bit(XMIT_FULL, &ap->busy); + done = 1; + } + unlock_xmit_path(ap); + return done; +} + +/* + * Flush output from our internal buffers. + * Called for the TCFLSH ioctl. + */ +static void +ppp_sync_flush_output(struct syncppp *ap) +{ + int done = 0; + + flush_skb_queue(&ap->xq); + lock_xmit_path(ap); + if (ap->tpkt != NULL) { + kfree_skb(ap->tpkt); + ap->tpkt = 0; + clear_bit(XMIT_FULL, &ap->busy); + done = 1; + } + unlock_xmit_path(ap); + if (done && ap->connected) + ppp_output_wakeup(&ap->chan); +} + +/* + * Receive-side routines. + */ + +static inline void +process_input_packet(struct syncppp *ap) +{ + struct sk_buff *skb; + unsigned char *p; + int code = 0; + + skb = ap->rpkt; + ap->rpkt = 0; + + /* strip address/control field if present */ + p = skb->data; + if (p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) { + /* chop off address/control */ + if (skb->len < 3) + goto err; + p = skb_pull(skb, 2); + } + + /* decompress protocol field if compressed */ + if (p[0] & 1) { + /* protocol is compressed */ + skb_push(skb, 1)[0] = 0; + } else if (skb->len < 2) + goto err; + + /* pass to generic layer or queue it */ + if (ap->connected) { + ppp_input(&ap->chan, skb); + } else { + skb_queue_tail(&ap->rq, skb); + /* drop old frames if queue too long */ + while (ap->rq.qlen > PPPSYNC_MAX_RQLEN + && (skb = skb_dequeue(&ap->rq)) != 0) + kfree(skb); + wake_up_interruptible(&ap->rwait); + } + return; + + err: + kfree_skb(skb); + if (ap->connected) + ppp_input_error(&ap->chan, code); +} + +static inline void +input_error(struct syncppp *ap, int code) +{ + if (ap->connected) + ppp_input_error(&ap->chan, code); +} + +/* called when the tty driver has data for us. + * + * Data is frame oriented: each call to ppp_sync_input is considered + * a whole frame. If the 1st flag byte is non-zero then the whole + * frame is considered to be in error and is tossed. + */ +static void +ppp_sync_input(struct syncppp *ap, const unsigned char *buf, + char *flags, int count) +{ + struct sk_buff *skb; + unsigned char *sp; + + if (count == 0) + return; + + /* if flag set, then error, ignore frame */ + if (flags != 0 && *flags) { + input_error(ap, *flags); + return; + } + + /* stuff the chars in the skb */ + if ((skb = ap->rpkt) == 0) { + if ((skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2)) == 0) { + printk(KERN_ERR "PPPsync: no memory (input pkt)\n"); + input_error(ap, 0); + return; + } + /* Try to get the payload 4-byte aligned */ + if (buf[0] != PPP_ALLSTATIONS) + skb_reserve(skb, 2 + (buf[0] & 1)); + ap->rpkt = skb; + } + if (count > skb_tailroom(skb)) { + /* packet overflowed MRU */ + input_error(ap, 1); + } else { + sp = skb_put(skb, count); + memcpy(sp, buf, count); + process_input_packet(ap); + } +} + +#ifdef MODULE +int +init_module(void) +{ + return ppp_sync_init(); +} + +void +cleanup_module(void) +{ + if (tty_register_ldisc(N_SYNC_PPP, NULL) != 0) + printk(KERN_ERR "failed to unregister Sync PPP line discipline\n"); +} +#endif /* MODULE */ diff --git a/drivers/net/strip.c b/drivers/net/strip.c index 9acb7f031..b9131cb73 100644 --- a/drivers/net/strip.c +++ b/drivers/net/strip.c @@ -118,6 +118,7 @@ static const char StripVersion[] = "1.3-STUART.CHESHIRE"; #include #include #include +#include #include #include diff --git a/drivers/pci/pcisyms.c b/drivers/pci/pcisyms.c index 030e36f3d..44d272776 100644 --- a/drivers/pci/pcisyms.c +++ b/drivers/pci/pcisyms.c @@ -19,6 +19,7 @@ EXPORT_SYMBOL(pci_write_config_word); EXPORT_SYMBOL(pci_write_config_dword); EXPORT_SYMBOL(pci_devices); EXPORT_SYMBOL(pci_root); +EXPORT_SYMBOL(pci_enable_device); EXPORT_SYMBOL(pci_find_class); EXPORT_SYMBOL(pci_find_device); EXPORT_SYMBOL(pci_find_slot); diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index fa6eba768..736ac0c05 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -98,16 +98,6 @@ static irq_info_t irq_table[NR_IRQS] = { { 0, 0, 0 }, /* etc */ }; #endif -/*====================================================================== - - Linux resource management extensions - -======================================================================*/ - -static spinlock_t rsrc_lock = SPIN_LOCK_UNLOCKED; - -#define check_io_region(b,n) (0) - /*====================================================================== These manage the internal databases of available resources. @@ -190,7 +180,7 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num) b = kmalloc(256, GFP_KERNEL); memset(b, 0, 256); for (i = base, most = 0; i < base+num; i += 8) { - if (check_region(i, 8) || check_io_region(i, 8)) + if (check_region(i, 8)) continue; hole = inb(i); for (j = 1; j < 8; j++) @@ -203,7 +193,7 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num) bad = any = 0; for (i = base; i < base+num; i += 8) { - if (check_region(i, 8) || check_io_region(i, 8)) + if (check_region(i, 8)) continue; for (j = 0; j < 8; j++) if (inb(i+j) != most) break; @@ -365,8 +355,7 @@ int find_io_region(ioaddr_t *base, ioaddr_t num, char *name) if (*base != 0) { for (m = io_db.next; m != &io_db; m = m->next) { if ((*base >= m->base) && (*base+num <= m->base+m->num)) { - if (check_region(*base, num) || - check_io_region(*base, num)) { + if (check_region(*base, num)) { return -1; } else { request_region(*base, num, name); @@ -382,8 +371,7 @@ int find_io_region(ioaddr_t *base, ioaddr_t num, char *name) for (*base = (m->base + align - 1) & (~(align-1)); *base+align <= m->base + m->num; *base += align) - if ((check_region(*base, num) == 0) && - (check_io_region(*base, num) == 0)) { + if (check_region(*base, num) == 0) { request_region(*base, num, name); return 0; } diff --git a/drivers/scsi/script_asm.pl b/drivers/scsi/script_asm.pl index d99fcc950..a25a7271a 100644 --- a/drivers/scsi/script_asm.pl +++ b/drivers/scsi/script_asm.pl @@ -896,7 +896,7 @@ foreach $label (@label) { open (OUTPUT, ">$output") || die "$0 : can't open $output for writing\n"; open (OUTPUTU, ">$outputu") || die "$0 : can't open $outputu for writing\n"; -print OUTPUT "u32 ".$prefix."SCRIPT[] = {\n"; +print OUTPUT "static u32 ".$prefix."SCRIPT[] = {\n"; $instructions = 0; for ($i = 0; $i < $#code; ) { if ($list_in_array) { @@ -935,7 +935,7 @@ foreach $i (@absolute) { } printf OUTPUTU "#undef A_$i\n"; - printf OUTPUT "u32 A_".$i."_used\[\] = {\n"; + printf OUTPUT "static u32 A_".$i."_used\[\] __attribute((unused)) = {\n"; printf STDERR "$i is used $symbol_references{$i}\n" if ($debug); foreach $j (split (/\s+/,$symbol_references{$i})) { $j =~ /(ABS|REL),(.*),(.*)/; @@ -957,15 +957,15 @@ foreach $i (sort @entry) { # NCR assembler outputs label patches in the form of indices into # the code. # -printf OUTPUT "u32 ".$prefix."LABELPATCHES[] = {\n"; +printf OUTPUT "static u32 ".$prefix."LABELPATCHES[] __attribute((unused)) = {\n"; for $patch (sort {$a <=> $b} @label_patches) { printf OUTPUT "\t0x%08x,\n", $patch; } printf OUTPUT "};\n\n"; $num_external_patches = 0; -printf OUTPUT "struct {\n\tu32\toffset;\n\tvoid\t\t*address;\n". - "} ".$prefix."EXTERNAL_PATCHES[] = {\n"; +printf OUTPUT "static struct {\n\tu32\toffset;\n\tvoid\t\t*address;\n". + "} ".$prefix."EXTERNAL_PATCHES[] __attribute((unused)) = {\n"; while ($ident = pop(@external_patches)) { $off = pop(@external_patches); printf OUTPUT "\t{0x%08x, &%s},\n", $off, $ident; @@ -973,11 +973,11 @@ while ($ident = pop(@external_patches)) { } printf OUTPUT "};\n\n"; -printf OUTPUT "u32 ".$prefix."INSTRUCTIONS\t= %d;\n", +printf OUTPUT "static u32 ".$prefix."INSTRUCTIONS __attribute((unused))\t= %d;\n", $instructions; -printf OUTPUT "u32 ".$prefix."PATCHES\t= %d;\n", +printf OUTPUT "static u32 ".$prefix."PATCHES __attribute((unused))\t= %d;\n", $#label_patches+1; -printf OUTPUT "u32 ".$prefix."EXTERNAL_PATCHES_LEN\t= %d;\n", +printf OUTPUT "static u32 ".$prefix."EXTERNAL_PATCHES_LEN __attribute((unused))\t= %d;\n", $num_external_patches; close OUTPUT; close OUTPUTU; diff --git a/drivers/sound/ac97.c b/drivers/sound/ac97.c index bc313134f..b54e62f76 100644 --- a/drivers/sound/ac97.c +++ b/drivers/sound/ac97.c @@ -5,6 +5,10 @@ /* And for stereo. */ #define ST 1 +/* Whether or not the bits in the channel are inverted. */ +#define INV 1 +#define NINV 0 + static struct ac97_chn_desc { int ac97_regnum; int oss_channel; @@ -13,21 +17,22 @@ static struct ac97_chn_desc { int oss_mask; int recordNum; u16 regmask; + int is_inverted; } mixerRegs[] = { - { AC97_MASTER_VOL_STEREO, SOUND_MIXER_VOLUME, 0x3f, ST, SOUND_MASK_VOLUME, 5, 0x0000 }, - { AC97_MASTER_VOL_MONO, SOUND_MIXER_PHONEOUT, 0x3f, MO, SOUND_MASK_PHONEOUT, 6, 0x0000 }, - { AC97_MASTER_TONE, SOUND_MIXER_TREBLE, 0x0f, MO, SOUND_MASK_TREBLE, -1, 0x00ff }, - { AC97_MASTER_TONE, SOUND_MIXER_BASS, 0x0f, MO, SOUND_MASK_BASS, -1, 0xff00 }, - { AC97_PCBEEP_VOL, SOUND_MIXER_SPEAKER, 0x0f, MO, SOUND_MASK_SPEAKER, -1, 0x001e }, - { AC97_PHONE_VOL, SOUND_MIXER_PHONEIN, 0x1f, MO, SOUND_MASK_PHONEIN, 7, 0x0000 }, - { AC97_MIC_VOL, SOUND_MIXER_MIC, 0x1f, MO, SOUND_MASK_MIC, 0, 0x0000 }, - { AC97_LINEIN_VOL, SOUND_MIXER_LINE, 0x1f, ST, SOUND_MASK_LINE, 4, 0x0000 }, - { AC97_CD_VOL, SOUND_MIXER_CD, 0x1f, ST, SOUND_MASK_CD, 1, 0x0000 }, - { AC97_VIDEO_VOL, SOUND_MIXER_VIDEO, 0x1f, ST, SOUND_MASK_VIDEO, 2, 0x0000 }, - { AC97_AUX_VOL, SOUND_MIXER_LINE1, 0x1f, ST, SOUND_MASK_LINE1, 3, 0x0000 }, - { AC97_PCMOUT_VOL, SOUND_MIXER_PCM, 0x1f, ST, SOUND_MASK_PCM, -1, 0x0000 }, - { AC97_RECORD_GAIN, SOUND_MIXER_IGAIN, 0x0f, ST, SOUND_MASK_IGAIN, -1, 0x0000 }, - { -1, -1, 0xff, 0, 0, -1, 0x0000 }, + { AC97_MASTER_VOL_STEREO, SOUND_MIXER_VOLUME, 0x3f, ST, SOUND_MASK_VOLUME, 5, 0x0000, INV }, + { AC97_MASTER_VOL_MONO, SOUND_MIXER_PHONEOUT, 0x3f, MO, SOUND_MASK_PHONEOUT, 6, 0x0000, INV }, + { AC97_MASTER_TONE, SOUND_MIXER_TREBLE, 0x0f, MO, SOUND_MASK_TREBLE, -1, 0x00ff, INV }, + { AC97_MASTER_TONE, SOUND_MIXER_BASS, 0x0f, MO, SOUND_MASK_BASS, -1, 0xff00, INV }, + { AC97_PCBEEP_VOL, SOUND_MIXER_SPEAKER, 0x0f, MO, SOUND_MASK_SPEAKER, -1, 0x001e, INV }, + { AC97_PHONE_VOL, SOUND_MIXER_PHONEIN, 0x1f, MO, SOUND_MASK_PHONEIN, 7, 0x0000, INV }, + { AC97_MIC_VOL, SOUND_MIXER_MIC, 0x1f, MO, SOUND_MASK_MIC, 0, 0x0000, INV }, + { AC97_LINEIN_VOL, SOUND_MIXER_LINE, 0x1f, ST, SOUND_MASK_LINE, 4, 0x0000, INV }, + { AC97_CD_VOL, SOUND_MIXER_CD, 0x1f, ST, SOUND_MASK_CD, 1, 0x0000, INV }, + { AC97_VIDEO_VOL, SOUND_MIXER_VIDEO, 0x1f, ST, SOUND_MASK_VIDEO, 2, 0x0000, INV }, + { AC97_AUX_VOL, SOUND_MIXER_LINE1, 0x1f, ST, SOUND_MASK_LINE1, 3, 0x0000, INV }, + { AC97_PCMOUT_VOL, SOUND_MIXER_PCM, 0x1f, ST, SOUND_MASK_PCM, -1, 0x0000, INV }, + { AC97_RECORD_GAIN, SOUND_MIXER_IGAIN, 0x0f, ST, SOUND_MASK_IGAIN, -1, 0x0000, NINV }, + { -1, -1, 0xff, 0, 0, -1, 0x0000, 0 }, }; static struct ac97_chn_desc * @@ -104,6 +109,25 @@ ac97_init (struct ac97_hwint *dev) return 0; } +/* Reset the mixer to the currently saved settings. */ +int +ac97_reset (struct ac97_hwint *dev) +{ + int x; + + if (dev->reset_device (dev)) + return -1; + + /* Now set the registers back to their last-written values. */ + for (x = 0; mixerRegs[x].ac97_regnum != -1; x++) { + int regnum = mixerRegs[x].ac97_regnum; + int value = dev->last_written_mixer_values [regnum / 2]; + if (value >= 0) + ac97_put_register (dev, regnum, value); + } + return 0; +} + /* Return the contents of register REG; use the cache if the value in it is valid. Returns a negative error code on failure. */ int @@ -156,38 +180,45 @@ ac97_put_register (struct ac97_hwint *dev, u8 reg, u16 value) scaled value on success. */ static int -ac97_scale_to_oss_val (int value, int maxval, int is_stereo) +ac97_scale_to_oss_val (int value, int maxval, int is_stereo, int inv) { /* Muted? */ if (value & AC97_MUTE) return 0; if (is_stereo) - return (ac97_scale_to_oss_val (value & 255, maxval, 0) << 8) - | (ac97_scale_to_oss_val ((value >> 8) & 255, maxval, 0) << 0); + return (ac97_scale_to_oss_val (value & 255, maxval, 0, inv) << 8) + | (ac97_scale_to_oss_val ((value >> 8) & 255, maxval, 0, inv) << 0); else { int i; /* Inverted. */ - value = maxval - value; + if (inv) + value = maxval - value; i = (value * 100 + (maxval / 2)) / maxval; if (i > 100) i = 100; + if (i < 0) + i = 0; return i; } } static int -ac97_scale_from_oss_val (int value, int maxval, int is_stereo) +ac97_scale_from_oss_val (int value, int maxval, int is_stereo, int inv) { if (is_stereo) - return (ac97_scale_from_oss_val (value & 255, maxval, 0) << 8) - | (ac97_scale_from_oss_val ((value >> 8) & 255, maxval, 0) << 0); + return (ac97_scale_from_oss_val (value & 255, maxval, 0, inv) << 8) + | (ac97_scale_from_oss_val ((value >> 8) & 255, maxval, 0, inv) << 0); else { - int i = maxval - ((value & 255) * maxval + 50) / 100; + int i = ((value & 255) * maxval + 50) / 100; + if (inv) + i = maxval - i; if (i < 0) i = 0; + if (i > maxval) + i = maxval; return i; } } @@ -204,7 +235,8 @@ ac97_set_mixer (struct ac97_hwint *dev, int oss_channel, u16 oss_value) if (! ac97_is_valid_channel (dev, channel)) return -ENODEV; scaled_value = ac97_scale_from_oss_val (oss_value, channel->maxval, - channel->is_stereo); + channel->is_stereo, + channel->is_inverted); if (scaled_value < 0) return scaled_value; @@ -253,7 +285,8 @@ ac97_get_mixer_scaled (struct ac97_hwint *dev, int oss_channel) regval >>= 1; } return ac97_scale_to_oss_val (regval, channel->maxval, - channel->is_stereo); + channel->is_stereo, + channel->is_inverted); } int @@ -383,8 +416,9 @@ ac97_mixer_ioctl (struct ac97_hwint *dev, unsigned int cmd, caddr_t arg) else ret = -EFAULT; } - if (ret >= 0) { - if (dev->last_written_OSS_values[channel] == AC97_REGVAL_UNKNOWN) + if (ret >= 0 && (dir & _IOC_READ)) { + if (dev->last_written_OSS_values[channel] + == AC97_REGVAL_UNKNOWN) dev->last_written_OSS_values[channel] = ac97_get_mixer_scaled (dev, channel); ret = dev->last_written_OSS_values[channel]; diff --git a/drivers/sound/ac97.h b/drivers/sound/ac97.h index 490d69f88..294000f6d 100644 --- a/drivers/sound/ac97.h +++ b/drivers/sound/ac97.h @@ -10,7 +10,7 @@ #include "sound_config.h" #include "sound_calls.h" -#define AC97_RESET 0x0000 // */ +#define AC97_RESET 0x0000 // #define AC97_MASTER_VOL_STEREO 0x0002 // Line Out #define AC97_HEADPHONE_VOL 0x0004 // #define AC97_MASTER_VOL_MONO 0x0006 // TAD Output @@ -207,6 +207,10 @@ extern int ac97_get_mixer_scaled (struct ac97_hwint *dev, int oss_channel); /* Default ioctl. */ extern int ac97_mixer_ioctl (struct ac97_hwint *dev, unsigned int cmd, caddr_t arg); + +/* Do a complete reset on the AC97 mixer, restoring all mixer registers to + the current values. Normally used after an APM resume event. */ +extern int ac97_reset (struct ac97_hwint *dev); #endif /* diff --git a/drivers/sound/nm256.h b/drivers/sound/nm256.h index 4cc720ab9..c640b88ce 100644 --- a/drivers/sound/nm256.h +++ b/drivers/sound/nm256.h @@ -3,10 +3,12 @@ #include "ac97.h" +/* The revisions that we currently handle. */ enum nm256rev { REV_NM256AV, REV_NM256ZX }; +/* Per-card structure. */ struct nm256_info { /* Magic number used to verify that this struct is valid. */ @@ -34,10 +36,12 @@ struct nm256_info /* The mixer device. */ int mixer_oss_dev; - /* Can only be opened once for each operation. These aren't set - until an actual I/O operation is performed; this allows one - device to be open for read/write without inhibiting I/O to - the other device. */ + /* + * Can only be opened once for each operation. These aren't set + * until an actual I/O operation is performed; this allows one + * device to be open for read/write without inhibiting I/O to + * the other device. + */ int is_open_play; int is_open_record; @@ -46,25 +50,40 @@ struct nm256_info /* Ditto for recording a sample. */ int recording; - /* The two memory ports. */ - char *ports[2]; - - /* Starting offset of the port1 area mapped into memory. */ - u32 port1_start; - /* Ending offset. */ - u32 port1_end; - /* The offset of the end of the actual buffer area. */ - u32 bufend; + /* The two memory ports. */ + struct nm256_ports { + /* Physical address of the port. */ + u32 physaddr; + /* Our mapped-in pointer. */ + char *ptr; + /* PTR's offset within the physical port. */ + u32 start_offset; + /* And the offset of the end of the buffer. */ + u32 end_offset; + } port[2]; /* The following are offsets within memory port 1. */ u32 coeffBuf; u32 allCoeffBuf; + /* Record and playback buffers. */ u32 abuf1, abuf2; /* Offset of the AC97 mixer in memory port 2. */ u32 mixer; + /* Offset of the mixer status register in memory port 2. */ + u32 mixer_status_offset; + + /* Non-zero if we have written initial values to the mixer. */ + u8 mixer_values_init; + + /* + * Status mask bit; (*mixer_status_loc & mixer_status_mask) == 0 means + * it's ready. + */ + u16 mixer_status_mask; + /* The sizes of the playback and record ring buffers. */ u32 playbackBufferSize; u32 recordBufferSize; @@ -77,7 +96,7 @@ struct nm256_info /* The start of the block currently playing. */ u32 curPlayPos; - /* The amount of data we requested to record. */ + /* The amount of data we were requested to record. */ u32 requestedRecAmt; /* The offset of the currently-recording block. */ u32 curRecPos; @@ -107,10 +126,17 @@ struct nm256_info /* Debug flag--bigger numbers mean more output. */ extern int nm256_debug; -/* Size of the second memory port. */ +/* The BIOS signature. */ +#define NM_SIGNATURE 0x4e4d0000 +/* Signature mask. */ +#define NM_SIG_MASK 0xffff0000 + +/* Size of the second memory area. */ #define NM_PORT2_SIZE 4096 -/* The location of the mixer. */ -#define NM_MIXER_BASE 0x600 + +/* The base offset of the mixer in the second memory area. */ +#define NM_MIXER_OFFSET 0x600 + /* The maximum size of a coefficient entry. */ #define NM_MAX_COEFFICIENT 0x5000 @@ -123,21 +149,33 @@ extern int nm256_debug; #define NM_MISC_INT_2 0x1 #define NM_ACK_INT(CARD, X) nm256_writePort16((CARD), 2, NM_INT_REG, (X) << 1) -/* For the second revision. It uses the same interrupt register, but it - holds 32 bits instead of 16. */ +/* The AV's "mixer ready" status bit and location. */ +#define NM_MIXER_STATUS_OFFSET 0xa04 +#define NM_MIXER_READY_MASK 0x0800 +#define NM_MIXER_PRESENCE 0xa06 +#define NM_PRESENCE_MASK 0x0050 +#define NM_PRESENCE_VALUE 0x0040 + +/* + * For the ZX. It uses the same interrupt register, but it holds 32 + * bits instead of 16. + */ #define NM2_PLAYBACK_INT 0x10000 #define NM2_RECORD_INT 0x80000 #define NM2_MISC_INT_1 0x8 #define NM2_MISC_INT_2 0x2 #define NM2_ACK_INT(CARD, X) nm256_writePort32((CARD), 2, NM_INT_REG, (X)) +/* The ZX's "mixer ready" status bit and location. */ +#define NM2_MIXER_STATUS_OFFSET 0xa06 +#define NM2_MIXER_READY_MASK 0x0800 + /* The playback registers start from here. */ #define NM_PLAYBACK_REG_OFFSET 0x0 /* The record registers start from here. */ #define NM_RECORD_REG_OFFSET 0x200 -/* The rate register is located 2 bytes from the start of the register - area. */ +/* The rate register is located 2 bytes from the start of the register area. */ #define NM_RATE_REG_OFFSET 2 /* Mono/stereo flag, number of bits on playback, and rate mask. */ @@ -156,7 +194,7 @@ extern int nm256_debug; #define NM_AUDIO_MUTE_LEFT 0x8000 #define NM_AUDIO_MUTE_RIGHT 0x0080 -/* Recording enable register */ +/* Recording enable register. */ #define NM_RECORD_ENABLE_REG (NM_RECORD_REG_OFFSET + 0) #define NM_RECORD_ENABLE_FLAG 1 #define NM_RECORD_FREERUN 2 @@ -179,26 +217,25 @@ extern int nm256_debug; if (port < 1 || port > 2 || card == NULL) \ return -1; \ \ - if (port == 1) { \ - if (offset < card->port1_start || offset >= card->port1_end) { \ - printk (KERN_ERR "Bad port request port 1:0x%x\n", offset); \ - return -1; \ - } \ - offset -= card->port1_start; \ - } else if (offset < 0 || offset > 4096) { \ - printk (KERN_ERR "Bad port request port 2: 0x%x\n", offset); \ - return -1; \ - } + if (offset < card->port[port - 1].start_offset \ + || offset >= card->port[port - 1].end_offset) { \ + printk (KERN_ERR "Bad access: port %d, offset 0x%x\n", port, offset); \ + return -1; \ + } \ + offset -= card->port[port - 1].start_offset; #define DEFwritePortX(X, func) \ static inline int nm256_writePort##X (struct nm256_info *card,\ - int port, int offset, int value)\ + int port, int offset, int value)\ {\ u##X *addr;\ +\ + if (nm256_debug > 1)\ + printk (KERN_DEBUG "Writing 0x%x to %d:0x%x\n", value, port, offset);\ \ NM_FIX_PORT;\ \ - addr = (u##X *)(card->ports[port - 1] + offset);\ + addr = (u##X *)(card->port[port - 1].ptr + offset);\ func (value, addr);\ return 0;\ } @@ -207,29 +244,28 @@ DEFwritePortX (8, writeb) DEFwritePortX (16, writew) DEFwritePortX (32, writel) -#define DEFreadPortX(X) \ +#define DEFreadPortX(X, func) \ static inline u##X nm256_readPort##X (struct nm256_info *card,\ int port, int offset)\ {\ - u##X *addr, res;\ + u##X *addr;\ \ NM_FIX_PORT\ \ - addr = (u##X *)(card->ports[port - 1] + offset);\ - memcpy_fromio (&res, addr, sizeof (res));\ - return res;\ + addr = (u##X *)(card->port[port - 1].ptr + offset);\ + return func(addr);\ } -DEFreadPortX (8) -DEFreadPortX (16) -DEFreadPortX (32) +DEFreadPortX (8, readb) +DEFreadPortX (16, readw) +DEFreadPortX (32, readl) static inline int nm256_writeBuffer8 (struct nm256_info *card, u8 *src, int port, int offset, int amt) { NM_FIX_PORT; - memcpy_toio (card->ports[port - 1] + offset, src, amt); + memcpy_toio (card->port[port - 1].ptr + offset, src, amt); return 0; } @@ -238,7 +274,7 @@ nm256_readBuffer8 (struct nm256_info *card, u8 *dst, int port, int offset, int amt) { NM_FIX_PORT; - memcpy_fromio (dst, card->ports[port - 1] + offset, amt); + memcpy_fromio (dst, card->port[port - 1].ptr + offset, amt); return 0; } diff --git a/drivers/sound/nm256_audio.c b/drivers/sound/nm256_audio.c index 0c3ee7b37..a066c65b9 100644 --- a/drivers/sound/nm256_audio.c +++ b/drivers/sound/nm256_audio.c @@ -1,27 +1,37 @@ -/* Audio driver for the NeoMagic 256AV and 256ZX chipsets in native - mode, with AC97 mixer support. - - Overall design and parts of this code stolen from vidc_*.c and - skeleton.c. - - Yeah, there are a lot of magic constants in here. You tell ME what - they are. I just get this stuff psychically, remember? - - This driver was written by someone who wishes to remain anonymous. - It is in the public domain, so share and enjoy. Try to make a profit - off of it; go on, I dare you. */ +/* + * Audio driver for the NeoMagic 256AV and 256ZX chipsets in native + * mode, with AC97 mixer support. + * + * Overall design and parts of this code stolen from vidc_*.c and + * skeleton.c. + * + * Yeah, there are a lot of magic constants in here. You tell ME what + * they are. I just get this stuff psychically, remember? + * + * This driver was written by someone who wishes to remain anonymous. + * It is in the public domain, so share and enjoy. Try to make a profit + * off of it; go on, I dare you. + */ #include #include #include +#ifdef CONFIG_APM +#include +#endif #include "sound_config.h" #include "soundmodule.h" #include "nm256.h" #include "nm256_coeff.h" int nm256_debug = 0; +static int force_load = 0; -/* The size of the playback reserve. */ +/* + * The size of the playback reserve. When the playback buffer has less + * than NM256_PLAY_WMARK_SIZE bytes to output, we request a new + * buffer. + */ #define NM256_PLAY_WMARK_SIZE 512 static struct audio_driver nm256_audio_driver; @@ -29,16 +39,74 @@ static struct audio_driver nm256_audio_driver; static int nm256_grabInterrupt (struct nm256_info *card); static int nm256_releaseInterrupt (struct nm256_info *card); static void nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy); -static void nm256_interrupt_zx (int irq, void *dev_id, - struct pt_regs *dummy); +static void nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy); /* These belong in linux/pci.h. */ #define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005 #define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006 +/* eeeew. */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) +#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start) +#else +#define RSRCADDRESS(dev,num) ((dev)->base_address[(num)] \ + & PCI_BASE_ADDRESS_MEM_MASK) + +#endif + /* List of cards. */ static struct nm256_info *nmcard_list; +/* Release the mapped-in memory for CARD. */ +static void +nm256_release_ports (struct nm256_info *card) +{ + int x; + + for (x = 0; x < 2; x++) { + if (card->port[x].ptr != NULL) { + u32 size = + card->port[x].end_offset - card->port[x].start_offset; + release_region ((unsigned long) card->port[x].ptr, size); + card->port[x].ptr = NULL; + } + } +} + +/* + * Map in the memory ports for CARD, if they aren't already mapped in + * and have been configured. If successful, a zero value is returned; + * otherwise any previously mapped-in areas are released and a non-zero + * value is returned. + * + * This is invoked twice, once for each port. Ideally it would only be + * called once, but we now need to map in the second port in order to + * check how much memory the card has on the 256ZX. + */ +static int +nm256_remap_ports (struct nm256_info *card) +{ + int x; + + for (x = 0; x < 2; x++) { + if (card->port[x].ptr == NULL && card->port[x].end_offset > 0) { + u32 physaddr + = card->port[x].physaddr + card->port[x].start_offset; + u32 size + = card->port[x].end_offset - card->port[x].start_offset; + + card->port[x].ptr = ioremap_nocache (physaddr, size); + + if (card->port[x].ptr == NULL) { + printk (KERN_ERR "NM256: Unable to remap port %d\n", x + 1); + nm256_release_ports (card); + return -1; + } + } + } + return 0; +} + /* Locate the card in our list. */ static struct nm256_info * nm256_find_card (int dev) @@ -52,8 +120,10 @@ nm256_find_card (int dev) return NULL; } -/* Ditto, but find the card struct corresponding to the mixer device DEV - instead. */ +/* + * Ditto, but find the card struct corresponding to the mixer device DEV + * instead. + */ static struct nm256_info * nm256_find_card_for_mixer (int dev) { @@ -81,11 +151,13 @@ static int samplerates[9] = { 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999 }; -/* Set the card samplerate, word size and stereo mode to correspond to - the settings in the CARD struct for the specified device in DEV. - We keep two separate sets of information, one for each device; the - hardware is not actually configured until a read or write is - attempted. */ +/* + * Set the card samplerate, word size and stereo mode to correspond to + * the settings in the CARD struct for the specified device in DEV. + * We keep two separate sets of information, one for each device; the + * hardware is not actually configured until a read or write is + * attempted. + */ int nm256_setInfo (int dev, struct nm256_info *card) @@ -113,24 +185,33 @@ nm256_setInfo (int dev, struct nm256_info *card) break; if (x < 8) { - u8 speedbits = ((x << 4) & NM_RATE_MASK) - | (card->sinfo[w].bits == 16 ? NM_RATE_BITS_16: 0) - | (card->sinfo[w].stereo ? NM_RATE_STEREO : 0); + u8 ratebits = ((x << 4) & NM_RATE_MASK); + if (card->sinfo[w].bits == 16) + ratebits |= NM_RATE_BITS_16; + if (card->sinfo[w].stereo) + ratebits |= NM_RATE_STEREO; card->sinfo[w].samplerate = samplerates[x]; + if (card->dev_for_play == dev && card->playing) { + if (nm256_debug) + printk (KERN_DEBUG "Setting play ratebits to 0x%x\n", + ratebits); nm256_loadCoefficient (card, 0, x); nm256_writePort8 (card, 2, - NM_PLAYBACK_REG_OFFSET + NM_RATE_REG_OFFSET, - speedbits); + NM_PLAYBACK_REG_OFFSET + NM_RATE_REG_OFFSET, + ratebits); } if (card->dev_for_record == dev && card->recording) { + if (nm256_debug) + printk (KERN_DEBUG "Setting record ratebits to 0x%x\n", + ratebits); nm256_loadCoefficient (card, 1, x); - nm256_writePort8 (card, 2, - NM_RECORD_REG_OFFSET + NM_RATE_REG_OFFSET, - speedbits); + nm256_writePort8 (card, 2, + NM_RECORD_REG_OFFSET + NM_RATE_REG_OFFSET, + ratebits); } return 0; } @@ -149,7 +230,7 @@ startPlay (struct nm256_info *card) /* Enable playback engine and interrupts. */ nm256_writePort8 (card, 2, NM_PLAYBACK_ENABLE_REG, - NM_PLAYBACK_ENABLE_FLAG | NM_PLAYBACK_FREERUN); + NM_PLAYBACK_ENABLE_FLAG | NM_PLAYBACK_FREERUN); /* Enable both channels. */ nm256_writePort16 (card, 2, NM_AUDIO_MUTE_REG, 0x0); @@ -157,9 +238,11 @@ startPlay (struct nm256_info *card) } } -/* Request one chunk of AMT bytes from the recording device. When the - operation is complete, the data will be copied into BUFFER and the - function DMAbuf_inputintr will be invoked. */ +/* + * Request one chunk of AMT bytes from the recording device. When the + * operation is complete, the data will be copied into BUFFER and the + * function DMAbuf_inputintr will be invoked. + */ static void nm256_startRecording (struct nm256_info *card, char *buffer, u32 amt) @@ -167,11 +250,14 @@ nm256_startRecording (struct nm256_info *card, char *buffer, u32 amt) u32 endpos; int enableEngine = 0; u32 ringsize = card->recordBufferSize; + unsigned long flags; if (amt > (ringsize / 2)) { - /* Of course this won't actually work right, because the - caller is going to assume we will give what we got asked - for. */ + /* + * Of course this won't actually work right, because the + * caller is going to assume we will give what we got asked + * for. + */ printk (KERN_ERR "NM256: Read request too large: %d\n", amt); amt = ringsize / 2; } @@ -181,8 +267,12 @@ nm256_startRecording (struct nm256_info *card, char *buffer, u32 amt) return; } - /* If we're not currently recording, set up the start and end registers - for the recording engine. */ + save_flags (flags); + cli (); + /* + * If we're not currently recording, set up the start and end registers + * for the recording engine. + */ if (! card->recording) { card->recording = 1; if (nm256_grabInterrupt (card) == 0) { @@ -198,10 +288,16 @@ nm256_startRecording (struct nm256_info *card, char *buffer, u32 amt) } else { /* Not sure what else to do here. */ + restore_flags (flags); return; } } + /* + * If we happen to go past the end of the buffer a bit (due to a + * delayed interrupt) it's OK. So might as well set the watermark + * right at the end of the data we want. + */ endpos = card->abuf2 + ((card->curRecPos + amt) % ringsize); card->recBuf = buffer; @@ -211,6 +307,8 @@ nm256_startRecording (struct nm256_info *card, char *buffer, u32 amt) if (enableEngine) nm256_writePort8 (card, 2, NM_RECORD_ENABLE_REG, NM_RECORD_ENABLE_FLAG | NM_RECORD_FREERUN); + + restore_flags (flags); } /* Stop the play engine. */ @@ -219,7 +317,7 @@ stopPlay (struct nm256_info *card) { /* Shut off sound from both channels. */ nm256_writePort16 (card, 2, NM_AUDIO_MUTE_REG, - NM_AUDIO_MUTE_LEFT | NM_AUDIO_MUTE_RIGHT); + NM_AUDIO_MUTE_LEFT | NM_AUDIO_MUTE_RIGHT); /* Disable play engine. */ nm256_writePort8 (card, 2, NM_PLAYBACK_ENABLE_REG, 0); if (card->playing) { @@ -246,18 +344,22 @@ stopRecord (struct nm256_info *card) } } -/* Ring buffers, man. That's where the hip-hop, wild-n-wooly action's at. - 1972? - - Write AMT bytes of BUFFER to the playback ring buffer, and start the - playback engine running. It will only accept up to 1/2 of the total - size of the ring buffer. */ +/* + * Ring buffers, man. That's where the hip-hop, wild-n-wooly action's at. + * 1972? (Well, I suppose it was cheep-n-easy to implement.) + * + * Write AMT bytes of BUFFER to the playback ring buffer, and start the + * playback engine running. It will only accept up to 1/2 of the total + * size of the ring buffer. No check is made that we're about to overwrite + * the currently-playing sample. + */ static void nm256_write_block (struct nm256_info *card, char *buffer, u32 amt) { u32 ringsize = card->playbackBufferSize; u32 endstop; + unsigned long flags; if (amt > (ringsize / 2)) { printk (KERN_ERR "NM256: Write request too large: %d\n", amt); @@ -273,6 +375,9 @@ nm256_write_block (struct nm256_info *card, char *buffer, u32 amt) card->requested_amt = amt; + save_flags (flags); + cli (); + if ((card->curPlayPos + amt) >= ringsize) { u32 rem = ringsize - card->curPlayPos; @@ -288,33 +393,40 @@ nm256_write_block (struct nm256_info *card, char *buffer, u32 amt) card->abuf1 + card->curPlayPos, amt); - /* Setup the start-n-stop-n-limit registers, and start that engine - goin'. - - Normally we just let it wrap around to avoid the click-click - action scene. */ + /* + * Setup the start-n-stop-n-limit registers, and start that engine + * goin'. + * + * Normally we just let it wrap around to avoid the click-click + * action scene. + */ if (! card->playing) { - /* The PBUFFER_END register in this case points to one "word" + /* The PBUFFER_END register in this case points to one sample before the end of the buffer. */ int w = (card->dev_for_play == card->dev[0] ? 0 : 1); - int wordsize = (card->sinfo[w].bits == 16 ? 2 : 1) - * (card->sinfo[w].stereo ? 2 : 1); + int sampsize = (card->sinfo[w].bits == 16 ? 2 : 1); + + if (card->sinfo[w].stereo) + sampsize *= 2; /* Need to set the not-normally-changing-registers up. */ nm256_writePort32 (card, 2, NM_PBUFFER_START, card->abuf1 + card->curPlayPos); nm256_writePort32 (card, 2, NM_PBUFFER_END, - card->abuf1 + ringsize - wordsize); + card->abuf1 + ringsize - sampsize); nm256_writePort32 (card, 2, NM_PBUFFER_CURRP, card->abuf1 + card->curPlayPos); } endstop = (card->curPlayPos + amt - NM256_PLAY_WMARK_SIZE) % ringsize; nm256_writePort32 (card, 2, NM_PBUFFER_WMARK, card->abuf1 + endstop); + if (! card->playing) startPlay (card); + + restore_flags (flags); } -/* We just got a card playback interrupt; process it. */ +/* We just got a card playback interrupt; process it. */ static void nm256_get_new_block (struct nm256_info *card) { @@ -332,13 +444,14 @@ nm256_get_new_block (struct nm256_info *card) amt -= card->curPlayPos; if (card->requested_amt > (amt + NM256_PLAY_WMARK_SIZE)) { - u32 endstop = + u32 endstop = card->curPlayPos + card->requested_amt - NM256_PLAY_WMARK_SIZE; nm256_writePort32 (card, 2, NM_PBUFFER_WMARK, card->abuf1 + endstop); - } else { + } + else { card->curPlayPos += card->requested_amt; /* Get a new block to write. This will eventually invoke - nm256_write_block (). */ + nm256_write_block () or stopPlay (). */ DMAbuf_outputintr (card->dev_for_play, 1); } } @@ -346,9 +459,11 @@ nm256_get_new_block (struct nm256_info *card) /* Ultra cheez-whiz. But I'm too lazy to grep headers. */ #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) -/* Read the last-recorded block from the ring buffer, copy it into the - saved buffer pointer, and invoke DMAuf_inputintr() with the recording - device. */ +/* + * Read the last-recorded block from the ring buffer, copy it into the + * saved buffer pointer, and invoke DMAuf_inputintr() with the recording + * device. + */ static void nm256_read_block (struct nm256_info *card) @@ -363,8 +478,10 @@ nm256_read_block (struct nm256_info *card) currptr = 0; } - /* This test is probably redundant; we shouldn't be here unless - it's true. */ + /* + * This test is probably redundant; we shouldn't be here unless + * it's true. + */ if (card->recording) { /* If we wrapped around, copy everything from the start of our recording buffer to the end of the buffer. */ @@ -394,52 +511,28 @@ nm256_read_block (struct nm256_info *card) } #undef MIN -/* Initialize the hardware and various other card data we'll need - later. */ +/* + * Initialize the hardware. + */ static void nm256_initHw (struct nm256_info *card) { - int x; - - card->playbackBufferSize = 16384; - card->recordBufferSize = 16384; - - card->coeffBuf = card->bufend - NM_MAX_COEFFICIENT; - card->abuf2 = card->coeffBuf - card->recordBufferSize; - card->abuf1 = card->abuf2 - card->playbackBufferSize; - card->allCoeffBuf = card->abuf2 - (NM_TOTAL_COEFF_COUNT * 4); - - /* Fixed setting. */ - card->mixer = NM_MIXER_BASE; - - card->playing = 0; - card->is_open_play = 0; - card->curPlayPos = 0; - - card->recording = 0; - card->is_open_record = 0; - card->curRecPos = 0; - - card->coeffsCurrent = 0; - - card->opencnt[0] = 0; card->opencnt[1] = 0; - /* Reset everything. */ - nm256_writePort8 (card, 2, 0, 0x11); - - /* Disable recording. */ - nm256_writePort8 (card, 2, NM_RECORD_ENABLE_REG, 0); + nm256_writePort8 (card, 2, 0x0, 0x11); nm256_writePort16 (card, 2, 0x214, 0); - /* Reasonable default settings, but largely unnecessary. */ - for (x = 0; x < 2; x++) { - card->sinfo[x].bits = 8; - card->sinfo[x].stereo = 0; - card->sinfo[x].samplerate = 8000; - } + stopRecord (card); + stopPlay (card); } -/* Handle a potential interrupt for the device referred to by DEV_ID. */ +/* + * Handle a potential interrupt for the device referred to by DEV_ID. + * + * I don't like the cut-n-paste job here either between the two routines, + * but there are sufficient differences between the two interrupt handlers + * that parameterizing it isn't all that great either. (Could use a macro, + * I suppose...yucky bleah.) + */ static void nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy) @@ -458,14 +551,32 @@ nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy) /* Not ours. */ if (status == 0) { if (badintrcount++ > 1000) { - printk (KERN_ERR "NM256: Releasing interrupt, over 1000 invalid interrupts\n"); - nm256_releaseInterrupt (card); + /* + * I'm not sure if the best thing is to stop the card from + * playing or just release the interrupt (after all, we're in + * a bad situation, so doing fancy stuff may not be such a good + * idea). + * + * I worry about the card engine continuing to play noise + * over and over, however--that could become a very + * obnoxious problem. And we know that when this usually + * happens things are fairly safe, it just means the user's + * inserted a PCMCIA card and someone's spamming us with IRQ 9s. + */ + + if (card->playing) + stopPlay (card); + if (card->recording) + stopRecord (card); + badintrcount = 0; } return; } badintrcount = 0; + /* Rather boring; check for individual interrupts and process them. */ + if (status & NM_PLAYBACK_INT) { status &= ~NM_PLAYBACK_INT; NM_ACK_INT (card, NM_PLAYBACK_INT); @@ -503,6 +614,7 @@ nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy) nm256_writePort8 (card, 2, 0x400, cbyte & ~2); } + /* Unknown interrupt. */ if (status) { printk (KERN_ERR "NM256: Fire in the hole! Unknown status 0x%x\n", status); @@ -511,8 +623,11 @@ nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy) } } -/* Handle a potential interrupt for the device referred to by DEV_ID. - This handler is for the 256ZX. */ +/* + * Handle a potential interrupt for the device referred to by DEV_ID. + * This handler is for the 256ZX, and is very similar to the non-ZX + * routine. + */ static void nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy) @@ -532,13 +647,33 @@ nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy) if (status == 0) { if (badintrcount++ > 1000) { printk (KERN_ERR "NM256: Releasing interrupt, over 1000 invalid interrupts\n"); - nm256_releaseInterrupt (card); + /* + * I'm not sure if the best thing is to stop the card from + * playing or just release the interrupt (after all, we're in + * a bad situation, so doing fancy stuff may not be such a good + * idea). + * + * I worry about the card engine continuing to play noise + * over and over, however--that could become a very + * obnoxious problem. And we know that when this usually + * happens things are fairly safe, it just means the user's + * inserted a PCMCIA card and someone's spamming us with + * IRQ 9s. + */ + + if (card->playing) + stopPlay (card); + if (card->recording) + stopRecord (card); + badintrcount = 0; } return; } badintrcount = 0; + /* Rather boring; check for individual interrupts and process them. */ + if (status & NM2_PLAYBACK_INT) { status &= ~NM2_PLAYBACK_INT; NM2_ACK_INT (card, NM2_PLAYBACK_INT); @@ -575,6 +710,7 @@ nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy) nm256_writePort8 (card, 2, 0x400, cbyte & ~2); } + /* Unknown interrupt. */ if (status) { printk (KERN_ERR "NM256: Fire in the hole! Unknown status 0x%x\n", status); @@ -583,7 +719,9 @@ nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy) } } -/* Request our interrupt. */ +/* + * Request our interrupt. + */ static int nm256_grabInterrupt (struct nm256_info *card) { @@ -597,7 +735,9 @@ nm256_grabInterrupt (struct nm256_info *card) return 0; } -/* Release our interrupt. */ +/* + * Release our interrupt. + */ static int nm256_releaseInterrupt (struct nm256_info *card) { @@ -612,6 +752,11 @@ nm256_releaseInterrupt (struct nm256_info *card) return 0; } +/* + * Waits for the mixer to become ready to be written; returns a zero value + * if it timed out. + */ + static int nm256_isReady (struct ac97_hwint *dev) { @@ -626,26 +771,25 @@ nm256_isReady (struct ac97_hwint *dev) return 0; } - if (card->rev == REV_NM256AV) { - testaddr = 0xa06; - testb = 0x0100; - } else if (card->rev == REV_NM256ZX) { - testaddr = 0xa08; - testb = 0x0800; - } else { - return -1; - } + testaddr = card->mixer_status_offset; + testb = card->mixer_status_mask; - while (t2-- > 0) { - if ((nm256_readPort16 (card, 2, testaddr) & testb) == 0) { + /* + * Loop around waiting for the mixer to become ready. + */ + while (! done && t2-- > 0) { + if ((nm256_readPort16 (card, 2, testaddr) & testb) == 0) done = 1; - break; - } - udelay (100); + else + udelay (100); } return done; } +/* + * Return the contents of the AC97 mixer register REG. Returns a positive + * value if successful, or a negative error code. + */ static int nm256_readAC97Reg (struct ac97_hwint *dev, u8 reg) { @@ -661,6 +805,7 @@ nm256_readAC97Reg (struct ac97_hwint *dev, u8 reg) nm256_isReady (dev); res = nm256_readPort16 (card, 2, card->mixer + reg); + /* Magic delay. Bleah yucky. */ udelay (1000); return res; } @@ -668,6 +813,10 @@ nm256_readAC97Reg (struct ac97_hwint *dev, u8 reg) return -EINVAL; } +/* + * Writes VALUE to AC97 mixer register REG. Returns 0 if successful, or + * a negative error code. + */ static int nm256_writeAC97Reg (struct ac97_hwint *dev, u8 reg, u16 value) { @@ -706,6 +855,13 @@ nm256_writeAC97Reg (struct ac97_hwint *dev, u8 reg, u16 value) return ! done; } +/* + * Initial register values to be written to the AC97 mixer. + * While most of these are identical to the reset values, we do this + * so that we have most of the register contents cached--this avoids + * reading from the mixer directly (which seems to be problematic, + * probably due to ignorance). + */ struct initialValues { unsigned short port; @@ -714,23 +870,24 @@ struct initialValues static struct initialValues nm256_ac97_initial_values[] = { - { 0x0002, 0x8000 }, - { 0x0004, 0x0000 }, - { 0x0006, 0x0000 }, - { 0x000A, 0x0000 }, - { 0x000C, 0x0008 }, - { 0x000E, 0x8008 }, - { 0x0010, 0x8808 }, - { 0x0012, 0x8808 }, - { 0x0014, 0x8808 }, - { 0x0016, 0x8808 }, - { 0x0018, 0x0808 }, - { 0x001A, 0x0000 }, - { 0x001C, 0x0B0B }, - { 0x0020, 0x0000 }, + { AC97_MASTER_VOL_STEREO, 0x8000 }, + { AC97_HEADPHONE_VOL, 0x8000 }, + { AC97_MASTER_VOL_MONO, 0x0000 }, + { AC97_PCBEEP_VOL, 0x0000 }, + { AC97_PHONE_VOL, 0x0008 }, + { AC97_MIC_VOL, 0x8000 }, + { AC97_LINEIN_VOL, 0x8808 }, + { AC97_CD_VOL, 0x8808 }, + { AC97_VIDEO_VOL, 0x8808 }, + { AC97_AUX_VOL, 0x8808 }, + { AC97_PCMOUT_VOL, 0x0808 }, + { AC97_RECORD_SELECT, 0x0000 }, + { AC97_RECORD_GAIN, 0x0B0B }, + { AC97_GENERAL_PURPOSE, 0x0000 }, { 0xffff, 0xffff } }; +/* Initialize the AC97 into a known state. */ static int nm256_resetAC97 (struct ac97_hwint *dev) { @@ -742,22 +899,28 @@ nm256_resetAC97 (struct ac97_hwint *dev) return -EINVAL; } - /* Reset the card. 'Tis magic! */ + /* Reset the mixer. 'Tis magic! */ nm256_writePort8 (card, 2, 0x6c0, 1); nm256_writePort8 (card, 2, 0x6cc, 0x87); nm256_writePort8 (card, 2, 0x6cc, 0x80); nm256_writePort8 (card, 2, 0x6cc, 0x0); - for (x = 0; nm256_ac97_initial_values[x].port != 0xffff; x++) { - ac97_put_register (dev, - nm256_ac97_initial_values[x].port, - nm256_ac97_initial_values[x].value); + if (! card->mixer_values_init) { + for (x = 0; nm256_ac97_initial_values[x].port != 0xffff; x++) { + ac97_put_register (dev, + nm256_ac97_initial_values[x].port, + nm256_ac97_initial_values[x].value); + card->mixer_values_init = 1; + } } return 0; } -/* We don't do anything special here. */ +/* + * We don't do anything particularly special here; it just passes the + * mixer ioctl to the AC97 driver. + */ static int nm256_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg) { @@ -774,7 +937,12 @@ static struct mixer_operations nm256_mixer_operations = { nm256_default_mixer_ioctl }; -/* I "love" C sometimes. Got braces? */ +/* + * Default settings for the OSS mixer. These are set last, after the + * mixer is initialized. + * + * I "love" C sometimes. Got braces? + */ static struct ac97_mixer_value_list mixer_defaults[] = { { SOUND_MIXER_VOLUME, { { 85, 85 } } }, { SOUND_MIXER_SPEAKER, { { 100 } } }, @@ -783,6 +951,8 @@ static struct ac97_mixer_value_list mixer_defaults[] = { { -1, { { 0, 0 } } } }; + +/* Installs the AC97 mixer into CARD. */ static int nm256_install_mixer (struct nm256_info *card) { @@ -812,36 +982,67 @@ nm256_install_mixer (struct nm256_info *card) return 0; } -/* See if the signature left by the NM256 BIOS is intact; if so, we use - the associated address as the end of our buffer. */ +/* Perform a full reset on the hardware; this is invoked when an APM + resume event occurs. */ static void -nm256_peek_for_sig (struct nm256_info *card, u32 port1addr) +nm256_full_reset (struct nm256_info *card) { - char *temp = ioremap_nocache (port1addr + card->port1_end - 0x0400, 16); + nm256_initHw (card); + ac97_reset (&(card->mdev)); +} + +/* + * See if the signature left by the NM256 BIOS is intact; if so, we use + * the associated address as the end of our audio buffer in the video + * RAM. + */ + +static void +nm256_peek_for_sig (struct nm256_info *card) +{ + u32 port1offset + = card->port[0].physaddr + card->port[0].end_offset - 0x0400; + /* The signature is located 1K below the end of video RAM. */ + char *temp = ioremap_nocache (port1offset, 16); + /* Default buffer end is 5120 bytes below the top of RAM. */ + u32 default_value = card->port[0].end_offset - 0x1400; u32 sig; + /* Install the default value first, so we don't have to repeatedly + do it if there is a problem. */ + card->port[0].end_offset = default_value; + if (temp == NULL) { printk (KERN_ERR "NM256: Unable to scan for card signature in video RAM\n"); return; } - memcpy_fromio (&sig, temp, sizeof (u32)); - if ((sig & 0xffff0000) == 0x4e4d0000) { - memcpy_fromio (&(card->bufend), temp + 4, sizeof (u32)); + sig = readl (temp); + if ((sig & NM_SIG_MASK) == NM_SIGNATURE) { + u32 pointer = readl (temp + 4); + + /* + * If it's obviously invalid, don't use it (the port already has a + * suitable default value set). + */ + if (pointer != 0xffffffff) + card->port[0].end_offset = pointer; + printk (KERN_INFO "NM256: Found card signature in video RAM: 0x%x\n", - card->bufend); + pointer); } release_region ((unsigned long) temp, 16); } -/* Install a driver for the soundcard referenced by PCIDEV. */ +/* + * Install a driver for the PCI device referenced by PCIDEV. + * VERSTR is a human-readable version string. + */ static int nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr) { struct nm256_info *card; - u32 port1addr = pcidev->resource[0].start; - u32 port2addr = pcidev->resource[1].start; int x; card = kmalloc (sizeof (struct nm256_info), GFP_KERNEL); @@ -855,52 +1056,85 @@ nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr) card->recording = 0; card->rev = rev; - /* The NM256 has two memory ports. The first port is nothing - more than a chunk of video RAM, which is used as the I/O ring - buffer. The second port has the actual juicy stuff (like the - mixer and the playback engine control registers). */ + /* Init the memory port info. */ + for (x = 0; x < 2; x++) { + card->port[x].physaddr = RSRCADDRESS (pcidev, x); + card->port[x].ptr = NULL; + card->port[x].start_offset = 0; + card->port[x].end_offset = 0; + } - card->ports[1] = ioremap_nocache (port2addr, NM_PORT2_SIZE); + /* Port 2 is easy. */ + card->port[1].start_offset = 0; + card->port[1].end_offset = NM_PORT2_SIZE; - if (card->ports[1] == NULL) { - printk (KERN_ERR "NM256: Unable to remap port 2\n"); + /* Yuck. But we have to map in port 2 so we can check how much RAM the + card has. */ + if (nm256_remap_ports (card)) { kfree_s (card, sizeof (struct nm256_info)); return 0; } + /* + * The NM256 has two memory ports. The first port is nothing + * more than a chunk of video RAM, which is used as the I/O ring + * buffer. The second port has the actual juicy stuff (like the + * mixer and the playback engine control registers). + */ + if (card->rev == REV_NM256AV) { - card->port1_end = 2560 * 1024; + /* Ok, try to see if this is a non-AC97 version of the hardware. */ + int pval = nm256_readPort16 (card, 2, NM_MIXER_PRESENCE); + if ((pval & NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) { + if (! force_load) { + printk (KERN_ERR "NM256: This doesn't look to me like the AC97-compatible version.\n"); + printk (KERN_ERR " You can force the driver to load by passing in the module\n"); + printk (KERN_ERR " parameter:\n"); + printk (KERN_ERR " force_ac97 = 1\n"); + printk (KERN_ERR "\n"); + printk (KERN_ERR " More likely, you should be using the appropriate SB-16 or\n"); + printk (KERN_ERR " CS4232 driver instead. (If your BIOS has settings for\n"); + printk (KERN_ERR " IRQ and/or DMA for the sound card, this is *not* the correct\n"); + printk (KERN_ERR " driver to use.)\n"); + nm256_release_ports (card); + kfree_s (card, sizeof (struct nm256_info)); + return 0; + } + else { + printk (KERN_INFO "NM256: Forcing driver load as per user request.\n"); + } + } + else { + /* printk (KERN_INFO "NM256: Congratulations. You're not running Eunice.\n")*/; + } + card->port[0].end_offset = 2560 * 1024; card->introutine = nm256_interrupt; + card->mixer_status_offset = NM_MIXER_STATUS_OFFSET; + card->mixer_status_mask = NM_MIXER_READY_MASK; } else { + /* Not sure if there is any relevant detect for the ZX or not. */ if (nm256_readPort8 (card, 2, 0xa0b) != 0) - card->port1_end = 6144 * 1024; + card->port[0].end_offset = 6144 * 1024; else - card->port1_end = 4096 * 1024; + card->port[0].end_offset = 4096 * 1024; card->introutine = nm256_interrupt_zx; + card->mixer_status_offset = NM2_MIXER_STATUS_OFFSET; + card->mixer_status_mask = NM2_MIXER_READY_MASK; } - /* Default value. */ - card->bufend = card->port1_end - 0x1400; - - if (buffertop >= 98304 && buffertop < card->port1_end) - card->bufend = buffertop; + if (buffertop >= 98304 && buffertop < card->port[0].end_offset) + card->port[0].end_offset = buffertop; else - nm256_peek_for_sig (card, port1addr); + nm256_peek_for_sig (card); - card->port1_start = card->bufend - 98304; + card->port[0].start_offset = card->port[0].end_offset - 98304; printk (KERN_INFO "NM256: Mapping port 1 from 0x%x - 0x%x\n", - card->port1_start, card->port1_end); - - card->ports[0] = - ioremap_nocache (port1addr + card->port1_start, - card->port1_end - card->port1_start); + card->port[0].start_offset, card->port[0].end_offset); - if (card->ports[0] == NULL) { - printk (KERN_ERR "NM256: Unable to remap port 1\n"); - release_region ((unsigned long) card->ports[1], NM_PORT2_SIZE); + if (nm256_remap_ports (card)) { kfree_s (card, sizeof (struct nm256_info)); return 0; } @@ -911,9 +1145,7 @@ nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr) card->has_irq = 0; if (nm256_grabInterrupt (card) != 0) { - release_region ((unsigned long) card->ports[0], - card->port1_end - card->port1_start); - release_region ((unsigned long) card->ports[1], NM_PORT2_SIZE); + nm256_release_ports (card); kfree_s (card, sizeof (struct nm256_info)); return 0; } @@ -924,10 +1156,36 @@ nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr) * Init the board. */ + card->playbackBufferSize = 16384; + card->recordBufferSize = 16384; + + card->coeffBuf = card->port[0].end_offset - NM_MAX_COEFFICIENT; + card->abuf2 = card->coeffBuf - card->recordBufferSize; + card->abuf1 = card->abuf2 - card->playbackBufferSize; + card->allCoeffBuf = card->abuf2 - (NM_TOTAL_COEFF_COUNT * 4); + + /* Fixed setting. */ + card->mixer = NM_MIXER_OFFSET; + card->mixer_values_init = 0; + + card->is_open_play = 0; + card->is_open_record = 0; + + card->coeffsCurrent = 0; + + card->opencnt[0] = 0; card->opencnt[1] = 0; + + /* Reasonable default settings, but largely unnecessary. */ + for (x = 0; x < 2; x++) { + card->sinfo[x].bits = 8; + card->sinfo[x].stereo = 0; + card->sinfo[x].samplerate = 8000; + } + nm256_initHw (card); for (x = 0; x < 2; x++) { - if ((card->dev[x] = + if ((card->dev[x] = sound_install_audiodrv(AUDIO_DRIVER_VERSION, "NM256", &nm256_audio_driver, sizeof(struct audio_driver), @@ -940,9 +1198,7 @@ nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr) } else { printk(KERN_ERR "NM256: Too many PCM devices available\n"); - release_region ((unsigned long) card->ports[0], - card->port1_end - card->port1_start); - release_region ((unsigned long) card->ports[1], NM_PORT2_SIZE); + nm256_release_ports (card); kfree_s (card, sizeof (struct nm256_info)); return 0; } @@ -964,6 +1220,48 @@ nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr) return 1; } + +#ifdef CONFIG_APM +/* + * APM event handler, so the card is properly reinitialized after a power + * event. + */ +static int +handle_apm_event (apm_event_t event) +{ + static int down = 0; + + switch (event) + { + case APM_SYS_SUSPEND: + case APM_USER_SUSPEND: + down++; + break; + case APM_NORMAL_RESUME: + case APM_CRITICAL_RESUME: + if (down) + { + struct nm256_info *crd; + + down = 0; + for (crd = nmcard_list; crd != NULL; crd = crd->next_card) + { + int playing = crd->playing; + nm256_full_reset (crd); + /* + * A little ugly, but that's ok; pretend the + * block we were playing is done. + */ + if (playing) + DMAbuf_outputintr (crd->dev_for_play, 1); + } + } + break; + } + return 0; +} +#endif + /* * This loop walks the PCI configuration database and finds where * the sound cards are. @@ -993,6 +1291,10 @@ init_nm256(void) if (count == 0) return -ENODEV; +#ifdef CONFIG_APM + apm_register_callback (&handle_apm_event); +#endif + printk (KERN_INFO "Done installing NM256 audio driver.\n"); return 0; } @@ -1028,10 +1330,13 @@ nm256_audio_open(int dev, int mode) if (! ((mode & OPEN_READ) || (mode & OPEN_WRITE))) return -EIO; - /* If it's open for both read and write, and the card's currently - being read or written to, then do the opposite of what has - already been done. Otherwise, don't specify any mode until the - user actually tries to do I/O. */ + /* + * If it's open for both read and write, and the card's currently + * being read or written to, then do the opposite of what has + * already been done. Otherwise, don't specify any mode until the + * user actually tries to do I/O. (Some programs open the device + * for both read and write, but only actually do reading or writing.) + */ if ((mode & OPEN_WRITE) && (mode & OPEN_READ)) { if (card->is_open_play) @@ -1105,6 +1410,7 @@ nm256_audio_close(int dev) } } +/* Standard ioctl handler. */ static int nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg) { @@ -1122,6 +1428,11 @@ nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg) else w = 1; + /* + * The code here is messy. There are probably better ways to do + * it. (It should be possible to handle it the same way the AC97 mixer + * is done.) + */ switch (cmd) { case SOUND_PCM_WRITE_RATE: @@ -1193,8 +1504,12 @@ nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg) return put_user(ret, (int *) arg); } -/* Given the dev DEV and an associated physical buffer PHYSBUF, return - a pointer to the actual buffer in kernel space. */ +/* + * Given the sound device DEV and an associated physical buffer PHYSBUF, + * return a pointer to the actual buffer in kernel space. + * + * This routine should exist as part of the soundcore routines. + */ static char * nm256_getDMAbuffer (int dev, unsigned long physbuf) @@ -1238,9 +1553,10 @@ nm256_audio_output_block(int dev, unsigned long physbuf, } } +/* Ditto, but do recording instead. */ static void nm256_audio_start_input(int dev, unsigned long physbuf, int count, - int intrflag) + int intrflag) { struct nm256_info *card = nm256_find_card (dev); @@ -1252,6 +1568,12 @@ nm256_audio_start_input(int dev, unsigned long physbuf, int count, } } +/* + * Prepare for inputting samples to DEV. + * Each requested buffer will be BSIZE byes long, with a total of + * BCOUNT buffers. + */ + static int nm256_audio_prepare_for_input(int dev, int bsize, int bcount) { @@ -1278,6 +1600,7 @@ nm256_audio_prepare_for_input(int dev, int bsize, int bcount) * 2. We get a write buffer without dma_mode setup (dmabuf.c:1152) * 3. We restart a transfer (dmabuf.c:1324) */ + static int nm256_audio_prepare_for_output(int dev, int bsize, int bcount) { @@ -1342,12 +1665,13 @@ static int loaded = 0; MODULE_PARM (usecache, "i"); MODULE_PARM (buffertop, "i"); MODULE_PARM (nm256_debug, "i"); +MODULE_PARM (force_load, "i"); int init_module (void) { nmcard_list = NULL; - printk (KERN_INFO "NeoMagic 256AV/256ZX audio driver, version 1.0\n"); + printk (KERN_INFO "NeoMagic 256AV/256ZX audio driver, version 1.1\n"); if (init_nm256 () == 0) { SOUND_LOCK; @@ -1372,9 +1696,7 @@ cleanup_module (void) stopRecord (card); if (card->has_irq) free_irq (card->irq, card); - release_region ((unsigned long) card->ports[0], - card->port1_end - card->port1_start); - release_region ((unsigned long) card->ports[1], NM_PORT2_SIZE); + nm256_release_ports (card); sound_unload_mixerdev (card->mixer_oss_dev); sound_unload_audiodev (card->dev[0]); sound_unload_audiodev (card->dev[1]); @@ -1383,6 +1705,9 @@ cleanup_module (void) } nmcard_list = NULL; } +#ifdef CONFIG_APM + apm_unregister_callback (&handle_apm_event); +#endif } #endif diff --git a/drivers/sound/nm256_coeff.h b/drivers/sound/nm256_coeff.h index c8fc7ecbe..0ceecc200 100644 --- a/drivers/sound/nm256_coeff.h +++ b/drivers/sound/nm256_coeff.h @@ -4622,7 +4622,8 @@ nm256_getStartOffset (u8 which) } static void -nm256_loadOneCoefficient (struct nm256_info *card, u32 port, u16 which) +nm256_loadOneCoefficient (struct nm256_info *card, int devnum, u32 port, + u16 which) { u32 coeffBuf = (which < 8) ? card->coeffBuf : card->allCoeffBuf; u16 offset = nm256_getStartOffset (which); @@ -4631,11 +4632,14 @@ nm256_loadOneCoefficient (struct nm256_info *card, u32 port, u16 which) card->coeffsCurrent = 0; if (nm256_debug) - printk (KERN_INFO "NM256: Loading coefficient buffer 0x%x-0x%x with coefficient %d\n", - coeffBuf, coeffBuf + size - 1, which); + printk (KERN_INFO "NM256: Loading coefficient buffer 0x%x-0x%x with coefficient %d, size %d, port 0x%x\n", + coeffBuf, coeffBuf + size - 1, which, size, port); nm256_writeBuffer8 (card, coefficients + offset, 1, coeffBuf, size); nm256_writePort32 (card, 2, port + 0, coeffBuf); - nm256_writePort32 (card, 2, port + 4, coeffBuf + size - 1); + /* ??? Record seems to behave differently than playback. */ + if (devnum == 0) + size--; + nm256_writePort32 (card, 2, port + 4, coeffBuf + size); } static void @@ -4663,7 +4667,7 @@ nm256_loadCoefficient (struct nm256_info *card, int which, int number) number += 8; if (! nm256_cachedCoefficients (card)) - nm256_loadOneCoefficient (card, addrs[which], number); + nm256_loadOneCoefficient (card, which, addrs[which], number); else { u32 base = card->allCoeffBuf; u32 offset = nm256_getStartOffset (number); diff --git a/drivers/usb/acm.c b/drivers/usb/acm.c index 3ecea982e..a47920d00 100644 --- a/drivers/usb/acm.c +++ b/drivers/usb/acm.c @@ -486,8 +486,8 @@ static void acm_disconnect(struct usb_device *dev) if (!acm->present) return; - printk("disconnecting\n"); - + acm->active=0; + acm->present=0; if (acm->writing){ usb_terminate_bulk(acm->dev, acm->writetransfer); acm->writing=0; @@ -498,8 +498,6 @@ static void acm_disconnect(struct usb_device *dev) } usb_release_irq(acm->dev,acm->ctrltransfer, acm->ctrlpipe); //BUG: What to do if a device is open?? Notify process or not allow cleanup? - acm->active=0; - acm->present=0; kfree(acm->writebuffer); kfree(acm->readbuffer); diff --git a/drivers/usb/cpia.c b/drivers/usb/cpia.c index 976ab02da..e6515c710 100644 --- a/drivers/usb/cpia.c +++ b/drivers/usb/cpia.c @@ -52,7 +52,7 @@ static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr) ptep = pte_offset(pmd, adr); pte = *ptep; if (pte_present(pte)) - ret = (pte_page(pte) | (adr & (PAGE_SIZE-1))); + ret = page_address(pte_page(pte)) | (adr & (PAGE_SIZE-1)); } } MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret)); diff --git a/drivers/usb/ezusb.c b/drivers/usb/ezusb.c index 8aabddd17..c64335699 100644 --- a/drivers/usb/ezusb.c +++ b/drivers/usb/ezusb.c @@ -1073,11 +1073,8 @@ void ezusb_cleanup(void) #ifdef MODULE -int minor = 192; - int init_module(void) { - ezusb_misc.minor = minor; return ezusb_init(); } diff --git a/drivers/usb/hub.c b/drivers/usb/hub.c index 59a539867..98c1c540c 100644 --- a/drivers/usb/hub.c +++ b/drivers/usb/hub.c @@ -15,6 +15,7 @@ #include #include +#include #include "usb.h" #include "hub.h" @@ -51,16 +52,16 @@ static int usb_set_port_feature(struct usb_device *dev, int port, int feature) static int usb_get_hub_status(struct usb_device *dev, void *data) { - /* FIXME: Don't hardcode 4 */ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0, data, 4, HZ); + USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0, + data, sizeof(struct usb_hub_status), HZ); } static int usb_get_port_status(struct usb_device *dev, int port, void *data) { - /* FIXME: Don't hardcode 4 */ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port, data, 4, HZ); + USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port, + data, sizeof(struct usb_hub_status), HZ); } /* @@ -101,6 +102,7 @@ static int usb_hub_configure(struct usb_hub *hub) unsigned char buffer[4], *bitmap; struct usb_hub_descriptor *descriptor; struct usb_descriptor_header *header; + struct usb_hub_status *hubsts; int i; /* Set it to the first configuration */ @@ -121,7 +123,7 @@ static int usb_hub_configure(struct usb_hub *hub) descriptor = (struct usb_hub_descriptor *)bitmap; hub->nports = dev->maxchild = descriptor->bNbrPorts; - printk(KERN_INFO "hub: %d-port%s detected\n", hub->nports, + printk(KERN_INFO "hub: %d port%s detected\n", hub->nports, (hub->nports == 1) ? "" : "s"); switch (descriptor->wHubCharacteristics & HUB_CHAR_LPSM) { @@ -144,14 +146,14 @@ static int usb_hub_configure(struct usb_hub *hub) switch (descriptor->wHubCharacteristics & HUB_CHAR_OCPM) { case 0x00: - printk(KERN_INFO "hub: global over current protection\n"); + printk(KERN_INFO "hub: global over-current protection\n"); break; case 0x08: - printk(KERN_INFO "hub: individual port over current protection\n"); + printk(KERN_INFO "hub: individual port over-current protection\n"); break; case 0x10: case 0x18: - printk(KERN_INFO "hub: no over current protection\n"); + printk(KERN_INFO "hub: no over-current protection\n"); break; } @@ -171,11 +173,12 @@ static int usb_hub_configure(struct usb_hub *hub) if (usb_get_hub_status(dev, buffer)) return -1; + hubsts = (struct usb_hub_status *)buffer; printk(KERN_INFO "hub: local power source is %s\n", - (buffer[0] & 1) ? "lost (inactive)" : "good"); + (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good"); - printk(KERN_INFO "hub: %sover current condition exists\n", - (buffer[0] & 2) ? "" : "no "); + printk(KERN_INFO "hub: %sover-current condition exists\n", + (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? "" : "no "); /* Enable power to the ports */ printk(KERN_INFO "hub: enabling power on all ports\n"); @@ -292,7 +295,7 @@ static void hub_disconnect(struct usb_device *dev) static void usb_hub_port_connect_change(struct usb_device *hub, int port) { struct usb_device *usb; - unsigned char buf[4]; + struct usb_port_status portsts; unsigned short portstatus, portchange; /* Disconnect anything that may have been there */ @@ -304,13 +307,13 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port) wait_ms(50); /* FIXME: This is from the *BSD stack, thanks! :) */ /* Check status */ - if (usb_get_port_status(hub, port + 1, buf)) { + if (usb_get_port_status(hub, port + 1, &portsts)) { printk(KERN_ERR "get_port_status failed\n"); return; } - portstatus = le16_to_cpup((unsigned short *)buf + 0); - portchange = le16_to_cpup((unsigned short *)buf + 1); + portstatus = le16_to_cpu(portsts.wPortStatus); + portchange = le16_to_cpu(portsts.wPortChange); /* If it's not in CONNECT and ENABLE state, we're done */ if ((!(portstatus & USB_PORT_STAT_CONNECTION)) && @@ -373,16 +376,16 @@ static void usb_hub_events(void) spin_unlock_irqrestore(&hub_event_lock, flags); for (i = 0; i < hub->nports; i++) { - unsigned char buf[4]; + struct usb_port_status portsts; unsigned short portstatus, portchange; - if (usb_get_port_status(dev, i + 1, buf)) { + if (usb_get_port_status(dev, i + 1, &portsts)) { printk(KERN_ERR "get_port_status failed\n"); continue; } - portstatus = le16_to_cpup((unsigned short *)buf + 0); - portchange = le16_to_cpup((unsigned short *)buf + 1); + portstatus = le16_to_cpu(portsts.wPortStatus); + portchange = le16_to_cpu(portsts.wPortChange); if (portchange & USB_PORT_STAT_C_CONNECTION) { printk(KERN_INFO "hub: port %d connection change\n", @@ -415,9 +418,8 @@ static void usb_hub_events(void) usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET); } - - } - } + } /* end for i */ + } /* end while (1) */ he_unlock: spin_unlock_irqrestore(&hub_event_lock, flags); diff --git a/drivers/usb/hub.h b/drivers/usb/hub.h index 49c531d30..c95a07d74 100644 --- a/drivers/usb/hub.h +++ b/drivers/usb/hub.h @@ -4,7 +4,7 @@ #include /* - * Hub feature numbers + * Hub Class feature numbers */ #define C_HUB_LOCAL_POWER 0 #define C_HUB_OVER_CURRENT 1 @@ -25,7 +25,12 @@ #define USB_PORT_FEAT_C_OVER_CURRENT 19 #define USB_PORT_FEAT_C_RESET 20 -/* wPortStatus */ +struct usb_port_status { + __u16 wPortStatus; + __u16 wPortChange; +} __attribute__ ((packed)); + +/* wPortStatus bits */ #define USB_PORT_STAT_CONNECTION 0x0001 #define USB_PORT_STAT_ENABLE 0x0002 #define USB_PORT_STAT_SUSPEND 0x0004 @@ -34,7 +39,7 @@ #define USB_PORT_STAT_POWER 0x0100 #define USB_PORT_STAT_LOW_SPEED 0x0200 -/* wPortChange */ +/* wPortChange bits */ #define USB_PORT_STAT_C_CONNECTION 0x0001 #define USB_PORT_STAT_C_ENABLE 0x0002 #define USB_PORT_STAT_C_SUSPEND 0x0004 @@ -46,6 +51,20 @@ #define HUB_CHAR_COMPOUND 0x0004 #define HUB_CHAR_OCPM 0x0018 +struct usb_hub_status { + __u16 wHubStatus; + __u16 wHubChange; +} __attribute__ ((packed)); + +/* + *Hub Status & Hub Change bit masks + */ +#define HUB_STATUS_LOCAL_POWER 0x0001 +#define HUB_STATUS_OVERCURRENT 0x0002 + +#define HUB_CHANGE_LOCAL_POWER 0x0001 +#define HUB_CHANGE_OVERCURRENT 0x0002 + /* Hub descriptor */ struct usb_hub_descriptor { __u8 bLength; @@ -103,4 +122,3 @@ struct usb_hub { }; #endif - diff --git a/drivers/usb/ohci-hcd.c b/drivers/usb/ohci-hcd.c index 3dc6d74ca..3345e12be 100644 --- a/drivers/usb/ohci-hcd.c +++ b/drivers/usb/ohci-hcd.c @@ -14,9 +14,8 @@ * [ Open Host Controller Interface driver for USB. ] * [ (C) Copyright 1999 Linus Torvalds (uhci.c) ] * [ (C) Copyright 1999 Gregory P. Smith ] - * [ _Log: ohci-hcd.c,v _ - * [ Revision 1.1 1999/04/05 08:32:30 greg ] * + * v4.3 1999/10/27 multiple HCs, bulk_request * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl. * v4.0 1999/08/18 @@ -48,6 +47,7 @@ #include #include #include +#include #include #include @@ -61,6 +61,7 @@ static int handle_apm_event(apm_event_t event); static int apm_resume = 0; #endif +static LIST_HEAD(ohci_hcd_list); static int ohci_link_ed(struct ohci * ohci, struct usb_ohci_ed *ed); static int sohci_kill_isoc (struct usb_isoc_desc *id); @@ -85,10 +86,11 @@ OHCI_DEBUG(printk("******* dev: devnum: %4x, slow: %4x, maxpacketsize: %4x\n",us **** Interface functions ***********************************************/ -static int sohci_blocking_handler(void * ohci_in, struct usb_ohci_ed *ed, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1) +static int sohci_blocking_handler(void * ohci_in, struct usb_ohci_td *td, void * data, int data_len, int dlen, int status, __OHCI_BAG lw0, __OHCI_BAG lw1) { + struct usb_ohci_ed *ed = td->ed; if(lw0 != NULL) { - if(USB_ST_CRC < 0 && (status == USB_ST_DATAUNDERRUN || status == USB_ST_NOERROR)) + if(0 < 0 && (status == USB_ST_DATAUNDERRUN || status == USB_ST_NOERROR)) ((struct ohci_state * )lw0)->status = data_len; else ((struct ohci_state * )lw0)->status = status; @@ -107,9 +109,9 @@ static int sohci_blocking_handler(void * ohci_in, struct usb_ohci_ed *ed, void * return 0; } -static int sohci_int_handler(void * ohci_in, struct usb_ohci_ed *ed, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1) +static int sohci_int_handler(void * ohci_in, struct usb_ohci_td *td, void * data, int data_len, int dlen, int status, __OHCI_BAG lw0, __OHCI_BAG lw1) { - + struct usb_ohci_ed *ed = td->ed; struct ohci * ohci = ohci_in; usb_device_irq handler=(void *) lw0; void *dev_id = (void *) lw1; @@ -127,9 +129,30 @@ static int sohci_int_handler(void * ohci_in, struct usb_ohci_ed *ed, void * data return 0; } -static int sohci_iso_handler(void * ohci_in, struct usb_ohci_ed *ed, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1) { +static int sohci_ret_handler(void * ohci_in, struct usb_ohci_td *td, void * data, int data_len, int dlen, int status, __OHCI_BAG lw0, __OHCI_BAG lw1) +{ + struct usb_ohci_ed *ed = td->ed; + struct ohci * ohci = ohci_in; + usb_device_irq handler=(void *) lw0; + void *dev_id = (void *) lw1; + int ret; + + OHCI_DEBUG({ int i; printk("USB HC RET <<<: %x: data(%d):", ed->hwINFO, data_len);) + OHCI_DEBUG( for(i=0; i < data_len; i++ ) printk(" %02x", ((__u8 *) data)[i]);) + OHCI_DEBUG( printk(" ret_status: %x\n", status); }) + + ret = handler(status, data, data_len, dev_id); + if(ret == 0) return 0; /* 0 .. do not requeue */ + if(status > 0) return -1; /* error occured do not requeue ? */ + ohci_trans_req(ohci, ed, 0, NULL, data, dlen, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id, td->type & 0x7, sohci_ret_handler); /* requeue int request */ + + return 0; +} + +static int sohci_iso_handler(void * ohci_in, struct usb_ohci_td *td, void * data, int data_len, int dlen, int status, __OHCI_BAG lw0, __OHCI_BAG lw1) { // struct ohci * ohci = ohci_in; + struct usb_ohci_ed *ed = td->ed; unsigned int ix = (unsigned int) lw0; struct usb_isoc_desc * id = (struct usb_isoc_desc *) lw1; struct usb_ohci_td **tdp = id->td; @@ -311,7 +334,7 @@ static void * sohci_request_bulk(struct usb_device *usb_dev, unsigned int pipe, OHCI_DEBUG( printk("USB HC BULK_RQ>>>: %x \n", ed->hwINFO);) - ohci_trans_req(ohci, ed, 0, NULL, data, len, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id, (usb_pipeout(pipe))?BULK_OUT:BULK_IN, sohci_int_handler); + ohci_trans_req(ohci, ed, 0, NULL, data, len, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id, (usb_pipeout(pipe))?BULK_OUT:BULK_IN, sohci_ret_handler); if (ED_STATE(ed) != ED_OPER) ohci_link_ed(ohci, ed); return ed; @@ -482,7 +505,7 @@ static int sohci_kill_isoc(struct usb_isoc_desc *id) { struct usb_ohci_ed *ed = NULL; struct usb_ohci_td **td = id->td; int i; -printk("KILL_ISOC***:\n"); + for (i = 0; i < id->frame_count; i++) { if(td[i]) { td[i]->type |= DEL; @@ -490,22 +513,17 @@ printk("KILL_ISOC***:\n"); } } if(ed) usb_ohci_rm_ep(id->usb_dev, ed, NULL, NULL, NULL, TD_RM); -printk(": end KILL_ISOC***: %p\n", ed); + id->start_frame = -1; return 0; } static void sohci_free_isoc(struct usb_isoc_desc *id) { -printk("FREE_ISOC***\n"); -wait_ms(2000); + if(id->start_frame >= 0) sohci_kill_isoc(id); -printk("FREE_ISOC2***\n"); -wait_ms(2000); kfree(id->td); kfree(id); -printk("FREE_ISOC3***\n"); -wait_ms(2000); } struct usb_operations sohci_device_operations = { @@ -772,17 +790,14 @@ struct usb_ohci_ed *usb_ohci_add_ep(struct usb_device * usb_dev, struct usb_hcd_ // struct ohci * ohci = usb_dev->bus->hcpriv; struct usb_ohci_td * td; - struct usb_ohci_ed * ed, *ed1; + struct usb_ohci_ed * ed; - int ed_state, ed_state1; + int ed_state; spin_lock(&usb_ed_lock); ed = ohci_find_ep(usb_dev, hcd_ed); - - ed1 = ((void *) ed) + 0x40; ed_state1 = ED_STATE(ed1); -OHCI_DEBUG(printk("++++ USB HC add 60 ed1 %x: %x :state: %x\n", ed1->hwINFO, (unsigned int ) ed1, ed_state1); ) ed_state = ED_STATE(ed); /* store state of ed */ OHCI_DEBUG(printk("USB HC add ed %x: %x :state: %x\n", ed->hwINFO, (unsigned int ) ed, ed_state); ) if (ed_state == ED_NEW) { @@ -1139,7 +1154,8 @@ static int usb_ohci_done_list(struct ohci * ohci, struct usb_ohci_td * td_list) struct usb_ohci_td * td_list_next = NULL; int cc; - int i; + int i; + int dlen = 0; while(td_list) { td_list_next = td_list->next_dl_td; @@ -1156,8 +1172,9 @@ static int usb_ohci_done_list(struct ohci * ohci, struct usb_ohci_td * td_list) } else { if(td_list->hwBE != 0) { + dlen = (bus_to_virt(td_list->hwBE) - td_list->buffer_start + 1); if(td_list->hwCBP == 0) - td_list->ed->len += (bus_to_virt(td_list->hwBE) - td_list->buffer_start + 1); + td_list->ed->len += dlen; else td_list->ed->len += (bus_to_virt(td_list->hwCBP) - td_list->buffer_start); } @@ -1170,9 +1187,10 @@ static int usb_ohci_done_list(struct ohci * ohci, struct usb_ohci_td * td_list) if((td_list->type & SEND) && (ED_STATE(td_list->ed) != ED_STOP) && (td_list->handler)) { /* send the reply */ td_list->handler((void *) ohci, - td_list->ed, + td_list, td_list->ed->buffer_start, td_list->ed->len, + dlen, cc, td_list->lw0, td_list->lw1); @@ -1227,7 +1245,7 @@ void reset_hc(struct ohci *ohci) { udelay(1); } } -static struct ohci *__ohci; + /* * Start an OHCI controller, set the BUS operational @@ -1353,7 +1371,7 @@ static struct ohci *alloc_ohci(void* mem_base) ohci->irq = -1; ohci->regs = mem_base; ohci->hc_area = hc_area; - __ohci = ohci; + /* * for load ballancing of the interrupt branches */ @@ -1395,7 +1413,7 @@ static void release_ohci(struct ohci *ohci) /* disconnect all devices */ if(ohci->bus->root_hub) usb_disconnect(&ohci->bus->root_hub); - reset_hc(__ohci); + reset_hc(ohci); writel(OHCI_USB_RESET, &ohci->regs->control); wait_ms(10); @@ -1428,6 +1446,9 @@ static int found_ohci(int irq, void* mem_base) return -ENOMEM; } + INIT_LIST_HEAD(&ohci->ohci_hcd_list); + list_add(&ohci->ohci_hcd_list, &ohci_hcd_list); + reset_hc(ohci); writel(OHCI_USB_RESET, &ohci->regs->control); wait_ms(10); @@ -1438,6 +1459,7 @@ static int found_ohci(int irq, void* mem_base) start_hc(ohci); return 0; } + printk(KERN_ERR "USB HC (ohci-hcd): request interrupt %d failed\n", irq); release_ohci(ohci); return -EBUSY; } @@ -1445,7 +1467,8 @@ static int found_ohci(int irq, void* mem_base) static int start_ohci(struct pci_dev *dev) { unsigned int mem_base = dev->resource[0].start; - + + pci_set_master(dev); mem_base = (unsigned int) ioremap_nocache(mem_base, 4096); if (!mem_base) { @@ -1488,17 +1511,18 @@ static int handle_apm_event(apm_event_t event) int ohci_hcd_init(void) { + int ret = -ENODEV; struct pci_dev *dev = NULL; while((dev = pci_find_class(PCI_CLASS_SERIAL_USB_OHCI, dev))) { - if (start_ohci(dev) < 0) return -ENODEV; + if (start_ohci(dev) >= 0) ret = 0; } #ifdef CONFIG_APM apm_register_callback(&handle_apm_event); #endif - return 0; + return ret; } #ifdef MODULE @@ -1509,10 +1533,17 @@ int init_module(void) void cleanup_module(void) { + struct ohci *ohci; + # ifdef CONFIG_APM apm_unregister_callback(&handle_apm_event); # endif - release_ohci(__ohci); + while(!list_empty(&ohci_hcd_list)) { + ohci = list_entry(ohci_hcd_list.next, struct ohci, ohci_hcd_list); + list_del(ohci->ohci_hcd_list); + INIT_LIST_HEAD(ohci->ohci_hcd_list); + release_ohci(ohci); + } } #endif //MODULE diff --git a/drivers/usb/ohci-hcd.h b/drivers/usb/ohci-hcd.h index 3ff3ae91d..722bbeaea 100644 --- a/drivers/usb/ohci-hcd.h +++ b/drivers/usb/ohci-hcd.h @@ -48,10 +48,11 @@ #include #include struct usb_ohci_ed; +struct usb_ohci_td; /* for ED and TD structures */ typedef void * __OHCI_BAG; -typedef int (*f_handler )(void * ohci, struct usb_ohci_ed *ed, void *data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1); +typedef int (*f_handler )(void * ohci, struct usb_ohci_td *td, void *data, int data_len, int dlen, int status, __OHCI_BAG lw0, __OHCI_BAG lw1); @@ -309,7 +310,9 @@ struct ohci { int irq; struct ohci_regs *regs; /* OHCI controller's memory */ struct ohci_hc_area *hc_area; /* hcca, int ed-tree, ohci itself .. */ - + + struct list_head ohci_hcd_list; /* list of all ohci_hcd */ + int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load ballancing)*/ struct usb_ohci_ed * ed_rm_list; /* list of all endpoints to be removed */ struct usb_ohci_ed * ed_bulktail; /* last endpoint of bulk list */ diff --git a/drivers/usb/uhci.c b/drivers/usb/uhci.c index 20be3faab..25b2b303c 100644 --- a/drivers/usb/uhci.c +++ b/drivers/usb/uhci.c @@ -154,7 +154,10 @@ static int uhci_td_result(struct uhci_device *dev, struct uhci_td *td, unsigned actlength = uhci_actual_length(tmp->status); if (rval) *rval += actlength; - if (explength != actlength) { + /* This check is bogus, at least for acm. It + always expects 64, but gets as many bytes + as available (typically 1) -- pavel */ + if (0 && (explength != actlength)) { /* Reset the data toggle on error. */ if (debug || uhci_debug) printk(KERN_DEBUG "Set toggle from %p rval %ld%c for status=%x to %d, exp=%d, act=%d\n", diff --git a/drivers/usb/usb-serial.c b/drivers/usb/usb-serial.c index b85f2b5c6..6eb2d6455 100644 --- a/drivers/usb/usb-serial.c +++ b/drivers/usb/usb-serial.c @@ -11,6 +11,9 @@ * vendor and device ids for that device. * * + * version 0.1.2 (10/25/99) gkh + * Fixed bug in detecting device. + * * version 0.1.1 (10/05/99) gkh * Changed the major number to not conflict with anything else. * @@ -528,7 +531,7 @@ static int usb_serial_probe(struct usb_device *dev) serial->interrupt_in_interval = endpoint->bInterval; /* serial->interrupt_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint); */ serial->interrupt_in_buffer = kmalloc (serial->bulk_in_size, GFP_KERNEL); - if (!serial->bulk_in_buffer) { + if (!serial->interrupt_in_buffer) { printk("USB Serial: Couldn't allocate interrupt_in_buffer\n"); goto probe_error; } -- cgit v1.2.3