diff options
Diffstat (limited to 'drivers/scsi/pcmcia/fdomain_stub.c')
-rw-r--r-- | drivers/scsi/pcmcia/fdomain_stub.c | 155 |
1 files changed, 58 insertions, 97 deletions
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 788c58d805f3..85f7ffac19a0 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c | |||
@@ -73,57 +73,48 @@ static char *version = | |||
73 | /*====================================================================*/ | 73 | /*====================================================================*/ |
74 | 74 | ||
75 | typedef struct scsi_info_t { | 75 | typedef struct scsi_info_t { |
76 | dev_link_t link; | 76 | struct pcmcia_device *p_dev; |
77 | dev_node_t node; | 77 | dev_node_t node; |
78 | struct Scsi_Host *host; | 78 | struct Scsi_Host *host; |
79 | } scsi_info_t; | 79 | } scsi_info_t; |
80 | 80 | ||
81 | 81 | ||
82 | static void fdomain_release(dev_link_t *link); | 82 | static void fdomain_release(struct pcmcia_device *link); |
83 | static void fdomain_detach(struct pcmcia_device *p_dev); | 83 | static void fdomain_detach(struct pcmcia_device *p_dev); |
84 | static void fdomain_config(dev_link_t *link); | 84 | static int fdomain_config(struct pcmcia_device *link); |
85 | 85 | ||
86 | static int fdomain_attach(struct pcmcia_device *p_dev) | 86 | static int fdomain_probe(struct pcmcia_device *link) |
87 | { | 87 | { |
88 | scsi_info_t *info; | 88 | scsi_info_t *info; |
89 | dev_link_t *link; | 89 | |
90 | 90 | DEBUG(0, "fdomain_attach()\n"); | |
91 | DEBUG(0, "fdomain_attach()\n"); | 91 | |
92 | 92 | /* Create new SCSI device */ | |
93 | /* Create new SCSI device */ | 93 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
94 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 94 | if (!info) |
95 | if (!info) return -ENOMEM; | 95 | return -ENOMEM; |
96 | memset(info, 0, sizeof(*info)); | 96 | |
97 | link = &info->link; link->priv = info; | 97 | info->p_dev = link; |
98 | link->io.NumPorts1 = 0x10; | 98 | link->priv = info; |
99 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | 99 | link->io.NumPorts1 = 0x10; |
100 | link->io.IOAddrLines = 10; | 100 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; |
101 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 101 | link->io.IOAddrLines = 10; |
102 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 102 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
103 | link->conf.Attributes = CONF_ENABLE_IRQ; | 103 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
104 | link->conf.Vcc = 50; | 104 | link->conf.Attributes = CONF_ENABLE_IRQ; |
105 | link->conf.IntType = INT_MEMORY_AND_IO; | 105 | link->conf.IntType = INT_MEMORY_AND_IO; |
106 | link->conf.Present = PRESENT_OPTION; | 106 | link->conf.Present = PRESENT_OPTION; |
107 | 107 | ||
108 | link->handle = p_dev; | 108 | return fdomain_config(link); |
109 | p_dev->instance = link; | ||
110 | |||
111 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
112 | fdomain_config(link); | ||
113 | |||
114 | return 0; | ||
115 | } /* fdomain_attach */ | 109 | } /* fdomain_attach */ |
116 | 110 | ||
117 | /*====================================================================*/ | 111 | /*====================================================================*/ |
118 | 112 | ||
119 | static void fdomain_detach(struct pcmcia_device *p_dev) | 113 | static void fdomain_detach(struct pcmcia_device *link) |
120 | { | 114 | { |
121 | dev_link_t *link = dev_to_instance(p_dev); | ||
122 | |||
123 | DEBUG(0, "fdomain_detach(0x%p)\n", link); | 115 | DEBUG(0, "fdomain_detach(0x%p)\n", link); |
124 | 116 | ||
125 | if (link->state & DEV_CONFIG) | 117 | fdomain_release(link); |
126 | fdomain_release(link); | ||
127 | 118 | ||
128 | kfree(link->priv); | 119 | kfree(link->priv); |
129 | } /* fdomain_detach */ | 120 | } /* fdomain_detach */ |
@@ -133,9 +124,8 @@ static void fdomain_detach(struct pcmcia_device *p_dev) | |||
133 | #define CS_CHECK(fn, ret) \ | 124 | #define CS_CHECK(fn, ret) \ |
134 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 125 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
135 | 126 | ||
136 | static void fdomain_config(dev_link_t *link) | 127 | static int fdomain_config(struct pcmcia_device *link) |
137 | { | 128 | { |
138 | client_handle_t handle = link->handle; | ||
139 | scsi_info_t *info = link->priv; | 129 | scsi_info_t *info = link->priv; |
140 | tuple_t tuple; | 130 | tuple_t tuple; |
141 | cisparse_t parse; | 131 | cisparse_t parse; |
@@ -150,103 +140,75 @@ static void fdomain_config(dev_link_t *link) | |||
150 | tuple.TupleData = tuple_data; | 140 | tuple.TupleData = tuple_data; |
151 | tuple.TupleDataMax = 64; | 141 | tuple.TupleDataMax = 64; |
152 | tuple.TupleOffset = 0; | 142 | tuple.TupleOffset = 0; |
153 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 143 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
154 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 144 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
155 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 145 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
156 | link->conf.ConfigBase = parse.config.base; | 146 | link->conf.ConfigBase = parse.config.base; |
157 | 147 | ||
158 | /* Configure card */ | ||
159 | link->state |= DEV_CONFIG; | ||
160 | |||
161 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 148 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
162 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 149 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
163 | while (1) { | 150 | while (1) { |
164 | if (pcmcia_get_tuple_data(handle, &tuple) != 0 || | 151 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || |
165 | pcmcia_parse_tuple(handle, &tuple, &parse) != 0) | 152 | pcmcia_parse_tuple(link, &tuple, &parse) != 0) |
166 | goto next_entry; | 153 | goto next_entry; |
167 | link->conf.ConfigIndex = parse.cftable_entry.index; | 154 | link->conf.ConfigIndex = parse.cftable_entry.index; |
168 | link->io.BasePort1 = parse.cftable_entry.io.win[0].base; | 155 | link->io.BasePort1 = parse.cftable_entry.io.win[0].base; |
169 | i = pcmcia_request_io(handle, &link->io); | 156 | i = pcmcia_request_io(link, &link->io); |
170 | if (i == CS_SUCCESS) break; | 157 | if (i == CS_SUCCESS) break; |
171 | next_entry: | 158 | next_entry: |
172 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); | 159 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); |
173 | } | 160 | } |
174 | 161 | ||
175 | CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); | 162 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
176 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); | 163 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
177 | 164 | ||
178 | /* A bad hack... */ | 165 | /* A bad hack... */ |
179 | release_region(link->io.BasePort1, link->io.NumPorts1); | 166 | release_region(link->io.BasePort1, link->io.NumPorts1); |
180 | 167 | ||
181 | /* Set configuration options for the fdomain driver */ | 168 | /* Set configuration options for the fdomain driver */ |
182 | sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ); | 169 | sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ); |
183 | fdomain_setup(str); | 170 | fdomain_setup(str); |
184 | 171 | ||
185 | host = __fdomain_16x0_detect(&fdomain_driver_template); | 172 | host = __fdomain_16x0_detect(&fdomain_driver_template); |
186 | if (!host) { | 173 | if (!host) { |
187 | printk(KERN_INFO "fdomain_cs: no SCSI devices found\n"); | 174 | printk(KERN_INFO "fdomain_cs: no SCSI devices found\n"); |
188 | goto cs_failed; | 175 | goto cs_failed; |
189 | } | 176 | } |
190 | 177 | ||
191 | scsi_add_host(host, NULL); /* XXX handle failure */ | 178 | if (scsi_add_host(host, NULL)) |
179 | goto cs_failed; | ||
192 | scsi_scan_host(host); | 180 | scsi_scan_host(host); |
193 | 181 | ||
194 | sprintf(info->node.dev_name, "scsi%d", host->host_no); | 182 | sprintf(info->node.dev_name, "scsi%d", host->host_no); |
195 | link->dev = &info->node; | 183 | link->dev_node = &info->node; |
196 | info->host = host; | 184 | info->host = host; |
197 | 185 | ||
198 | link->state &= ~DEV_CONFIG_PENDING; | 186 | return 0; |
199 | return; | 187 | |
200 | |||
201 | cs_failed: | 188 | cs_failed: |
202 | cs_error(link->handle, last_fn, last_ret); | 189 | cs_error(link, last_fn, last_ret); |
203 | fdomain_release(link); | 190 | fdomain_release(link); |
204 | return; | 191 | return -ENODEV; |
205 | |||
206 | } /* fdomain_config */ | 192 | } /* fdomain_config */ |
207 | 193 | ||
208 | /*====================================================================*/ | 194 | /*====================================================================*/ |
209 | 195 | ||
210 | static void fdomain_release(dev_link_t *link) | 196 | static void fdomain_release(struct pcmcia_device *link) |
211 | { | 197 | { |
212 | scsi_info_t *info = link->priv; | 198 | scsi_info_t *info = link->priv; |
213 | 199 | ||
214 | DEBUG(0, "fdomain_release(0x%p)\n", link); | 200 | DEBUG(0, "fdomain_release(0x%p)\n", link); |
215 | 201 | ||
216 | scsi_remove_host(info->host); | 202 | scsi_remove_host(info->host); |
217 | link->dev = NULL; | 203 | pcmcia_disable_device(link); |
218 | 204 | scsi_unregister(info->host); | |
219 | pcmcia_release_configuration(link->handle); | ||
220 | pcmcia_release_io(link->handle, &link->io); | ||
221 | pcmcia_release_irq(link->handle, &link->irq); | ||
222 | |||
223 | scsi_unregister(info->host); | ||
224 | |||
225 | link->state &= ~DEV_CONFIG; | ||
226 | } | 205 | } |
227 | 206 | ||
228 | /*====================================================================*/ | 207 | /*====================================================================*/ |
229 | 208 | ||
230 | static int fdomain_suspend(struct pcmcia_device *dev) | 209 | static int fdomain_resume(struct pcmcia_device *link) |
231 | { | 210 | { |
232 | dev_link_t *link = dev_to_instance(dev); | 211 | fdomain_16x0_bus_reset(NULL); |
233 | |||
234 | link->state |= DEV_SUSPEND; | ||
235 | if (link->state & DEV_CONFIG) | ||
236 | pcmcia_release_configuration(link->handle); | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int fdomain_resume(struct pcmcia_device *dev) | ||
242 | { | ||
243 | dev_link_t *link = dev_to_instance(dev); | ||
244 | |||
245 | link->state &= ~DEV_SUSPEND; | ||
246 | if (link->state & DEV_CONFIG) { | ||
247 | pcmcia_request_configuration(link->handle, &link->conf); | ||
248 | fdomain_16x0_bus_reset(NULL); | ||
249 | } | ||
250 | 212 | ||
251 | return 0; | 213 | return 0; |
252 | } | 214 | } |
@@ -264,10 +226,9 @@ static struct pcmcia_driver fdomain_cs_driver = { | |||
264 | .drv = { | 226 | .drv = { |
265 | .name = "fdomain_cs", | 227 | .name = "fdomain_cs", |
266 | }, | 228 | }, |
267 | .probe = fdomain_attach, | 229 | .probe = fdomain_probe, |
268 | .remove = fdomain_detach, | 230 | .remove = fdomain_detach, |
269 | .id_table = fdomain_ids, | 231 | .id_table = fdomain_ids, |
270 | .suspend = fdomain_suspend, | ||
271 | .resume = fdomain_resume, | 232 | .resume = fdomain_resume, |
272 | }; | 233 | }; |
273 | 234 | ||