[PATCH] try to keep hd64465 socket driver up to date

Dominik Brodowski linux at brodo.de
Sat Jul 5 13:00:29 BST 2003


Even though the hd64465_ss.c driver seems to be very broken [note the
#error in lines 625-628], try to keep it up to date wrt pcmcia core
changes in 2.5.
This patch includes the following changes:

- irqreturn_t update
- callbacks use pcmcia_socket * not integer
- remove "inquire_socket"
- move "owner" field to pcmcia_socket
- allow socket drivers to call pcmcia_parse_events directly
- Remove work handler and work queue.  Call pcmcia_parse_events direct
  from interrupt handler. 
- update registration process

 drivers/pcmcia/hd64465_ss.c |  186 ++++++++++++++------------------------------
 1 files changed, 62 insertions(+), 124 deletions(-)



diff -ruN linux-original/drivers/pcmcia/hd64465_ss.c linux/drivers/pcmcia/hd64465_ss.c
--- linux-original/drivers/pcmcia/hd64465_ss.c	2003-07-05 10:22:58.000000000 +0200
+++ linux/drivers/pcmcia/hd64465_ss.c	2003-07-05 11:51:06.000000000 +0200
@@ -1,5 +1,5 @@
 /*
- * $Id$
+ * $Id: hd64465_ss.c,v 1.6 2003/05/04 19:29:58 lethal Exp $
  *
  * Device driver for the PCMCIA controller module of the
  * Hitachi HD64465 handheld companion chip.
@@ -74,38 +74,26 @@
 
 typedef struct hs_socket_t
 {
+    unsigned int	number;
     u_int   	    	irq;
     u_long  	    	mem_base;
     u_long  	    	mem_length;
-    void	    	(*handler)(void *info, u_int events);
-    void    	    	*handler_info;
-    u_int   	    	pending_events;
     u_int   	    	ctrl_base;
     socket_state_t  	state;
     pccard_io_map     	io_maps[MAX_IO_WIN];
     pccard_mem_map  	mem_maps[MAX_WIN];
     struct vm_struct	*io_vma;    /* allocated kernel vm for mapping IO space */
+    struct pcmcia_socket	socket;
 } hs_socket_t;
 
+
+
 #define HS_MAX_SOCKETS 2
 static hs_socket_t hs_sockets[HS_MAX_SOCKETS];
-static spinlock_t hs_pending_event_lock = SPIN_LOCK_UNLOCKED;
 
 /* Calculate socket number from ptr into hs_sockets[] */
 #define hs_sockno(sp) 	(sp - hs_sockets)
 
-static socket_cap_t hs_socket_cap =
-{
-    SS_CAP_PCCARD   	    /* support 16 bit cards */
-    |SS_CAP_STATIC_MAP      /* mappings are fixed in host memory */
-    ,
-    0xffde/*0xffff*/, 	    /* IRQs mapped in s/w so can do any, really */
-    HD64465_PCC_WINDOW,     /* 16MB fixed window size */
-    0,	    	    	    /* no PCI support */
-    0,	    	    	    /* no CardBus support */
-    0	    	    	    /* no bus operations needed */
-};
-
 #define hs_in(sp, r)	    inb((sp)->ctrl_base + (r))
 #define hs_out(sp, v, r)    outb(v, (sp)->ctrl_base + (r))
 
@@ -359,11 +347,11 @@
 
 /*============================================================*/
 
