Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 10 Feb 2000 10:27:07 -0800 (PST)
From:      Doug Ambrisko <ambrisko@whistle.com>
To:        imp@village.org, freebsd-mobile@freebsd.org
Subject:   Update to pccard ata changes (removal support)
Message-ID:  <200002101827.KAA90609@whistle.com>

next in thread | raw e-mail | index | archive | help
I have now added removal support to the ata driver for pccard.

Caveats, the devices increment each time they are inserted and removed.
Also I do not checks for mounted devices etc. yet.  I'm not sure what
the details are to deal with this (since as the card is being ripped out
there won't be time to sync the device).  So your machine might panic. 
I don't know and haven't tested this.  I also need to look at the 
incrementing device issue.  I thought it would be usefull to get this
code out before I start to investigate that.

I have tested it with my external hard disk, CD-Rom and Zip.  They
all seemed to handle it fine.  Device accesses to old device names
failed somewhat gracefully (ie. no panic but some error messages).

Please let me know how it works.  Again this is relative to -current.

Doug A.

Index: ata-all.c
===================================================================
RCS file: /cvs/freebsd/src/sys/dev/ata/ata-all.c,v
retrieving revision 1.47
diff -c -r1.47 ata-all.c
*** ata-all.c	2000/02/04 10:20:20	1.47
--- ata-all.c	2000/02/10 18:17:34
***************
*** 30,35 ****
--- 30,36 ----
  
  #include "ata.h"
  #include "apm.h"
+ #include "card.h"
  #include "isa.h"
  #include "pci.h"
  #include "atadisk.h"
***************
*** 88,93 ****
--- 89,103 ----
  static void btrim(int8_t *, int32_t);
  static void bpack(int8_t *, int8_t *, int32_t);
  
+ #if NCARD > 0
+ static	int	ata_pccard_attach __P((device_t dev));
+ static	int	ata_pccard_detach __P((device_t dev));
+ static	int	ata_pccard_probe __P((device_t dev));
+ /* XXX */
+ extern  void    ad_drvinit(void);
+ extern  void    atapi_init(void);
+ #endif /* NCARD > 0 */
+ 
  /* local vars */
  static int32_t atanlun = 2;
  static struct intr_config_hook *ata_attach_hook = NULL;
***************
*** 187,192 ****
--- 197,354 ----
  DRIVER_MODULE(ata, isa, ata_isa_driver, ata_devclass, 0, 0);
  #endif
  
+ #if NCARD > 0
+ static int
+ ata_pccard_probe(dev)
+ 	device_t	dev;
+ {
+     struct resource *port;
+     int rid;
+     int32_t res;
+     int32_t lun;
+     static struct intr_config_hook *tmp;
+ 
+     /* Allocate the port range */
+     rid = 0;
+     port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 16, RF_ACTIVE);
+     /* XXX 16 shouldn't be hard coded */
+ 
+     if (!port)
+ 	return (ENOMEM);
+     
+     /* don't worry about conflict since PCCard code should have checked 
+        already */
+     /*
+      * XXX ALTPORT not used in pccard XXX
+      * Here's the i/o map for isa vs pccard
+      * Offset		isa	pccard
+      * DATA		0	0
+      * ERROR		1	1	R
+      * FEATURE		1	1	W
+      * COUNT		2	2	W
+      * IREASON		2	2	R
+      * SECTOR		3	3
+      * CYL_LSB		4	4
+      * CYL_MSB		5	5
+      * DRIVE		6	6
+      * CMD		7	7
+      * STATUS		7	7
+      * ALTSTATUS	206	8	R
+      * CTLR		206	8	W
+      * wd_digin		207	9
+      */
+ 
+     /* trick ata_probe to not queue up interrupts since interupts 
+        are active now */
+     tmp=ata_attach_hook;
+     ata_attach_hook = 1;      
+ 
+     res = ata_probe(rman_get_start(port), 
+ 	rman_get_start(port) + ATA_ALTPORT_ONE_WINDOW, 0, dev, &lun);
+ 
+     /* restore hook */
+     ata_attach_hook = tmp;
+ 
+     bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
+ 
+     if (res) {
+ 	isa_set_portsize(dev, res);
+ 	*(int *)device_get_softc(dev) = lun;
+         atadevices[lun]->flags |= ATA_USE_16BIT;
+ 	return 0;
+     }
+     return ENXIO;
+ }
+ 
+ static int
+ ata_pccard_attach(dev)
+ 	device_t	dev;
+ {
+     struct ata_softc *sc = atadevices[*(int *)device_get_softc(dev)];
+     int status;
+     
+     /* Allocate the port range and interrupt */
+     sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid, 
+ 				      0, ~0, 1,	RF_ACTIVE);
+     if (!sc->port_res) {
+ 	/* XXX Need to free things ? */
+ 	return (ENOMEM);
+     }
+ 
+     sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid, 
+ 			     0, ~0, 1, RF_ACTIVE);
+     if (!sc->irq_res) {
+ 	/* XXX Need to free things ? */
+ 	bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid, sc->port_res);
+ 	return (ENOMEM);
+     }
+     status = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_BIO, ataintr, 
+ 			    atadevices[*(int *)device_get_softc(dev)], 
+ 			    &sc->irq_handle);
+ 
+     /* XXX The following really should just scan *THIS* device XXX */
+     /* XXX Also, we need to do more than just ad XXX */
+ 
+     if (status == 0) {
+         ata_attach(dev);
+     }
+     return status;
+ }
+ 
+ 
+ static int
+ ata_pccard_detach(dev)
+ 	device_t	dev;
+ {
+     struct ata_softc *sc = atadevices[*(int *)device_get_softc(dev)];
+ 
+     if (sc->gone) {
+ 		device_printf(dev,"already unloaded\n");
+ 		return(0);
+     }
+ 
+     sc->gone = 1;
+ 
+     bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
+ 
+     if (sc->port_res) {
+ 		bus_release_resource(dev, SYS_RES_IOPORT,
+ 				     sc->port_rid, sc->port_res);
+ 		sc->port_res = 0;
+     }
+     if (sc->irq_res) {
+ 		bus_release_resource(dev, SYS_RES_IRQ,
+ 				     sc->irq_rid, sc->irq_res);
+ 		sc->irq_res = 0;
+     }
+ 
+     atadevices[*(int *)device_get_softc(dev)]=NULL;
+ 
+     free(sc, M_DEVBUF);
+ 
+     device_printf(dev,"unloaded\n");
+     return (0);
+ }
+ 
+ 
+ static device_method_t ata_pccard_methods[] = {
+ 	/* Device interface */
+ 	DEVMETHOD(device_probe,		ata_pccard_probe),
+ 	DEVMETHOD(device_attach,	ata_pccard_attach),
+ 	DEVMETHOD(device_detach,	ata_pccard_detach),
+ 
+ 	{ 0, 0 }
+ };
+ 
+ static driver_t ata_pccard_driver = {
+ 	"ata",
+ 	ata_pccard_methods,
+ 	sizeof(int),
+ };
+ 
+ DRIVER_MODULE(ata, pccard, ata_pccard_driver, ata_devclass, 0, 0);
+ #endif (NCARD > 0)
+ 
  #if NPCI > 0
  static const char *
  ata_pcimatch(device_t dev)
