diff options
Diffstat (limited to 'drivers/scsi/pcmcia/nsp_cs.c')
-rw-r--r-- | drivers/scsi/pcmcia/nsp_cs.c | 167 |
1 files changed, 48 insertions, 119 deletions
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 050ea13ff80b..9e3ab3fd5355 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c | |||
@@ -104,9 +104,6 @@ static struct scsi_host_template nsp_driver_template = { | |||
104 | #endif | 104 | #endif |
105 | }; | 105 | }; |
106 | 106 | ||
107 | static dev_link_t *dev_list = NULL; | ||
108 | static dev_info_t dev_info = {"nsp_cs"}; | ||
109 | |||
110 | static nsp_hw_data nsp_data_base; /* attach <-> detect glue */ | 107 | static nsp_hw_data nsp_data_base; /* attach <-> detect glue */ |
111 | 108 | ||
112 | 109 | ||
@@ -1596,19 +1593,17 @@ static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt) | |||
1596 | configure the card at this point -- we wait until we receive a | 1593 | configure the card at this point -- we wait until we receive a |
1597 | card insertion event. | 1594 | card insertion event. |
1598 | ======================================================================*/ | 1595 | ======================================================================*/ |
1599 | static dev_link_t *nsp_cs_attach(void) | 1596 | static int nsp_cs_attach(struct pcmcia_device *p_dev) |
1600 | { | 1597 | { |
1601 | scsi_info_t *info; | 1598 | scsi_info_t *info; |
1602 | client_reg_t client_reg; | ||
1603 | dev_link_t *link; | 1599 | dev_link_t *link; |
1604 | int ret; | ||
1605 | nsp_hw_data *data = &nsp_data_base; | 1600 | nsp_hw_data *data = &nsp_data_base; |
1606 | 1601 | ||
1607 | nsp_dbg(NSP_DEBUG_INIT, "in"); | 1602 | nsp_dbg(NSP_DEBUG_INIT, "in"); |
1608 | 1603 | ||
1609 | /* Create new SCSI device */ | 1604 | /* Create new SCSI device */ |
1610 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 1605 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
1611 | if (info == NULL) { return NULL; } | 1606 | if (info == NULL) { return -ENOMEM; } |
1612 | memset(info, 0, sizeof(*info)); | 1607 | memset(info, 0, sizeof(*info)); |
1613 | link = &info->link; | 1608 | link = &info->link; |
1614 | link->priv = info; | 1609 | link->priv = info; |
@@ -1636,23 +1631,14 @@ static dev_link_t *nsp_cs_attach(void) | |||
1636 | link->conf.IntType = INT_MEMORY_AND_IO; | 1631 | link->conf.IntType = INT_MEMORY_AND_IO; |
1637 | link->conf.Present = PRESENT_OPTION; | 1632 | link->conf.Present = PRESENT_OPTION; |
1638 | 1633 | ||
1634 | link->handle = p_dev; | ||
1635 | p_dev->instance = link; | ||
1639 | 1636 | ||
1640 | /* Register with Card Services */ | 1637 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
1641 | link->next = dev_list; | 1638 | nsp_cs_config(link); |
1642 | dev_list = link; | ||
1643 | client_reg.dev_info = &dev_info; | ||
1644 | client_reg.Version = 0x0210; | ||
1645 | client_reg.event_callback_args.client_data = link; | ||
1646 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
1647 | if (ret != CS_SUCCESS) { | ||
1648 | cs_error(link->handle, RegisterClient, ret); | ||
1649 | nsp_cs_detach(link); | ||
1650 | return NULL; | ||
1651 | } | ||
1652 | |||
1653 | 1639 | ||
1654 | nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link); | 1640 | nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link); |
1655 | return link; | 1641 | return 0; |
1656 | } /* nsp_cs_attach */ | 1642 | } /* nsp_cs_attach */ |
1657 | 1643 | ||
1658 | 1644 | ||
@@ -1662,35 +1648,19 @@ static dev_link_t *nsp_cs_attach(void) | |||
1662 | structures are freed. Otherwise, the structures will be freed | 1648 | structures are freed. Otherwise, the structures will be freed |
1663 | when the device is released. | 1649 | when the device is released. |
1664 | ======================================================================*/ | 1650 | ======================================================================*/ |
1665 | static void nsp_cs_detach(dev_link_t *link) | 1651 | static void nsp_cs_detach(struct pcmcia_device *p_dev) |
1666 | { | 1652 | { |
1667 | dev_link_t **linkp; | 1653 | dev_link_t *link = dev_to_instance(p_dev); |
1668 | 1654 | ||
1669 | nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link); | 1655 | nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link); |
1670 | 1656 | ||
1671 | /* Locate device structure */ | 1657 | if (link->state & DEV_CONFIG) { |
1672 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) { | 1658 | ((scsi_info_t *)link->priv)->stop = 1; |
1673 | if (*linkp == link) { | ||
1674 | break; | ||
1675 | } | ||
1676 | } | ||
1677 | if (*linkp == NULL) { | ||
1678 | return; | ||
1679 | } | ||
1680 | |||
1681 | if (link->state & DEV_CONFIG) | ||
1682 | nsp_cs_release(link); | 1659 | nsp_cs_release(link); |
1683 | |||
1684 | /* Break the link with Card Services */ | ||
1685 | if (link->handle) { | ||
1686 | pcmcia_deregister_client(link->handle); | ||
1687 | } | 1660 | } |
1688 | 1661 | ||
1689 | /* Unlink device structure, free bits */ | ||
1690 | *linkp = link->next; | ||
1691 | kfree(link->priv); | 1662 | kfree(link->priv); |
1692 | link->priv = NULL; | 1663 | link->priv = NULL; |
1693 | |||
1694 | } /* nsp_cs_detach */ | 1664 | } /* nsp_cs_detach */ |
1695 | 1665 | ||
1696 | 1666 | ||
@@ -2021,99 +1991,58 @@ static void nsp_cs_release(dev_link_t *link) | |||
2021 | #endif | 1991 | #endif |
2022 | } /* nsp_cs_release */ | 1992 | } /* nsp_cs_release */ |
2023 | 1993 | ||
2024 | /*====================================================================== | 1994 | static int nsp_cs_suspend(struct pcmcia_device *dev) |
2025 | |||
2026 | The card status event handler. Mostly, this schedules other | ||
2027 | stuff to run after an event is received. A CARD_REMOVAL event | ||
2028 | also sets some flags to discourage the net drivers from trying | ||
2029 | to talk to the card any more. | ||
2030 | |||
2031 | When a CARD_REMOVAL event is received, we immediately set a flag | ||
2032 | to block future accesses to this device. All the functions that | ||
2033 | actually access the device should check this flag to make sure | ||
2034 | the card is still present. | ||
2035 | |||
2036 | ======================================================================*/ | ||
2037 | static int nsp_cs_event(event_t event, | ||
2038 | int priority, | ||
2039 | event_callback_args_t *args) | ||
2040 | { | 1995 | { |
2041 | dev_link_t *link = args->client_data; | 1996 | dev_link_t *link = dev_to_instance(dev); |
2042 | scsi_info_t *info = link->priv; | 1997 | scsi_info_t *info = link->priv; |
2043 | nsp_hw_data *data; | 1998 | nsp_hw_data *data; |
2044 | 1999 | ||
2045 | nsp_dbg(NSP_DEBUG_INIT, "in, event=0x%08x", event); | 2000 | link->state |= DEV_SUSPEND; |
2046 | 2001 | ||
2047 | switch (event) { | 2002 | nsp_dbg(NSP_DEBUG_INIT, "event: suspend"); |
2048 | case CS_EVENT_CARD_REMOVAL: | ||
2049 | nsp_dbg(NSP_DEBUG_INIT, "event: remove"); | ||
2050 | link->state &= ~DEV_PRESENT; | ||
2051 | if (link->state & DEV_CONFIG) { | ||
2052 | ((scsi_info_t *)link->priv)->stop = 1; | ||
2053 | nsp_cs_release(link); | ||
2054 | } | ||
2055 | break; | ||
2056 | 2003 | ||
2057 | case CS_EVENT_CARD_INSERTION: | 2004 | if (info->host != NULL) { |
2058 | nsp_dbg(NSP_DEBUG_INIT, "event: insert"); | 2005 | nsp_msg(KERN_INFO, "clear SDTR status"); |
2059 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
2060 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68)) | ||
2061 | info->bus = args->bus; | ||
2062 | #endif | ||
2063 | nsp_cs_config(link); | ||
2064 | break; | ||
2065 | 2006 | ||
2066 | case CS_EVENT_PM_SUSPEND: | 2007 | data = (nsp_hw_data *)info->host->hostdata; |
2067 | nsp_dbg(NSP_DEBUG_INIT, "event: suspend"); | ||
2068 | link->state |= DEV_SUSPEND; | ||
2069 | /* Fall through... */ | ||
2070 | case CS_EVENT_RESET_PHYSICAL: | ||
2071 | /* Mark the device as stopped, to block IO until later */ | ||
2072 | nsp_dbg(NSP_DEBUG_INIT, "event: reset physical"); | ||
2073 | 2008 | ||
2074 | if (info->host != NULL) { | 2009 | nsphw_init_sync(data); |
2075 | nsp_msg(KERN_INFO, "clear SDTR status"); | 2010 | } |
2076 | 2011 | ||
2077 | data = (nsp_hw_data *)info->host->hostdata; | 2012 | info->stop = 1; |
2078 | 2013 | ||
2079 | nsphw_init_sync(data); | 2014 | if (link->state & DEV_CONFIG) |
2080 | } | 2015 | pcmcia_release_configuration(link->handle); |
2081 | 2016 | ||
2082 | info->stop = 1; | 2017 | return 0; |
2083 | if (link->state & DEV_CONFIG) { | 2018 | } |
2084 | pcmcia_release_configuration(link->handle); | ||
2085 | } | ||
2086 | break; | ||
2087 | 2019 | ||
2088 | case CS_EVENT_PM_RESUME: | 2020 | static int nsp_cs_resume(struct pcmcia_device *dev) |
2089 | nsp_dbg(NSP_DEBUG_INIT, "event: resume"); | 2021 | { |
2090 | link->state &= ~DEV_SUSPEND; | 2022 | dev_link_t *link = dev_to_instance(dev); |
2091 | /* Fall through... */ | 2023 | scsi_info_t *info = link->priv; |
2092 | case CS_EVENT_CARD_RESET: | 2024 | nsp_hw_data *data; |
2093 | nsp_dbg(NSP_DEBUG_INIT, "event: reset"); | ||
2094 | if (link->state & DEV_CONFIG) { | ||
2095 | pcmcia_request_configuration(link->handle, &link->conf); | ||
2096 | } | ||
2097 | info->stop = 0; | ||
2098 | 2025 | ||
2099 | if (info->host != NULL) { | 2026 | nsp_dbg(NSP_DEBUG_INIT, "event: resume"); |
2100 | nsp_msg(KERN_INFO, "reset host and bus"); | ||
2101 | 2027 | ||
2102 | data = (nsp_hw_data *)info->host->hostdata; | 2028 | link->state &= ~DEV_SUSPEND; |
2103 | 2029 | ||
2104 | nsphw_init (data); | 2030 | if (link->state & DEV_CONFIG) |
2105 | nsp_bus_reset(data); | 2031 | pcmcia_request_configuration(link->handle, &link->conf); |
2106 | } | ||
2107 | 2032 | ||
2108 | break; | 2033 | info->stop = 0; |
2109 | 2034 | ||
2110 | default: | 2035 | if (info->host != NULL) { |
2111 | nsp_dbg(NSP_DEBUG_INIT, "event: unknown"); | 2036 | nsp_msg(KERN_INFO, "reset host and bus"); |
2112 | break; | 2037 | |
2038 | data = (nsp_hw_data *)info->host->hostdata; | ||
2039 | |||
2040 | nsphw_init (data); | ||
2041 | nsp_bus_reset(data); | ||
2113 | } | 2042 | } |
2114 | nsp_dbg(NSP_DEBUG_INIT, "end"); | 2043 | |
2115 | return 0; | 2044 | return 0; |
2116 | } /* nsp_cs_event */ | 2045 | } |
2117 | 2046 | ||
2118 | /*======================================================================* | 2047 | /*======================================================================* |
2119 | * module entry point | 2048 | * module entry point |
@@ -2136,10 +2065,11 @@ static struct pcmcia_driver nsp_driver = { | |||
2136 | .drv = { | 2065 | .drv = { |
2137 | .name = "nsp_cs", | 2066 | .name = "nsp_cs", |
2138 | }, | 2067 | }, |
2139 | .attach = nsp_cs_attach, | 2068 | .probe = nsp_cs_attach, |
2140 | .event = nsp_cs_event, | 2069 | .remove = nsp_cs_detach, |
2141 | .detach = nsp_cs_detach, | ||
2142 | .id_table = nsp_cs_ids, | 2070 | .id_table = nsp_cs_ids, |
2071 | .suspend = nsp_cs_suspend, | ||
2072 | .resume = nsp_cs_resume, | ||
2143 | }; | 2073 | }; |
2144 | #endif | 2074 | #endif |
2145 | 2075 | ||
@@ -2171,7 +2101,6 @@ static void __exit nsp_cs_exit(void) | |||
2171 | 2101 | ||
2172 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) | 2102 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) |
2173 | pcmcia_unregister_driver(&nsp_driver); | 2103 | pcmcia_unregister_driver(&nsp_driver); |
2174 | BUG_ON(dev_list != NULL); | ||
2175 | #else | 2104 | #else |
2176 | unregister_pcmcia_driver(&dev_info); | 2105 | unregister_pcmcia_driver(&dev_info); |
2177 | /* XXX: this really needs to move into generic code.. */ | 2106 | /* XXX: this really needs to move into generic code.. */ |