-static int hs_init(unsigned int sock)
+static int hs_init(struct pcmcia_socket *s)
 {
-    	hs_socket_t *sp = &hs_sockets[sock];
+    	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
 	
-    	DPRINTK("hs_init(%d)\n", sock);
+    	DPRINTK("hs_init(%d)\n", sp->number);
 	
 	sp->pending_events = 0;
 	sp->state.Vcc = 0;
@@ -375,9 +363,10 @@
 
 /*============================================================*/
 
-static int hs_suspend(unsigned int sock)
+static int hs_suspend(struct pcmcia_socket *s)
 {
-    	DPRINTK("hs_suspend(%d)\n", sock);
+    	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
+    	DPRINTK("hs_suspend(%d)\n", sp->number);
 
     	/* TODO */
 	
@@ -386,32 +375,10 @@
 
 /*============================================================*/
 
-static int hs_register_callback(unsigned int sock,
-    	    void (*handler)(void *, unsigned int), void * info)
-{
-    	hs_socket_t *sp = &hs_sockets[sock];
-	
-    	DPRINTK("hs_register_callback(%d)\n", sock);
-	sp->handler = handler;
-	sp->handler_info = info;
-	return 0;
-}
-
-/*============================================================*/
 
-static int hs_inquire_socket(unsigned int sock, socket_cap_t *cap)
+static int hs_get_status(struct pcmcia_socket *s, u_int *value)
 {
-    	DPRINTK("hs_inquire_socket(%d)\n", sock);
-
-	*cap = hs_socket_cap;
-	return 0;
-}
-
-/*============================================================*/
-
-static int hs_get_status(unsigned int sock, u_int *value)
-{
-    	hs_socket_t *sp = &hs_sockets[sock];
+    	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
     	unsigned int isr;
 	u_int status = 0;
 	
@@ -473,9 +440,9 @@
 
 /*============================================================*/
 
-static int hs_get_socket(unsigned int sock, socket_state_t *state)
+static int hs_get_socket(struct pcmcia_socket *s, socket_state_t *state)
 {
-    	hs_socket_t *sp = &hs_sockets[sock];
+    	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
 
     	DPRINTK("hs_get_socket(%d)\n", sock);
 	
@@ -485,9 +452,9 @@
 
 /*============================================================*/
 
-static int hs_set_socket(unsigned int sock, socket_state_t *state)
+static int hs_set_socket(struct pcmcia_socket *s, socket_state_t *state)
 {
-    	hs_socket_t *sp = &hs_sockets[sock];
+    	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
     	u_long flags;
 	u_int changed;
 	unsigned short cscier;
@@ -495,12 +462,12 @@
     	DPRINTK("hs_set_socket(sock=%d, flags=%x, csc_mask=%x, Vcc=%d, Vpp=%d, io_irq=%d)\n",
 	    sock, state->flags, state->csc_mask, state->Vcc, state->Vpp, state->io_irq);
 	
-	save_and_cli(flags);	/* Don't want interrupts happening here */
+	local_irq_save(flags);	/* Don't want interrupts happening here */
 
 	if (state->Vpp != sp->state.Vpp ||
 	    state->Vcc != sp->state.Vcc) {
 	    if (!hs_set_voltages(sp, state->Vcc, state->Vpp)) {
-	    	restore_flags(flags);
+	    	local_irq_restore(flags);
 	    	return -EINVAL;
 	    }
 	}
@@ -588,7 +555,7 @@
 /*    	hd64465_io_debug = 0; */
 	sp->state = *state;
 	    
-	restore_flags(flags);
+	local_irq_restore(flags);
 
 #if HD64465_DEBUG > 10
 	if (state->flags & SS_OUTPUT_ENA)   
@@ -599,9 +566,9 @@
 
 /*============================================================*/
 
-static int hs_set_io_map(unsigned int sock, struct pccard_io_map *io)
+static int hs_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
 {
-    	hs_socket_t *sp = &hs_sockets[sock];
+    	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
 	int map = io->map;
 	struct pccard_io_map *sio;
 	pgprot_t prot;
@@ -681,9 +648,9 @@
 
 /*============================================================*/
 
-static int hs_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+static int hs_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
 {
-    	hs_socket_t *sp = &hs_sockets[sock];
+    	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
 	struct pccard_mem_map *smem;
 	int map = mem->map;
 	unsigned long paddr, size;
@@ -722,13 +689,6 @@
 
 /*============================================================*/
 
-static void hs_proc_setup(unsigned int sock, struct proc_dir_entry *base)
-{
-    	DPRINTK("hs_proc_setup(%d)\n", sock);
-}
-
-/*============================================================*/
-
 /*
  * This function is registered with the HD64465 glue code to do a
  * secondary demux step on the PCMCIA interrupts.  It handles 
@@ -756,35 +716,9 @@
 
 /*
  * Interrupt handling routine.
- *
- * This uses the schedule_work() technique to cause reportable events
- * such as card insertion and removal to be handled in keventd's
- * process context.
  */
  
-
-static void hs_events_bh(void *dummy)
-{
-	hs_socket_t *sp;
-	u_int events;
-	int i;
-
-	for (i=0; i<HS_MAX_SOCKETS; i++) {
-	    sp = &hs_sockets[i];
-
-	    spin_lock_irq(&hs_pending_event_lock);
-	    events = sp->pending_events;
-	    sp->pending_events = 0;
-	    spin_unlock_irq(&hs_pending_event_lock);
-	    
-	    if (sp->handler)
-		sp->handler(sp->handler_info, events);
-	}
-}
-
-static DECLARE_WORK(hs_events_task, hs_events_bh, NULL);
-
-static void hs_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t hs_interrupt(int irq, void *dev, struct pt_regs *regs)
 {
     	hs_socket_t *sp = (hs_socket_t *)dev;
 	u_int events = 0;
@@ -839,34 +773,22 @@
 
 	hs_out(sp, cscr, CSCR);
 
-	if (events) {
-	    /*
-    	     * Arrange for events to be reported to the registered
-	     * event handler function (from CardServices) in a process
-	     * context (keventd) "soon".
-	     */
-	    spin_lock(&hs_pending_event_lock);
-	    sp->pending_events |= events;
-	    spin_unlock(&hs_pending_event_lock);
-	    
-	    schedule_work(&hs_events_task);
-	}
+	if (events)
+		pcmcia_parse_events(&sp->socket, events);
+
+	return IRQ_HANDLED;
 }
 
 /*============================================================*/
 
 static struct pccard_operations hs_operations = {
-	.owner			= THIS_MODULE,
 	.init			= hs_init,
 	.suspend		= hs_suspend,
-	.register_callback	= hs_register_callback,
-	.inquire_socket		= hs_inquire_socket,
 	.get_status		= hs_get_status,
 	.get_socket		= hs_get_socket,
 	.set_socket		= hs_set_socket,
 	.set_io_map		= hs_set_io_map,
 	.set_mem_map		= hs_set_mem_map,
-	.proc_setup		= hs_proc_setup,
 };
 
 static int hs_init_socket(hs_socket_t *sp, int irq, unsigned long mem_base,
@@ -959,15 +881,9 @@
 	    vfree(sp->io_vma->addr);
 }
 
-static struct pcmcia_socket_class_data hd64465_data = {
-	.nsock = HS_MAX_SOCKETS,
-	.ops = &hs_operations,
-};
-
 static struct device_driver hd64465_driver = {
 	.name = "hd64465-pcmcia",
 	.bus = &platform_bus_type,
-	.devclass = &pcmcia_socket_class,
 	.suspend = pcmcia_socket_dev_suspend,
 	.resume = pcmcia_socket_dev_resume,
 };
@@ -996,7 +912,8 @@
 	}
 
 /*	hd64465_io_debug = 1; */
-	register_driver(&hd64465_driver);
+	if (driver_register(&hd64465_driver))
+		return -EINVAL;
 	
 	/* Wake both sockets out of STANDBY mode */
 	/* TODO: wait 15ms */
@@ -1014,36 +931,53 @@
 	v |= HD64465_PCCCSCR_PSWSEL;
 	outb(v, HD64465_REG_PCC0CSCR);
 
-    	hs_set_voltages(&hs_sockets[0], 0, 0);
-    	hs_set_voltages(&hs_sockets[1], 0, 0);
-	
 	/*
 	 * Setup hs_sockets[] structures and request system resources.
 	 * TODO: on memory allocation failure, power down the socket
 	 *       before quitting.
 	 */
+	for (i=0; i<2; i++) {
+		hs_set_voltages(&hs_sockets[i], 0, 0);
+
+		hs_sockets[i].socket.features |=  SS_CAP_PCCARD | SS_CAP_STATIC_MAP;      /* mappings are fixed in host memory */
+		hs_sockets[i].socket.irq_mask =  0xffde;/*0xffff*/	    /* IRQs mapped in s/w so can do any, really */
+		hs_sockets[i].socket.map_size = HD64465_PCC_WINDOW;     /* 16MB fixed window size */
+
+		hs_sockets[i].socket.owner = THIS_MODULE;
+		hs_sockets[i].socket.ss_entry = &hs_operations;
+	}
+
 	i = hs_init_socket(&hs_sockets[0],
 	    HD64465_IRQ_PCMCIA0,
 	    HD64465_PCC0_BASE,
 	    HD64465_REG_PCC0ISR);
 	if (i < 0) {
 		unregister_driver(&hd64465_driver);
-		return i;
+	    return i;
 	}
+
 	i = hs_init_socket(&hs_sockets[1],
 	    HD64465_IRQ_PCMCIA1,
 	    HD64465_PCC1_BASE,
 	    HD64465_REG_PCC1ISR);
 	if (i < 0) {
 		unregister_driver(&hd64465_driver);
-		return i;
+	    return i;
 	}
 
 /*	hd64465_io_debug = 0; */
-	hd64465_device.dev.class_data = &hd64465_data;
+
 	platform_device_register(&hd64465_device);
 
-	return 0;
+	for (i=0; i<2; i++) {
+		unsigned int ret;
+		hs_sockets[i].socket.dev.dev = &hd64465_device.dev;		
+		ret = pcmcia_register_socket(&hs_sockets[i].socket);
+		if (ret && i)
+			pcmcia_unregister_socket(&hs_socket[0].socket);
+	}
+
+    	return 0;
 }
 
 static void __exit exit_hs(void)
@@ -1051,16 +985,20 @@
     	u_long flags;
 	int i;
 	
-	save_and_cli(flags);
+	for (i=0 ; i<HS_MAX_SOCKETS ; i++)
+		pcmcia_unregister_socket(&hs_socket[i].socket);
+
+	local_irq_save(flags);
 
     	/*
 	 * Release kernel resources
 	 */
 	for (i=0 ; i<HS_MAX_SOCKETS ; i++)
 	    hs_exit_socket(&hs_sockets[i]);
-	platform_device_unregister(&hd64465_device);
 	
-	restore_flags(flags);
+	local_irq_restore(flags);
+
+	platform_device_unregister(&hd64465_device);
 	unregister_driver(&hd64465_driver);
 }
 



More information about the linux-pcmcia mailing list