***************
*** 655,661 ****
       * of non-exsistent devices and thereby long delays
       */
      for (ctlr=0; ctlr<MAXATA; ctlr++) {
! 	if (!atadevices[ctlr]) continue;
  	if (atadevices[ctlr]->devices & ATA_ATA_SLAVE)
  	    if (ata_getparam(atadevices[ctlr], ATA_SLAVE, ATA_C_ATA_IDENTIFY))
  		atadevices[ctlr]->devices &= ~ATA_ATA_SLAVE;
--- 817,824 ----
       * of non-exsistent devices and thereby long delays
       */
      for (ctlr=0; ctlr<MAXATA; ctlr++) {
! 	if (!atadevices[ctlr] || 
! 	    (atadevices[ctlr]->devices & ATA_PROBED)) continue;
  	if (atadevices[ctlr]->devices & ATA_ATA_SLAVE)
  	    if (ata_getparam(atadevices[ctlr], ATA_SLAVE, ATA_C_ATA_IDENTIFY))
  		atadevices[ctlr]->devices &= ~ATA_ATA_SLAVE;
***************
*** 673,679 ****
  #if NATADISK > 0
      /* now we know whats there, do the real attach, first the ATA disks */
      for (ctlr=0; ctlr<MAXATA; ctlr++) {
! 	if (!atadevices[ctlr]) continue;
  	if (atadevices[ctlr]->devices & ATA_ATA_MASTER)
  	    ad_attach(atadevices[ctlr], ATA_MASTER);
  	if (atadevices[ctlr]->devices & ATA_ATA_SLAVE)
--- 836,843 ----
  #if NATADISK > 0
      /* now we know whats there, do the real attach, first the ATA disks */
      for (ctlr=0; ctlr<MAXATA; ctlr++) {
! 	if (!atadevices[ctlr] || 
! 	    (atadevices[ctlr]->devices & ATA_PROBED)) continue;
  	if (atadevices[ctlr]->devices & ATA_ATA_MASTER)
  	    ad_attach(atadevices[ctlr], ATA_MASTER);
  	if (atadevices[ctlr]->devices & ATA_ATA_SLAVE)
***************
*** 683,695 ****
  #if NATAPICD > 0 || NATAPIFD > 0 || NATAPIST > 0
      /* then the atapi devices */
      for (ctlr=0; ctlr<MAXATA; ctlr++) {
! 	if (!atadevices[ctlr]) continue;
  	if (atadevices[ctlr]->devices & ATA_ATAPI_MASTER)
  	    atapi_attach(atadevices[ctlr], ATA_MASTER);
  	if (atadevices[ctlr]->devices & ATA_ATAPI_SLAVE)
  	    atapi_attach(atadevices[ctlr], ATA_SLAVE);
      }
  #endif
      if (ata_attach_hook) {
  	config_intrhook_disestablish(ata_attach_hook);
  	free(ata_attach_hook, M_ATA);
--- 847,865 ----
  #if NATAPICD > 0 || NATAPIFD > 0 || NATAPIST > 0
      /* then the atapi devices */
      for (ctlr=0; ctlr<MAXATA; ctlr++) {
! 	if (!atadevices[ctlr] || 
! 	    (atadevices[ctlr]->devices & ATA_PROBED)) continue;
  	if (atadevices[ctlr]->devices & ATA_ATAPI_MASTER)
  	    atapi_attach(atadevices[ctlr], ATA_MASTER);
  	if (atadevices[ctlr]->devices & ATA_ATAPI_SLAVE)
  	    atapi_attach(atadevices[ctlr], ATA_SLAVE);
      }
  #endif
+     /* mark all current controllers probed for devices */
+     for (ctlr=0; ctlr<MAXATA; ctlr++) {
+ 	if (!atadevices[ctlr]) continue; 
+ 	atadevices[ctlr]->devices |= ATA_PROBED;
+     }
      if (ata_attach_hook) {
  	config_intrhook_disestablish(ata_attach_hook);
  	free(ata_attach_hook, M_ATA);
Index: ata-all.h
===================================================================
RCS file: /cvs/freebsd/src/sys/dev/ata/ata-all.h,v
retrieving revision 1.23
diff -c -r1.23 ata-all.h
*** ata-all.h	2000/01/28 13:35:42	1.23
--- ata-all.h	2000/02/10 18:17:34
***************
*** 87,92 ****
--- 87,93 ----
  #define		ATA_S_BUSY		0x80	/* busy */
  
  #define ATA_ALTPORT			0x206	/* alternate Status register */
+ #define ATA_ALTPORT_ONE_WINDOW		0x08	/* Alternate port for pccard */
  #define		ATA_A_IDS		0x02	/* disable interrupts */
  #define		ATA_A_RESET		0x04	/* RESET controller */
  #define		ATA_A_4BIT		0x08	/* 4 head bits */
***************
*** 281,286 ****
--- 282,288 ----
  #define		ATA_ATA_SLAVE		0x02
  #define		ATA_ATAPI_MASTER	0x04
  #define		ATA_ATAPI_SLAVE		0x08
+ #define		ATA_PROBED		0x10
  
      u_int8_t			status;		/* last controller status */
      u_int8_t			error;		/* last controller error */
***************
*** 300,306 ****
  #if NAPM > 0
      struct apmhook 		resume_hook;	/* hook for apm */
  #endif
! 
  };
  
  /* array to hold all ata softc's */
--- 302,313 ----
  #if NAPM > 0
      struct apmhook 		resume_hook;	/* hook for apm */
  #endif
!     int	port_rid;	                       /* resource id for port range */
!     struct resource* port_res;                 /* resource for port range */
!     int	irq_rid;	                       /* resource id for irq */
!     struct resource* irq_res;                  /* resource for irq */
!     void*	irq_handle;	               /* handle for irq handler */
!     int gone;
  };
  
  /* array to hold all ata softc's */


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-mobile" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200002101827.KAA90609>