diff options
Diffstat (limited to 'drivers/scsi/a100u2w.c')
-rw-r--r-- | drivers/scsi/a100u2w.c | 1239 |
1 files changed, 636 insertions, 603 deletions
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index 7f4241bfb9c..f608d4a1d6d 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c | |||
@@ -19,27 +19,6 @@ | |||
19 | * along with this program; see the file COPYING. If not, write to | 19 | * along with this program; see the file COPYING. If not, write to |
20 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | 20 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | * | 21 | * |
22 | * -------------------------------------------------------------------------- | ||
23 | * | ||
24 | * Redistribution and use in source and binary forms, with or without | ||
25 | * modification, are permitted provided that the following conditions | ||
26 | * are met: | ||
27 | * 1. Redistributions of source code must retain the above copyright | ||
28 | * notice, this list of conditions, and the following disclaimer, | ||
29 | * without modification, immediately at the beginning of the file. | ||
30 | * 2. Redistributions in binary form must reproduce the above copyright | ||
31 | * notice, this list of conditions and the following disclaimer in the | ||
32 | * documentation and/or other materials provided with the distribution. | ||
33 | * 3. The name of the author may not be used to endorse or promote products | ||
34 | * derived from this software without specific prior written permission. | ||
35 | * | ||
36 | * Where this Software is combined with software released under the terms of | ||
37 | * the GNU General Public License ("GPL") and the terms of the GPL would require the | ||
38 | * combined work to also be released under the terms of the GPL, the terms | ||
39 | * and conditions of this License will apply in addition to those of the | ||
40 | * GPL with the exception of any terms or conditions of this License that | ||
41 | * conflict with, or are expressly prohibited by, the GPL. | ||
42 | * | ||
43 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
44 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
45 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
@@ -75,6 +54,8 @@ | |||
75 | * 9/28/04 Christoph Hellwig <hch@lst.de> | 54 | * 9/28/04 Christoph Hellwig <hch@lst.de> |
76 | * - merge the two source files | 55 | * - merge the two source files |
77 | * - remove internal queueing code | 56 | * - remove internal queueing code |
57 | * 14/06/07 Alan Cox <alan@redhat.com> | ||
58 | * - Grand cleanup and Linuxisation | ||
78 | */ | 59 | */ |
79 | 60 | ||
80 | #include <linux/module.h> | 61 | #include <linux/module.h> |
@@ -102,14 +83,12 @@ | |||
102 | #include "a100u2w.h" | 83 | #include "a100u2w.h" |
103 | 84 | ||
104 | 85 | ||
105 | #define JIFFIES_TO_MS(t) ((t) * 1000 / HZ) | 86 | static struct orc_scb *__orc_alloc_scb(struct orc_host * host); |
106 | #define MS_TO_JIFFIES(j) ((j * HZ) / 1000) | 87 | static void inia100_scb_handler(struct orc_host *host, struct orc_scb *scb); |
107 | 88 | ||
108 | static ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp); | 89 | static struct orc_nvram nvram, *nvramp = &nvram; |
109 | static void inia100SCBPost(BYTE * pHcb, BYTE * pScb); | ||
110 | 90 | ||
111 | static NVRAM nvram, *nvramp = &nvram; | 91 | static u8 default_nvram[64] = |
112 | static UCHAR dftNvRam[64] = | ||
113 | { | 92 | { |
114 | /*----------header -------------*/ | 93 | /*----------header -------------*/ |
115 | 0x01, /* 0x00: Sub System Vendor ID 0 */ | 94 | 0x01, /* 0x00: Sub System Vendor ID 0 */ |
@@ -158,823 +137,882 @@ static UCHAR dftNvRam[64] = | |||
158 | }; | 137 | }; |
159 | 138 | ||
160 | 139 | ||
161 | /***************************************************************************/ | 140 | static u8 wait_chip_ready(struct orc_host * host) |
162 | static void waitForPause(unsigned amount) | ||
163 | { | ||
164 | ULONG the_time = jiffies + MS_TO_JIFFIES(amount); | ||
165 | while (time_before_eq(jiffies, the_time)) | ||
166 | cpu_relax(); | ||
167 | } | ||
168 | |||
169 | /***************************************************************************/ | ||
170 | static UCHAR waitChipReady(ORC_HCS * hcsp) | ||
171 | { | 141 | { |
172 | int i; | 142 | int i; |
173 | 143 | ||
174 | for (i = 0; i < 10; i++) { /* Wait 1 second for report timeout */ | 144 | for (i = 0; i < 10; i++) { /* Wait 1 second for report timeout */ |
175 | if (ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HOSTSTOP) /* Wait HOSTSTOP set */ | 145 | if (inb(host->base + ORC_HCTRL) & HOSTSTOP) /* Wait HOSTSTOP set */ |
176 | return 1; | 146 | return 1; |
177 | waitForPause(100); /* wait 100ms before try again */ | 147 | mdelay(100); |
178 | } | 148 | } |
179 | return 0; | 149 | return 0; |
180 | } | 150 | } |
181 | 151 | ||
182 | /***************************************************************************/ | 152 | static u8 wait_firmware_ready(struct orc_host * host) |
183 | static UCHAR waitFWReady(ORC_HCS * hcsp) | ||
184 | { | 153 | { |
185 | int i; | 154 | int i; |
186 | 155 | ||
187 | for (i = 0; i < 10; i++) { /* Wait 1 second for report timeout */ | 156 | for (i = 0; i < 10; i++) { /* Wait 1 second for report timeout */ |
188 | if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY) /* Wait READY set */ | 157 | if (inb(host->base + ORC_HSTUS) & RREADY) /* Wait READY set */ |
189 | return 1; | 158 | return 1; |
190 | waitForPause(100); /* wait 100ms before try again */ | 159 | mdelay(100); /* wait 100ms before try again */ |
191 | } | 160 | } |
192 | return 0; | 161 | return 0; |
193 | } | 162 | } |
194 | 163 | ||
195 | /***************************************************************************/ | 164 | /***************************************************************************/ |
196 | static UCHAR waitSCSIRSTdone(ORC_HCS * hcsp) | 165 | static u8 wait_scsi_reset_done(struct orc_host * host) |
197 | { | 166 | { |
198 | int i; | 167 | int i; |
199 | 168 | ||
200 | for (i = 0; i < 10; i++) { /* Wait 1 second for report timeout */ | 169 | for (i = 0; i < 10; i++) { /* Wait 1 second for report timeout */ |
201 | if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & SCSIRST)) /* Wait SCSIRST done */ | 170 | if (!(inb(host->base + ORC_HCTRL) & SCSIRST)) /* Wait SCSIRST done */ |
202 | return 1; | 171 | return 1; |
203 | waitForPause(100); /* wait 100ms before try again */ | 172 | mdelay(100); /* wait 100ms before try again */ |
204 | } | 173 | } |
205 | return 0; | 174 | return 0; |
206 | } | 175 | } |
207 | 176 | ||
208 | /***************************************************************************/ | 177 | /***************************************************************************/ |
209 | static UCHAR waitHDOoff(ORC_HCS * hcsp) | 178 | static u8 wait_HDO_off(struct orc_host * host) |
210 | { | 179 | { |
211 | int i; | 180 | int i; |
212 | 181 | ||
213 | for (i = 0; i < 10; i++) { /* Wait 1 second for report timeout */ | 182 | for (i = 0; i < 10; i++) { /* Wait 1 second for report timeout */ |
214 | if (!(ORC_RD(hcsp->HCS_Base, ORC_HCTRL) & HDO)) /* Wait HDO off */ | 183 | if (!(inb(host->base + ORC_HCTRL) & HDO)) /* Wait HDO off */ |
215 | return 1; | 184 | return 1; |
216 | waitForPause(100); /* wait 100ms before try again */ | 185 | mdelay(100); /* wait 100ms before try again */ |
217 | } | 186 | } |
218 | return 0; | 187 | return 0; |
219 | } | 188 | } |
220 | 189 | ||
221 | /***************************************************************************/ | 190 | /***************************************************************************/ |
222 | static UCHAR waitHDIset(ORC_HCS * hcsp, UCHAR * pData) | 191 | static u8 wait_hdi_set(struct orc_host * host, u8 * data) |
223 | { | 192 | { |
224 | int i; | 193 | int i; |
225 | 194 | ||
226 | for (i = 0; i < 10; i++) { /* Wait 1 second for report timeout */ | 195 | for (i = 0; i < 10; i++) { /* Wait 1 second for report timeout */ |
227 | if ((*pData = ORC_RD(hcsp->HCS_Base, ORC_HSTUS)) & HDI) | 196 | if ((*data = inb(host->base + ORC_HSTUS)) & HDI) |
228 | return 1; /* Wait HDI set */ | 197 | return 1; /* Wait HDI set */ |
229 | waitForPause(100); /* wait 100ms before try again */ | 198 | mdelay(100); /* wait 100ms before try again */ |
230 | } | 199 | } |
231 | return 0; | 200 | return 0; |
232 | } | 201 | } |
233 | 202 | ||
234 | /***************************************************************************/ | 203 | /***************************************************************************/ |
235 | static unsigned short get_FW_version(ORC_HCS * hcsp) | 204 | static unsigned short orc_read_fwrev(struct orc_host * host) |
236 | { | 205 | { |
237 | UCHAR bData; | 206 | u16 version; |
238 | union { | 207 | u8 data; |
239 | unsigned short sVersion; | 208 | |
240 | unsigned char cVersion[2]; | 209 | outb(ORC_CMD_VERSION, host->base + ORC_HDATA); |
241 | } Version; | 210 | outb(HDO, host->base + ORC_HCTRL); |
242 | 211 | if (wait_HDO_off(host) == 0) /* Wait HDO off */ | |
243 | ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_VERSION); | ||
244 | ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); | ||
245 | if (waitHDOoff(hcsp) == 0) /* Wait HDO off */ | ||
246 | return 0; | 212 | return 0; |
247 | 213 | ||
248 | if (waitHDIset(hcsp, &bData) == 0) /* Wait HDI set */ | 214 | if (wait_hdi_set(host, &data) == 0) /* Wait HDI set */ |
249 | return 0; | 215 | return 0; |
250 | Version.cVersion[0] = ORC_RD(hcsp->HCS_Base, ORC_HDATA); | 216 | version = inb(host->base + ORC_HDATA); |
251 | ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */ | 217 | outb(data, host->base + ORC_HSTUS); /* Clear HDI */ |
252 | 218 | ||
253 | if (waitHDIset(hcsp, &bData) == 0) /* Wait HDI set */ | 219 | if (wait_hdi_set(host, &data) == 0) /* Wait HDI set */ |
254 | return 0; | 220 | return 0; |
255 | Version.cVersion[1] = ORC_RD(hcsp->HCS_Base, ORC_HDATA); | 221 | version |= inb(host->base + ORC_HDATA) << 8; |
256 | ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */ | 222 | outb(data, host->base + ORC_HSTUS); /* Clear HDI */ |
257 | 223 | ||
258 | return (Version.sVersion); | 224 | return version; |
259 | } | 225 | } |
260 | 226 | ||
261 | /***************************************************************************/ | 227 | /***************************************************************************/ |
262 | static UCHAR set_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char value) | 228 | static u8 orc_nv_write(struct orc_host * host, unsigned char address, unsigned char value) |
263 | { | 229 | { |
264 | ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_SET_NVM); /* Write command */ | 230 | outb(ORC_CMD_SET_NVM, host->base + ORC_HDATA); /* Write command */ |
265 | ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); | 231 | outb(HDO, host->base + ORC_HCTRL); |
266 | if (waitHDOoff(hcsp) == 0) /* Wait HDO off */ | 232 | if (wait_HDO_off(host) == 0) /* Wait HDO off */ |
267 | return 0; | 233 | return 0; |
268 | 234 | ||
269 | ORC_WR(hcsp->HCS_Base + ORC_HDATA, address); /* Write address */ | 235 | outb(address, host->base + ORC_HDATA); /* Write address */ |
270 | ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); | 236 | outb(HDO, host->base + ORC_HCTRL); |
271 | if (waitHDOoff(hcsp) == 0) /* Wait HDO off */ | 237 | if (wait_HDO_off(host) == 0) /* Wait HDO off */ |
272 | return 0; | 238 | return 0; |
273 | 239 | ||
274 | ORC_WR(hcsp->HCS_Base + ORC_HDATA, value); /* Write value */ | 240 | outb(value, host->base + ORC_HDATA); /* Write value */ |
275 | ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); | 241 | outb(HDO, host->base + ORC_HCTRL); |
276 | if (waitHDOoff(hcsp) == 0) /* Wait HDO off */ | 242 | if (wait_HDO_off(host) == 0) /* Wait HDO off */ |
277 | return 0; | 243 | return 0; |
278 | 244 | ||
279 | return 1; | 245 | return 1; |
280 | } | 246 | } |
281 | 247 | ||
282 | /***************************************************************************/ | 248 | /***************************************************************************/ |
283 | static UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn) | 249 | static u8 orc_nv_read(struct orc_host * host, u8 address, u8 *ptr) |
284 | { | 250 | { |
285 | unsigned char bData; | 251 | unsigned char data; |
286 | 252 | ||
287 | ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_GET_NVM); /* Write command */ | 253 | outb(ORC_CMD_GET_NVM, host->base + ORC_HDATA); /* Write command */ |
288 | ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); | 254 | outb(HDO, host->base + ORC_HCTRL); |
289 | if (waitHDOoff(hcsp) == 0) /* Wait HDO off */ | 255 | if (wait_HDO_off(host) == 0) /* Wait HDO off */ |
290 | return 0; | 256 | return 0; |
291 | 257 | ||
292 | ORC_WR(hcsp->HCS_Base + ORC_HDATA, address); /* Write address */ | 258 | outb(address, host->base + ORC_HDATA); /* Write address */ |
293 | ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); | 259 | outb(HDO, host->base + ORC_HCTRL); |
294 | if (waitHDOoff(hcsp) == 0) /* Wait HDO off */ | 260 | if (wait_HDO_off(host) == 0) /* Wait HDO off */ |
295 | return 0; | 261 | return 0; |
296 | 262 | ||
297 | if (waitHDIset(hcsp, &bData) == 0) /* Wait HDI set */ | 263 | if (wait_hdi_set(host, &data) == 0) /* Wait HDI set */ |
298 | return 0; | 264 | return 0; |
299 | *pDataIn = ORC_RD(hcsp->HCS_Base, ORC_HDATA); | 265 | *ptr = inb(host->base + ORC_HDATA); |
300 | ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */ | 266 | outb(data, host->base + ORC_HSTUS); /* Clear HDI */ |
301 | 267 | ||
302 | return 1; | 268 | return 1; |
269 | |||
303 | } | 270 | } |
304 | 271 | ||
305 | /***************************************************************************/ | 272 | /** |
306 | static void orc_exec_scb(ORC_HCS * hcsp, ORC_SCB * scbp) | 273 | * orc_exec_sb - Queue an SCB with the HA |
274 | * @host: host adapter the SCB belongs to | ||
275 | * @scb: SCB to queue for execution | ||
276 | */ | ||
277 | |||
278 | static void orc_exec_scb(struct orc_host * host, struct orc_scb * scb) | ||
307 | { | 279 | { |
308 | scbp->SCB_Status = ORCSCB_POST; | 280 | scb->status = ORCSCB_POST; |
309 | ORC_WR(hcsp->HCS_Base + ORC_PQUEUE, scbp->SCB_ScbIdx); | 281 | outb(scb->scbidx, host->base + ORC_PQUEUE); |
310 | return; | ||
311 | } | 282 | } |
312 | 283 | ||
313 | 284 | ||
314 | /*********************************************************************** | 285 | /** |
315 | Read SCSI H/A configuration parameters from serial EEPROM | 286 | * se2_rd_all - read SCSI parameters from EEPROM |
316 | ************************************************************************/ | 287 | * @host: Host whose EEPROM is being loaded |
317 | static int se2_rd_all(ORC_HCS * hcsp) | 288 | * |
289 | * Read SCSI H/A configuration parameters from serial EEPROM | ||
290 | */ | ||
291 | |||
292 | static int se2_rd_all(struct orc_host * host) | ||
318 | { | 293 | { |
319 | int i; | 294 | int i; |
320 | UCHAR *np, chksum = 0; | 295 | u8 *np, chksum = 0; |
321 | 296 | ||
322 | np = (UCHAR *) nvramp; | 297 | np = (u8 *) nvramp; |
323 | for (i = 0; i < 64; i++, np++) { /* <01> */ | 298 | for (i = 0; i < 64; i++, np++) { /* <01> */ |
324 | if (get_NVRAM(hcsp, (unsigned char) i, np) == 0) | 299 | if (orc_nv_read(host, (u8) i, np) == 0) |
325 | return -1; | 300 | return -1; |
326 | // *np++ = get_NVRAM(hcsp, (unsigned char ) i); | ||
327 | } | 301 | } |
328 | 302 | ||
329 | /*------ Is ckecksum ok ? ------*/ | 303 | /*------ Is ckecksum ok ? ------*/ |
330 | np = (UCHAR *) nvramp; | 304 | np = (u8 *) nvramp; |
331 | for (i = 0; i < 63; i++) | 305 | for (i = 0; i < 63; i++) |
332 | chksum += *np++; | 306 | chksum += *np++; |
333 | 307 | ||
334 | if (nvramp->CheckSum != (UCHAR) chksum) | 308 | if (nvramp->CheckSum != (u8) chksum) |
335 | return -1; | 309 | return -1; |
336 | return 1; | 310 | return 1; |
337 | } | 311 | } |
338 | 312 | ||
339 | /************************************************************************ | 313 | /** |
340 | Update SCSI H/A configuration parameters from serial EEPROM | 314 | * se2_update_all - update the EEPROM |
341 | *************************************************************************/ | 315 | * @host: Host whose EEPROM is being updated |
342 | static void se2_update_all(ORC_HCS * hcsp) | 316 | * |
317 | * Update changed bytes in the EEPROM image. | ||
318 | */ | ||
319 | |||
320 | static void se2_update_all(struct orc_host * host) | ||
343 | { /* setup default pattern */ | 321 | { /* setup default pattern */ |
344 | int i; | 322 | int i; |
345 | UCHAR *np, *np1, chksum = 0; | 323 | u8 *np, *np1, chksum = 0; |
346 | 324 | ||
347 | /* Calculate checksum first */ | 325 | /* Calculate checksum first */ |
348 | np = (UCHAR *) dftNvRam; | 326 | np = (u8 *) default_nvram; |
349 | for (i = 0; i < 63; i++) | 327 | for (i = 0; i < 63; i++) |
350 | chksum += *np++; | 328 | chksum += *np++; |
351 | *np = chksum; | 329 | *np = chksum; |
352 | 330 | ||
353 | np = (UCHAR *) dftNvRam; | 331 | np = (u8 *) default_nvram; |
354 | np1 = (UCHAR *) nvramp; | 332 | np1 = (u8 *) nvramp; |
355 | for (i = 0; i < 64; i++, np++, np1++) { | 333 | for (i = 0; i < 64; i++, np++, np1++) { |
356 | if (*np != *np1) { | 334 | if (*np != *np1) |
357 | set_NVRAM(hcsp, (unsigned char) i, *np); | 335 | orc_nv_write(host, (u8) i, *np); |
358 | } | ||
359 | } | 336 | } |
360 | return; | ||
361 | } | 337 | } |
362 | 338 | ||
363 | /************************************************************************* | 339 | /** |
364 | Function name : read_eeprom | 340 | * read_eeprom - load EEPROM |
365 | **************************************************************************/ | 341 | * @host: Host EEPROM to read |
366 | static void read_eeprom(ORC_HCS * hcsp) | 342 | * |
343 | * Read the EEPROM for a given host. If it is invalid or fails | ||
344 | * the restore the defaults and use them. | ||
345 | */ | ||
346 | |||
347 | static void read_eeprom(struct orc_host * host) | ||
367 | { | 348 | { |
368 | if (se2_rd_all(hcsp) != 1) { | 349 | if (se2_rd_all(host) != 1) { |
369 | se2_update_all(hcsp); /* setup default pattern */ | 350 | se2_update_all(host); /* setup default pattern */ |
370 | se2_rd_all(hcsp); /* load again */ | 351 | se2_rd_all(host); /* load again */ |
371 | } | 352 | } |
372 | } | 353 | } |
373 | 354 | ||
374 | 355 | ||
375 | /***************************************************************************/ | 356 | /** |
376 | static UCHAR load_FW(ORC_HCS * hcsp) | 357 | * orc_load_firmware - initialise firmware |
358 | * @host: Host to set up | ||
359 | * | ||
360 | * Load the firmware from the EEPROM into controller SRAM. This | ||
361 | * is basically a 4K block copy and then a 4K block read to check | ||
362 | * correctness. The rest is convulted by the indirect interfaces | ||
363 | * in the hardware | ||
364 | */ | ||
365 | |||
366 | static u8 orc_load_firmware(struct orc_host * host) | ||
377 | { | 367 | { |
378 | U32 dData; | 368 | u32 data32; |
379 | USHORT wBIOSAddress; | 369 | u16 bios_addr; |
380 | USHORT i; | 370 | u16 i; |
381 | UCHAR *pData, bData; | 371 | u8 *data32_ptr, data; |
382 | 372 | ||
383 | 373 | ||
384 | bData = ORC_RD(hcsp->HCS_Base, ORC_GCFG); | 374 | /* Set up the EEPROM for access */ |
385 | ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData | EEPRG); /* Enable EEPROM programming */ | 375 | |
386 | ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, 0x00); | 376 | data = inb(host->base + ORC_GCFG); |
387 | ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x00); | 377 | outb(data | EEPRG, host->base + ORC_GCFG); /* Enable EEPROM programming */ |
388 | if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0x55) { | 378 | outb(0x00, host->base + ORC_EBIOSADR2); |
389 | ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /* Disable EEPROM programming */ | 379 | outw(0x0000, host->base + ORC_EBIOSADR0); |
380 | if (inb(host->base + ORC_EBIOSDATA) != 0x55) { | ||
381 | outb(data, host->base + ORC_GCFG); /* Disable EEPROM programming */ | ||
390 | return 0; | 382 | return 0; |
391 | } | 383 | } |
392 | ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x01); | 384 | outw(0x0001, host->base + ORC_EBIOSADR0); |
393 | if (ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA) != 0xAA) { | 385 | if (inb(host->base + ORC_EBIOSDATA) != 0xAA) { |
394 | ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /* Disable EEPROM programming */ | 386 | outb(data, host->base + ORC_GCFG); /* Disable EEPROM programming */ |
395 | return 0; | 387 | return 0; |
396 | } | 388 | } |
397 | ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD); /* Enable SRAM programming */ | 389 | |
398 | pData = (UCHAR *) & dData; | 390 | outb(PRGMRST | DOWNLOAD, host->base + ORC_RISCCTL); /* Enable SRAM programming */ |
399 | dData = 0; /* Initial FW address to 0 */ | 391 | data32_ptr = (u8 *) & data32; |
400 | ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x10); | 392 | data32 = 0; /* Initial FW address to 0 */ |
401 | *pData = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */ | 393 | outw(0x0010, host->base + ORC_EBIOSADR0); |
402 | ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x11); | 394 | *data32_ptr = inb(host->base + ORC_EBIOSDATA); /* Read from BIOS */ |
403 | *(pData + 1) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */ | 395 | outw(0x0011, host->base + ORC_EBIOSADR0); |
404 | ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, 0x12); | 396 | *(data32_ptr + 1) = inb(host->base + ORC_EBIOSDATA); /* Read from BIOS */ |
405 | *(pData + 2) = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */ | 397 | outw(0x0012, host->base + ORC_EBIOSADR0); |
406 | ORC_WR(hcsp->HCS_Base + ORC_EBIOSADR2, *(pData + 2)); | 398 | *(data32_ptr + 2) = inb(host->base + ORC_EBIOSDATA); /* Read from BIOS */ |
407 | ORC_WRLONG(hcsp->HCS_Base + ORC_FWBASEADR, dData); /* Write FW address */ | 399 | outw(*(data32_ptr + 2), host->base + ORC_EBIOSADR2); |
408 | 400 | outl(data32, host->base + ORC_FWBASEADR); /* Write FW address */ | |
409 | wBIOSAddress = (USHORT) dData; /* FW code locate at BIOS address + ? */ | 401 | |
410 | for (i = 0, pData = (UCHAR *) & dData; /* Download the code */ | 402 | /* Copy the code from the BIOS to the SRAM */ |
403 | |||
404 | bios_addr = (u16) data32; /* FW code locate at BIOS address + ? */ | ||
405 | for (i = 0, data32_ptr = (u8 *) & data32; /* Download the code */ | ||
411 | i < 0x1000; /* Firmware code size = 4K */ | 406 | i < 0x1000; /* Firmware code size = 4K */ |
412 | i++, wBIOSAddress++) { | 407 | i++, bios_addr++) { |
413 | ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress); | 408 | outw(bios_addr, host->base + ORC_EBIOSADR0); |
414 | *pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */ | 409 | *data32_ptr++ = inb(host->base + ORC_EBIOSDATA); /* Read from BIOS */ |
415 | if ((i % 4) == 3) { | 410 | if ((i % 4) == 3) { |
416 | ORC_WRLONG(hcsp->HCS_Base + ORC_RISCRAM, dData); /* Write every 4 bytes */ | 411 | outl(data32, host->base + ORC_RISCRAM); /* Write every 4 bytes */ |
417 | pData = (UCHAR *) & dData; | 412 | data32_ptr = (u8 *) & data32; |
418 | } | 413 | } |
419 | } | 414 | } |
420 | 415 | ||
421 | ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST | DOWNLOAD); /* Reset program count 0 */ | 416 | /* Go back and check they match */ |
422 | wBIOSAddress -= 0x1000; /* Reset the BIOS adddress */ | 417 | |
423 | for (i = 0, pData = (UCHAR *) & dData; /* Check the code */ | 418 | outb(PRGMRST | DOWNLOAD, host->base + ORC_RISCCTL); /* Reset program count 0 */ |
419 | bios_addr -= 0x1000; /* Reset the BIOS adddress */ | ||
420 | for (i = 0, data32_ptr = (u8 *) & data32; /* Check the code */ | ||
424 | i < 0x1000; /* Firmware code size = 4K */ | 421 | i < 0x1000; /* Firmware code size = 4K */ |
425 | i++, wBIOSAddress++) { | 422 | i++, bios_addr++) { |
426 | ORC_WRSHORT(hcsp->HCS_Base + ORC_EBIOSADR0, wBIOSAddress); | 423 | outw(bios_addr, host->base + ORC_EBIOSADR0); |
427 | *pData++ = ORC_RD(hcsp->HCS_Base, ORC_EBIOSDATA); /* Read from BIOS */ | 424 | *data32_ptr++ = inb(host->base + ORC_EBIOSDATA); /* Read from BIOS */ |
428 | if ((i % 4) == 3) { | 425 | if ((i % 4) == 3) { |
429 | if (ORC_RDLONG(hcsp->HCS_Base, ORC_RISCRAM) != dData) { | 426 | if (inl(host->base + ORC_RISCRAM) != data32) { |
430 | ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST); /* Reset program to 0 */ | 427 | outb(PRGMRST, host->base + ORC_RISCCTL); /* Reset program to 0 */ |
431 | ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /*Disable EEPROM programming */ | 428 | outb(data, host->base + ORC_GCFG); /*Disable EEPROM programming */ |
432 | return 0; | 429 | return 0; |
433 | } | 430 | } |
434 | pData = (UCHAR *) & dData; | 431 | data32_ptr = (u8 *) & data32; |
435 | } | 432 | } |
436 | } | 433 | } |
437 | ORC_WR(hcsp->HCS_Base + ORC_RISCCTL, PRGMRST); /* Reset program to 0 */ | 434 | |
438 | ORC_WR(hcsp->HCS_Base + ORC_GCFG, bData); /* Disable EEPROM programming */ | 435 | /* Success */ |
436 | outb(PRGMRST, host->base + ORC_RISCCTL); /* Reset program to 0 */ | ||
437 | outb(data, host->base + ORC_GCFG); /* Disable EEPROM programming */ | ||
439 | return 1; | 438 | return 1; |
440 | } | 439 | } |
441 | 440 | ||
442 | /***************************************************************************/ | 441 | /***************************************************************************/ |
443 | static void setup_SCBs(ORC_HCS * hcsp) | 442 | static void setup_SCBs(struct orc_host * host) |
444 | { | 443 | { |
445 | ORC_SCB *pVirScb; | 444 | struct orc_scb *scb; |
446 | int i; | 445 | int i; |
447 | ESCB *pVirEscb; | 446 | struct orc_extended_scb *escb; |
448 | dma_addr_t pPhysEscb; | 447 | dma_addr_t escb_phys; |
449 | 448 | ||
450 | /* Setup SCB HCS_Base and SCB Size registers */ | 449 | /* Setup SCB base and SCB Size registers */ |
451 | ORC_WR(hcsp->HCS_Base + ORC_SCBSIZE, ORC_MAXQUEUE); /* Total number of SCBs */ | 450 | outb(ORC_MAXQUEUE, host->base + ORC_SCBSIZE); /* Total number of SCBs */ |
452 | /* SCB HCS_Base address 0 */ | 451 | /* SCB base address 0 */ |
453 | ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE0, hcsp->HCS_physScbArray); | 452 | outl(host->scb_phys, host->base + ORC_SCBBASE0); |
454 | /* SCB HCS_Base address 1 */ | 453 | /* SCB base address 1 */ |
455 | ORC_WRLONG(hcsp->HCS_Base + ORC_SCBBASE1, hcsp->HCS_physScbArray); | 454 | outl(host->scb_phys, host->base + ORC_SCBBASE1); |
456 | 455 | ||
457 | /* setup scatter list address with one buffer */ | 456 | /* setup scatter list address with one buffer */ |
458 | pVirScb = hcsp->HCS_virScbArray; | 457 | scb = host->scb_virt; |
459 | pVirEscb = hcsp->HCS_virEscbArray; | 458 | escb = host->escb_virt; |
460 | 459 | ||
461 | for (i = 0; i < ORC_MAXQUEUE; i++) { | 460 | for (i = 0; i < ORC_MAXQUEUE; i++) { |
462 | pPhysEscb = (hcsp->HCS_physEscbArray + (sizeof(ESCB) * i)); | 461 | escb_phys = (host->escb_phys + (sizeof(struct orc_extended_scb) * i)); |
463 | pVirScb->SCB_SGPAddr = (U32) pPhysEscb; | 462 | scb->sg_addr = (u32) escb_phys; |
464 | pVirScb->SCB_SensePAddr = (U32) pPhysEscb; | 463 | scb->sense_addr = (u32) escb_phys; |
465 | pVirScb->SCB_EScb = pVirEscb; | 464 | scb->escb = escb; |
466 | pVirScb->SCB_ScbIdx = i; | 465 | scb->scbidx = i; |
467 | pVirScb++; | 466 | scb++; |
468 | pVirEscb++; | 467 | escb++; |
469 | } | 468 | } |
470 | |||
471 | return; | ||
472 | } | 469 | } |
473 | 470 | ||
474 | /***************************************************************************/ | 471 | /** |
475 | static void initAFlag(ORC_HCS * hcsp) | 472 | * init_alloc_map - initialise allocation map |
473 | * @host: host map to configure | ||
474 | * | ||
475 | * Initialise the allocation maps for this device. If the device | ||
476 | * is not quiescent the caller must hold the allocation lock | ||
477 | */ | ||
478 | |||
479 | static void init_alloc_map(struct orc_host * host) | ||
476 | { | 480 | { |
477 | UCHAR i, j; | 481 | u8 i, j; |
478 | 482 | ||
479 | for (i = 0; i < MAX_CHANNELS; i++) { | 483 | for (i = 0; i < MAX_CHANNELS; i++) { |
480 | for (j = 0; j < 8; j++) { | 484 | for (j = 0; j < 8; j++) { |
481 | hcsp->BitAllocFlag[i][j] = 0xffffffff; | 485 | host->allocation_map[i][j] = 0xffffffff; |
482 | } | 486 | } |
483 | } | 487 | } |
484 | } | 488 | } |
485 | 489 | ||
486 | /***************************************************************************/ | 490 | /** |
487 | static int init_orchid(ORC_HCS * hcsp) | 491 | * init_orchid - initialise the host adapter |
492 | * @host:host adapter to initialise | ||
493 | * | ||
494 | * Initialise the controller and if neccessary load the firmware. | ||
495 | * | ||
496 | * Returns -1 if the initialisation fails. | ||
497 | */ | ||
498 | |||
499 | static int init_orchid(struct orc_host * host) | ||
488 | { | 500 | { |
489 | UBYTE *readBytep; | 501 | u8 *ptr; |
490 | USHORT revision; | 502 | u16 revision; |
491 | UCHAR i; | 503 | u8 i; |
492 | 504 | ||
493 | initAFlag(hcsp); | 505 | init_alloc_map(host); |
494 | ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFF); /* Disable all interrupt */ | 506 | outb(0xFF, host->base + ORC_GIMSK); /* Disable all interrupts */ |
495 | if (ORC_RD(hcsp->HCS_Base, ORC_HSTUS) & RREADY) { /* Orchid is ready */ | 507 | |
496 | revision = get_FW_version(hcsp); | 508 | if (inb(host->base + ORC_HSTUS) & RREADY) { /* Orchid is ready */ |
509 | revision = orc_read_fwrev(host); | ||
497 | if (revision == 0xFFFF) { | 510 | if (revision == 0xFFFF) { |
498 | ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST); /* Reset Host Adapter */ | 511 | outb(DEVRST, host->base + ORC_HCTRL); /* Reset Host Adapter */ |
499 | if (waitChipReady(hcsp) == 0) | 512 | if (wait_chip_ready(host) == 0) |
500 | return (-1); | 513 | return -1; |
501 | load_FW(hcsp); /* Download FW */ | 514 | orc_load_firmware(host); /* Download FW */ |
502 | setup_SCBs(hcsp); /* Setup SCB HCS_Base and SCB Size registers */ | 515 | setup_SCBs(host); /* Setup SCB base and SCB Size registers */ |
503 | ORC_WR(hcsp->HCS_Base + ORC_HCTRL, 0); /* clear HOSTSTOP */ | 516 | outb(0x00, host->base + ORC_HCTRL); /* clear HOSTSTOP */ |
504 | if (waitFWReady(hcsp) == 0) | 517 | if (wait_firmware_ready(host) == 0) |
505 | return (-1); | 518 | return -1; |
506 | /* Wait for firmware ready */ | 519 | /* Wait for firmware ready */ |
507 | } else { | 520 | } else { |
508 | setup_SCBs(hcsp); /* Setup SCB HCS_Base and SCB Size registers */ | 521 | setup_SCBs(host); /* Setup SCB base and SCB Size registers */ |
509 | } | 522 | } |
510 | } else { /* Orchid is not Ready */ | 523 | } else { /* Orchid is not Ready */ |
511 | ORC_WR(hcsp->HCS_Base + ORC_HCTRL, DEVRST); /* Reset Host Adapter */ | 524 | outb(DEVRST, host->base + ORC_HCTRL); /* Reset Host Adapter */ |
512 | if (waitChipReady(hcsp) == 0) | 525 | if (wait_chip_ready(host) == 0) |
513 | return (-1); | 526 | return -1; |
514 | load_FW(hcsp); /* Download FW */ | 527 | orc_load_firmware(host); /* Download FW */ |
515 | setup_SCBs(hcsp); /* Setup SCB HCS_Base and SCB Size registers */ | 528 | setup_SCBs(host); /* Setup SCB base and SCB Size registers */ |
516 | ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); /* Do Hardware Reset & */ | 529 | outb(HDO, host->base + ORC_HCTRL); /* Do Hardware Reset & */ |
517 | 530 | ||
518 | /* clear HOSTSTOP */ | 531 | /* clear HOSTSTOP */ |
519 | if (waitFWReady(hcsp) == 0) /* Wait for firmware ready */ | 532 | if (wait_firmware_ready(host) == 0) /* Wait for firmware ready */ |
520 | return (-1); | 533 | return -1; |
521 | } | 534 | } |
522 | 535 | ||
523 | /*------------- get serial EEProm settting -------*/ | 536 | /* Load an EEProm copy into RAM */ |
524 | 537 | /* Assumes single threaded at this point */ | |
525 | read_eeprom(hcsp); | 538 | read_eeprom(host); |
526 | |||
527 | if (nvramp->Revision != 1) | ||
528 | return (-1); | ||
529 | 539 | ||
530 | hcsp->HCS_SCSI_ID = nvramp->SCSI0Id; | 540 | if (nvramp->revision != 1) |
531 | hcsp->HCS_BIOS = nvramp->BIOSConfig1; | 541 | return -1; |
532 | hcsp->HCS_MaxTar = MAX_TARGETS; | ||
533 | readBytep = (UCHAR *) & (nvramp->Target00Config); | ||
534 | for (i = 0; i < 16; readBytep++, i++) { | ||
535 | hcsp->TargetFlag[i] = *readBytep; | ||
536 | hcsp->MaximumTags[i] = ORC_MAXTAGS; | ||
537 | } /* for */ | ||
538 | 542 | ||
539 | if (nvramp->SCSI0Config & NCC_BUSRESET) { /* Reset SCSI bus */ | 543 | host->scsi_id = nvramp->scsi_id; |
540 | hcsp->HCS_Flags |= HCF_SCSI_RESET; | 544 | host->BIOScfg = nvramp->BIOSConfig1; |
545 | host->max_targets = MAX_TARGETS; | ||
546 | ptr = (u8 *) & (nvramp->Target00Config); | ||
547 | for (i = 0; i < 16; ptr++, i++) { | ||
548 | host->target_flag[i] = *ptr; | ||
549 | host->max_tags[i] = ORC_MAXTAGS; | ||
541 | } | 550 | } |
542 | ORC_WR(hcsp->HCS_Base + ORC_GIMSK, 0xFB); /* enable RP FIFO interrupt */ | 551 | |
543 | return (0); | 552 | if (nvramp->SCSI0Config & NCC_BUSRESET) |
553 | host->flags |= HCF_SCSI_RESET; | ||
554 | outb(0xFB, host->base + ORC_GIMSK); /* enable RP FIFO interrupt */ | ||
555 | return 0; | ||
544 | } | 556 | } |
545 | 557 | ||
546 | /***************************************************************************** | 558 | /** |
547 | Function name : orc_reset_scsi_bus | 559 | * orc_reset_scsi_bus - perform bus reset |
548 | Description : Reset registers, reset a hanging bus and | 560 | * @host: host being reset |
549 | kill active and disconnected commands for target w/o soft reset | 561 | * |
550 | Input : pHCB - Pointer to host adapter structure | 562 | * Perform a full bus reset on the adapter. |
551 | Output : None. | 563 | */ |
552 | Return : pSRB - Pointer to SCSI request block. | 564 | |
553 | *****************************************************************************/ | 565 | static int orc_reset_scsi_bus(struct orc_host * host) |
554 | static int orc_reset_scsi_bus(ORC_HCS * pHCB) | ||
555 | { /* I need Host Control Block Information */ | 566 | { /* I need Host Control Block Information */ |
556 | ULONG flags; | 567 | unsigned long flags; |
557 | 568 | ||
558 | spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags); | 569 | spin_lock_irqsave(&host->allocation_lock, flags); |
559 | 570 | ||
560 | initAFlag(pHCB); | 571 | init_alloc_map(host); |
561 | /* reset scsi bus */ | 572 | /* reset scsi bus */ |
562 | ORC_WR(pHCB->HCS_Base + ORC_HCTRL, SCSIRST); | 573 | outb(SCSIRST, host->base + ORC_HCTRL); |
563 | if (waitSCSIRSTdone(pHCB) == 0) { | 574 | /* FIXME: We can spend up to a second with the lock held and |
564 | spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); | 575 | interrupts off here */ |
576 | if (wait_scsi_reset_done(host) == 0) { | ||
577 | spin_unlock_irqrestore(&host->allocation_lock, flags); | ||
565 | return FAILED; | 578 | return FAILED; |
566 | } else { | 579 | } else { |
567 | spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); | 580 | spin_unlock_irqrestore(&host->allocation_lock, flags); |
568 | return SUCCESS; | 581 | return SUCCESS; |
569 | } | 582 | } |
570 | } | 583 | } |
571 | 584 | ||
572 | /***************************************************************************** | 585 | /** |
573 | Function name : orc_device_reset | 586 | * orc_device_reset - device reset handler |
574 | Description : Reset registers, reset a hanging bus and | 587 | * @host: host to reset |
575 | kill active and disconnected commands for target w/o soft reset | 588 | * @cmd: command causing the reset |
576 | Input : pHCB - Pointer to host adapter structure | 589 | * @target; target device |
577 | Output : None. | 590 | * |
578 | Return : pSRB - Pointer to SCSI request block. | 591 | * Reset registers, reset a hanging bus and kill active and disconnected |
579 | *****************************************************************************/ | 592 | * commands for target w/o soft reset |
580 | static int orc_device_reset(ORC_HCS * pHCB, struct scsi_cmnd *SCpnt, unsigned int target) | 593 | */ |
594 | |||
595 | static int orc_device_reset(struct orc_host * host, struct scsi_cmnd *cmd, unsigned int target) | ||
581 | { /* I need Host Control Block Information */ | 596 | { /* I need Host Control Block Information */ |
582 | ORC_SCB *pScb; | 597 | struct orc_scb *scb; |
583 | ESCB *pVirEscb; | 598 | struct orc_extended_scb *escb; |
584 | ORC_SCB *pVirScb; | 599 | struct orc_scb *host_scb; |
585 | UCHAR i; | 600 | u8 i; |
586 | ULONG flags; | 601 | unsigned long flags; |
587 | 602 | ||
588 | spin_lock_irqsave(&(pHCB->BitAllocFlagLock), flags); | 603 | spin_lock_irqsave(&(host->allocation_lock), flags); |
589 | pScb = (ORC_SCB *) NULL; | 604 | scb = (struct orc_scb *) NULL; |
590 | pVirEscb = (ESCB *) NULL; | 605 | escb = (struct orc_extended_scb *) NULL; |
591 | 606 | ||
592 | /* setup scatter list address with one buffer */ | 607 | /* setup scatter list address with one buffer */ |
593 | pVirScb = pHCB->HCS_virScbArray; | 608 | host_scb = host->scb_virt; |
609 | |||
610 | /* FIXME: is this safe if we then fail to issue the reset or race | ||
611 | a completion ? */ | ||
612 | init_alloc_map(host); | ||
594 | 613 | ||
595 | initAFlag(pHCB); | 614 | /* Find the scb corresponding to the command */ |
596 | /* device reset */ | ||
597 | for (i = 0; i < ORC_MAXQUEUE; i++) { | 615 | for (i = 0; i < ORC_MAXQUEUE; i++) { |
598 | pVirEscb = pVirScb->SCB_EScb; | 616 | escb = host_scb->escb; |
599 | if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == SCpnt)) | 617 | if (host_scb->status && escb->srb == cmd) |
600 | break; | 618 | break; |
601 | pVirScb++; | 619 | host_scb++; |
602 | } | 620 | } |
603 | 621 | ||
604 | if (i == ORC_MAXQUEUE) { | 622 | if (i == ORC_MAXQUEUE) { |
605 | printk("Unable to Reset - No SCB Found\n"); | 623 | printk(KERN_ERR "Unable to Reset - No SCB Found\n"); |
606 | spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); | 624 | spin_unlock_irqrestore(&(host->allocation_lock), flags); |
607 | return FAILED; | 625 | return FAILED; |
608 | } | 626 | } |
609 | if ((pScb = orc_alloc_scb(pHCB)) == NULL) { | 627 | |
610 | spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); | 628 | /* Allocate a new SCB for the reset command to the firmware */ |
629 | if ((scb = __orc_alloc_scb(host)) == NULL) { | ||
630 | /* Can't happen.. */ | ||
631 | spin_unlock_irqrestore(&(host->allocation_lock), flags); | ||
611 | return FAILED; | 632 | return FAILED; |
612 | } | 633 | } |
613 | pScb->SCB_Opcode = ORC_BUSDEVRST; | 634 | |
614 | pScb->SCB_Target = target; | 635 | /* Reset device is handled by the firmare, we fill in an SCB and |
615 | pScb->SCB_HaStat = 0; | 636 | fire it at the controller, it does the rest */ |
616 | pScb->SCB_TaStat = 0; | 637 | scb->opcode = ORC_BUSDEVRST; |
617 | pScb->SCB_Status = 0x0; | 638 | scb->target = target; |
618 | pScb->SCB_Link = 0xFF; | 639 | scb->hastat = 0; |
619 | pScb->SCB_Reserved0 = 0; | 640 | scb->tastat = 0; |
620 | pScb->SCB_Reserved1 = 0; | 641 | scb->status = 0x0; |
621 | pScb->SCB_XferLen = 0; | 642 | scb->link = 0xFF; |
622 | pScb->SCB_SGLen = 0; | 643 | scb->reserved0 = 0; |
623 | 644 | scb->reserved1 = 0; | |
624 | pVirEscb->SCB_Srb = NULL; | 645 | scb->xferlen = 0; |
625 | pVirEscb->SCB_Srb = SCpnt; | 646 | scb->sg_len = 0; |
626 | orc_exec_scb(pHCB, pScb); /* Start execute SCB */ | 647 | |
627 | spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); | 648 | escb->srb = NULL; |
649 | escb->srb = cmd; | ||
650 | orc_exec_scb(host, scb); /* Start execute SCB */ | ||
651 | spin_unlock_irqrestore(&host->allocation_lock, flags); | ||
628 | return SUCCESS; | 652 | return SUCCESS; |
629 | } | 653 | } |
630 | 654 | ||
655 | /** | ||
656 | * __orc_alloc_scb - allocate an SCB | ||
657 | * @host: host to allocate from | ||
658 | * | ||
659 | * Allocate an SCB and return a pointer to the SCB object. NULL | ||
660 | * is returned if no SCB is free. The caller must already hold | ||
661 | * the allocator lock at this point. | ||
662 | */ | ||
631 | 663 | ||
632 | /***************************************************************************/ | 664 | |
633 | static ORC_SCB *__orc_alloc_scb(ORC_HCS * hcsp) | 665 | static struct orc_scb *__orc_alloc_scb(struct orc_host * host) |
634 | { | 666 | { |
635 | ORC_SCB *pTmpScb; | 667 | u8 channel; |
636 | UCHAR Ch; | 668 | unsigned long idx; |
637 | ULONG idx; | 669 | u8 index; |
638 | UCHAR index; | 670 | u8 i; |
639 | UCHAR i; | ||
640 | 671 | ||
641 | Ch = hcsp->HCS_Index; | 672 | channel = host->index; |
642 | for (i = 0; i < 8; i++) { | 673 | for (i = 0; i < 8; i++) { |
643 | for (index = 0; index < 32; index++) { | 674 | for (index = 0; index < 32; index++) { |
644 | if ((hcsp->BitAllocFlag[Ch][i] >> index) & 0x01) { | 675 | if ((host->allocation_map[channel][i] >> index) & 0x01) { |
645 | hcsp->BitAllocFlag[Ch][i] &= ~(1 << index); | 676 | host->allocation_map[channel][i] &= ~(1 << index); |
646 | break; | 677 | break; |
647 | } | 678 | } |
648 | } | 679 | } |
649 | idx = index + 32 * i; | 680 | idx = index + 32 * i; |
650 | pTmpScb = (ORC_SCB *) ((ULONG) hcsp->HCS_virScbArray + (idx * sizeof(ORC_SCB))); | 681 | /* Translate the index to a structure instance */ |
651 | return (pTmpScb); | 682 | return (struct orc_scb *) ((unsigned long) host->scb_virt + (idx * sizeof(struct orc_scb))); |
652 | } | 683 | } |
653 | return (NULL); | 684 | return NULL; |
654 | } | 685 | } |
655 | 686 | ||
656 | static ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp) | 687 | /** |
688 | * orc_alloc_scb - allocate an SCB | ||
689 | * @host: host to allocate from | ||
690 | * | ||
691 | * Allocate an SCB and return a pointer to the SCB object. NULL | ||
692 | * is returned if no SCB is free. | ||
693 | */ | ||
694 | |||
695 | static struct orc_scb *orc_alloc_scb(struct orc_host * host) | ||
657 | { | 696 | { |
658 | ORC_SCB *pTmpScb; | 697 | struct orc_scb *scb; |
659 | ULONG flags; | 698 | unsigned long flags; |
660 | 699 | ||
661 | spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags); | 700 | spin_lock_irqsave(&host->allocation_lock, flags); |
662 | pTmpScb = __orc_alloc_scb(hcsp); | 701 | scb = __orc_alloc_scb(host); |
663 | spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); | 702 | spin_unlock_irqrestore(&host->allocation_lock, flags); |
664 | return (pTmpScb); | 703 | return scb; |
665 | } | 704 | } |
666 | 705 | ||
706 | /** | ||
707 | * orc_release_scb - release an SCB | ||
708 | * @host: host owning the SCB | ||
709 | * @scb: SCB that is now free | ||
710 | * | ||
711 | * Called to return a completed SCB to the allocation pool. Before | ||
712 | * calling the SCB must be out of use on both the host and the HA. | ||
713 | */ | ||
667 | 714 | ||
668 | /***************************************************************************/ | 715 | static void orc_release_scb(struct orc_host *host, struct orc_scb *scb) |
669 | static void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp) | ||
670 | { | 716 | { |
671 | ULONG flags; | 717 | unsigned long flags; |
672 | UCHAR Index; | 718 | u8 index, i, channel; |
673 | UCHAR i; | 719 | |
674 | UCHAR Ch; | 720 | spin_lock_irqsave(&(host->allocation_lock), flags); |
675 | 721 | channel = host->index; /* Channel */ | |
676 | spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags); | 722 | index = scb->scbidx; |
677 | Ch = hcsp->HCS_Index; | 723 | i = index / 32; |
678 | Index = scbp->SCB_ScbIdx; | 724 | index %= 32; |
679 | i = Index / 32; | 725 | host->allocation_map[channel][i] |= (1 << index); |
680 | Index %= 32; | 726 | spin_unlock_irqrestore(&(host->allocation_lock), flags); |
681 | hcsp->BitAllocFlag[Ch][i] |= (1 << Index); | ||
682 | spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); | ||
683 | } | 727 | } |
684 | 728 | ||
685 | /***************************************************************************** | 729 | /** |
686 | Function name : abort_SCB | 730 | * orchid_abort_scb - abort a command |
687 | Description : Abort a queued command. | 731 | * |
688 | (commands that are on the bus can't be aborted easily) | 732 | * Abort a queued command that has been passed to the firmware layer |
689 | Input : pHCB - Pointer to host adapter structure | 733 | * if possible. This is all handled by the firmware. We aks the firmware |
690 | Output : None. | 734 | * and it either aborts the command or fails |
691 | Return : pSRB - Pointer to SCSI request block. | 735 | */ |
692 | *****************************************************************************/ | 736 | |
693 | static int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb) | 737 | static int orchid_abort_scb(struct orc_host * host, struct orc_scb * scb) |
694 | { | 738 | { |
695 | unsigned char bData, bStatus; | 739 | unsigned char data, status; |
696 | 740 | ||
697 | ORC_WR(hcsp->HCS_Base + ORC_HDATA, ORC_CMD_ABORT_SCB); /* Write command */ | 741 | outb(ORC_CMD_ABORT_SCB, host->base + ORC_HDATA); /* Write command */ |
698 | ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); | 742 | outb(HDO, host->base + ORC_HCTRL); |
699 | if (waitHDOoff(hcsp) == 0) /* Wait HDO off */ | 743 | if (wait_HDO_off(host) == 0) /* Wait HDO off */ |
700 | return 0; | 744 | return 0; |
701 | 745 | ||
702 | ORC_WR(hcsp->HCS_Base + ORC_HDATA, pScb->SCB_ScbIdx); /* Write address */ | 746 | outb(scb->scbidx, host->base + ORC_HDATA); /* Write address */ |
703 | ORC_WR(hcsp->HCS_Base + ORC_HCTRL, HDO); | 747 | outb(HDO, host->base + ORC_HCTRL); |
704 | if (waitHDOoff(hcsp) == 0) /* Wait HDO off */ | 748 | if (wait_HDO_off(host) == 0) /* Wait HDO off */ |
705 | return 0; | 749 | return 0; |
706 | 750 | ||
707 | if (waitHDIset(hcsp, &bData) == 0) /* Wait HDI set */ | 751 | if (wait_hdi_set(host, &data) == 0) /* Wait HDI set */ |
708 | return 0; | 752 | return 0; |
709 | bStatus = ORC_RD(hcsp->HCS_Base, ORC_HDATA); | 753 | status = inb(host->base + ORC_HDATA); |
710 | ORC_WR(hcsp->HCS_Base + ORC_HSTUS, bData); /* Clear HDI */ | 754 | outb(data, host->base + ORC_HSTUS); /* Clear HDI */ |
711 | 755 | ||
712 | if (bStatus == 1) /* 0 - Successfully */ | 756 | if (status == 1) /* 0 - Successfully */ |
713 | return 0; /* 1 - Fail */ | 757 | return 0; /* 1 - Fail */ |
714 | return 1; | 758 | return 1; |
715 | } | 759 | } |
716 | 760 | ||
717 | /***************************************************************************** | 761 | static int inia100_abort_cmd(struct orc_host * host, struct scsi_cmnd *cmd) |
718 | Function name : inia100_abort | ||
719 | Description : Abort a queued command. | ||
720 | (commands that are on the bus can't be aborted easily) | ||
721 | Input : pHCB - Pointer to host adapter structure | ||
722 | Output : None. | ||
723 | Return : pSRB - Pointer to SCSI request block. | ||
724 | *****************************************************************************/ | ||
725 | static int orc_abort_srb(ORC_HCS * hcsp, struct scsi_cmnd *SCpnt) | ||
726 | { | 762 | { |
727 | ESCB *pVirEscb; | 763 | struct orc_extended_scb *escb; |
728 | ORC_SCB *pVirScb; | 764 | struct orc_scb *scb; |
729 | UCHAR i; | 765 | u8 i; |
730 | ULONG flags; | 766 | unsigned long flags; |
731 | 767 | ||
732 | spin_lock_irqsave(&(hcsp->BitAllocFlagLock), flags); | 768 | spin_lock_irqsave(&(host->allocation_lock), flags); |
733 | 769 | ||
734 | pVirScb = hcsp->HCS_virScbArray; | 770 | scb = host->scb_virt; |
735 | 771 | ||
736 | for (i = 0; i < ORC_MAXQUEUE; i++, pVirScb++) { | 772 | /* Walk the queue until we find the SCB that belongs to the command |
737 | pVirEscb = pVirScb->SCB_EScb; | 773 | block. This isn't a performance critical path so a walk in the park |
738 | if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == SCpnt)) { | 774 | here does no harm */ |
739 | if (pVirScb->SCB_TagMsg == 0) { | 775 | |
740 | spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); | 776 | for (i = 0; i < ORC_MAXQUEUE; i++, scb++) { |
741 | return FAILED; | 777 | escb = scb->escb; |
778 | if (scb->status && escb->srb == cmd) { | ||
779 | if (scb->tag_msg == 0) { | ||
780 | goto out; | ||
742 | } else { | 781 | } else { |
743 | if (abort_SCB(hcsp, pVirScb)) { | 782 | /* Issue an ABORT to the firmware */ |
744 | pVirEscb->SCB_Srb = NULL; | 783 | if (orchid_abort_scb(host, scb)) { |
745 | spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); | 784 | escb->srb = NULL; |
785 | spin_unlock_irqrestore(&host->allocation_lock, flags); | ||
746 | return SUCCESS; | 786 | return SUCCESS; |
747 | } else { | 787 | } else |
748 | spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); | 788 | goto out; |
749 | return FAILED; | ||
750 | } | ||
751 | } | 789 | } |
752 | } | 790 | } |
753 | } | 791 | } |
754 | spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); | 792 | out: |
793 | spin_unlock_irqrestore(&host->allocation_lock, flags); | ||
755 | return FAILED; | 794 | return FAILED; |
756 | } | 795 | } |
757 | 796 | ||
758 | /*********************************************************************** | 797 | /** |
759 | Routine Description: | 798 | * orc_interrupt - IRQ processing |
760 | This is the interrupt service routine for the Orchid SCSI adapter. | 799 | * @host: Host causing the interrupt |
761 | It reads the interrupt register to determine if the adapter is indeed | 800 | * |
762 | the source of the interrupt and clears the interrupt at the device. | 801 | * This function is called from the IRQ handler and protected |
763 | Arguments: | 802 | * by the host lock. While the controller reports that there are |
764 | HwDeviceExtension - HBA miniport driver's adapter data storage | 803 | * scb's for processing we pull them off the controller, turn the |
765 | Return Value: | 804 | * index into a host address pointer to the scb and call the scb |
766 | ***********************************************************************/ | 805 | * handler. |
767 | static void orc_interrupt( | 806 | * |
768 | ORC_HCS * hcsp | 807 | * Returns IRQ_HANDLED if any SCBs were processed, IRQ_NONE otherwise |
769 | ) | 808 | */ |
809 | |||
810 | static irqreturn_t orc_interrupt(struct orc_host * host) | ||
770 | { | 811 | { |
771 | BYTE bScbIdx; | 812 | u8 scb_index; |
772 | ORC_SCB *pScb; | 813 | struct orc_scb *scb; |
773 | 814 | ||
774 | if (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT) == 0) { | 815 | /* Check if we have an SCB queued for servicing */ |
775 | return; // 0; | 816 | if (inb(host->base + ORC_RQUEUECNT) == 0) |
817 | return IRQ_NONE; | ||
776 | 818 | ||
777 | } | ||
778 | do { | 819 | do { |
779 | bScbIdx = ORC_RD(hcsp->HCS_Base, ORC_RQUEUE); | 820 | /* Get the SCB index of the SCB to service */ |
780 | 821 | scb_index = inb(host->base + ORC_RQUEUE); | |
781 | pScb = (ORC_SCB *) ((ULONG) hcsp->HCS_virScbArray + (ULONG) (sizeof(ORC_SCB) * bScbIdx)); | 822 | |
782 | pScb->SCB_Status = 0x0; | 823 | /* Translate it back to a host pointer */ |
783 | 824 | scb = (struct orc_scb *) ((unsigned long) host->scb_virt + (unsigned long) (sizeof(struct orc_scb) * scb_index)); | |
784 | inia100SCBPost((BYTE *) hcsp, (BYTE *) pScb); | 825 | scb->status = 0x0; |
785 | } while (ORC_RD(hcsp->HCS_Base, ORC_RQUEUECNT)); | 826 | /* Process the SCB */ |
786 | return; //1; | 827 | inia100_scb_handler(host, scb); |
787 | 828 | } while (inb(host->base + ORC_RQUEUECNT)); | |
829 | return IRQ_HANDLED; | ||
788 | } /* End of I1060Interrupt() */ | 830 | } /* End of I1060Interrupt() */ |
789 | 831 | ||
790 | /***************************************************************************** | 832 | /** |
791 | Function name : inia100BuildSCB | 833 | * inia100_build_scb - build SCB |
792 | Description : | 834 | * @host: host owing the control block |
793 | Input : pHCB - Pointer to host adapter structure | 835 | * @scb: control block to use |
794 | Output : None. | 836 | * @cmd: Mid layer command |
795 | Return : pSRB - Pointer to SCSI request block. | 837 | * |
796 | *****************************************************************************/ | 838 | * Build a host adapter control block from the SCSI mid layer command |
797 | static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, struct scsi_cmnd * SCpnt) | 839 | */ |
840 | |||
841 | static void inia100_build_scb(struct orc_host * host, struct orc_scb * scb, struct scsi_cmnd * cmd) | ||
798 | { /* Create corresponding SCB */ | 842 | { /* Create corresponding SCB */ |
799 | struct scatterlist *pSrbSG; | 843 | struct scatterlist *sg; |
800 | ORC_SG *pSG; /* Pointer to SG list */ | 844 | struct orc_sgent *sgent; /* Pointer to SG list */ |
801 | int i, count_sg; | 845 | int i, count_sg; |
802 | ESCB *pEScb; | 846 | struct orc_extended_scb *escb; |
803 | 847 | ||
804 | pEScb = pSCB->SCB_EScb; | 848 | /* Links between the escb, scb and Linux scsi midlayer cmd */ |
805 | pEScb->SCB_Srb = SCpnt; | 849 | escb = scb->escb; |
806 | pSG = NULL; | 850 | escb->srb = cmd; |
807 | 851 | sgent = NULL; | |
808 | pSCB->SCB_Opcode = ORC_EXECSCSI; | 852 | |
809 | pSCB->SCB_Flags = SCF_NO_DCHK; /* Clear done bit */ | 853 | /* Set up the SCB to do a SCSI command block */ |
810 | pSCB->SCB_Target = SCpnt->device->id; | 854 | scb->opcode = ORC_EXECSCSI; |
811 | pSCB->SCB_Lun = SCpnt->device->lun; | 855 | scb->flags = SCF_NO_DCHK; /* Clear done bit */ |
812 | pSCB->SCB_Reserved0 = 0; | 856 | scb->target = cmd->device->id; |
813 | pSCB->SCB_Reserved1 = 0; | 857 | scb->lun = cmd->device->lun; |
814 | pSCB->SCB_SGLen = 0; | 858 | scb->reserved0 = 0; |
815 | 859 | scb->reserved1 = 0; | |
816 | if ((pSCB->SCB_XferLen = (U32) SCpnt->request_bufflen)) { | 860 | scb->sg_len = 0; |
817 | pSG = (ORC_SG *) & pEScb->ESCB_SGList[0]; | 861 | |
818 | if (SCpnt->use_sg) { | 862 | scb->xferlen = (u32) scsi_bufflen(cmd); |
819 | pSrbSG = (struct scatterlist *) SCpnt->request_buffer; | 863 | sgent = (struct orc_sgent *) & escb->sglist[0]; |
820 | count_sg = pci_map_sg(pHCB->pdev, pSrbSG, SCpnt->use_sg, | 864 | |
821 | SCpnt->sc_data_direction); | 865 | count_sg = scsi_dma_map(cmd); |
822 | pSCB->SCB_SGLen = (U32) (count_sg * 8); | 866 | BUG_ON(count_sg < 0); |
823 | for (i = 0; i < count_sg; i++, pSG++, pSrbSG++) { | 867 | |
824 | pSG->SG_Ptr = (U32) sg_dma_address(pSrbSG); | 868 | /* Build the scatter gather lists */ |
825 | pSG->SG_Len = (U32) sg_dma_len(pSrbSG); | 869 | if (count_sg) { |
826 | } | 870 | scb->sg_len = (u32) (count_sg * 8); |
827 | } else if (SCpnt->request_bufflen != 0) {/* Non SG */ | 871 | scsi_for_each_sg(cmd, sg, count_sg, i) { |
828 | pSCB->SCB_SGLen = 0x8; | 872 | sgent->base = (u32) sg_dma_address(sg); |
829 | SCpnt->SCp.dma_handle = pci_map_single(pHCB->pdev, | 873 | sgent->length = (u32) sg_dma_len(sg); |
830 | SCpnt->request_buffer, | 874 | sgent++; |
831 | SCpnt->request_bufflen, | ||
832 | SCpnt->sc_data_direction); | ||
833 | pSG->SG_Ptr = (U32) SCpnt->SCp.dma_handle; | ||
834 | pSG->SG_Len = (U32) SCpnt->request_bufflen; | ||
835 | } else { | ||
836 | pSCB->SCB_SGLen = 0; | ||
837 | pSG->SG_Ptr = 0; | ||
838 | pSG->SG_Len = 0; | ||
839 | } | 875 | } |
876 | } else { | ||
877 | scb->sg_len = 0; | ||
878 | sgent->base = 0; | ||
879 | sgent->length = 0; | ||
840 | } | 880 | } |
841 | pSCB->SCB_SGPAddr = (U32) pSCB->SCB_SensePAddr; | 881 | scb->sg_addr = (u32) scb->sense_addr; |
842 | pSCB->SCB_HaStat = 0; | 882 | scb->hastat = 0; |
843 | pSCB->SCB_TaStat = 0; | 883 | scb->tastat = 0; |
844 | pSCB->SCB_Link = 0xFF; | 884 | scb->link = 0xFF; |
845 | pSCB->SCB_SenseLen = SENSE_SIZE; | 885 | scb->sense_len = SENSE_SIZE; |
846 | pSCB->SCB_CDBLen = SCpnt->cmd_len; | 886 | scb->cdb_len = cmd->cmd_len; |
847 | if (pSCB->SCB_CDBLen >= IMAX_CDB) { | 887 | if (scb->cdb_len >= IMAX_CDB) { |
848 | printk("max cdb length= %x\b", SCpnt->cmd_len); | 888 | printk("max cdb length= %x\b", cmd->cmd_len); |
849 | pSCB->SCB_CDBLen = IMAX_CDB; | 889 | scb->cdb_len = IMAX_CDB; |
850 | } | 890 | } |
851 | pSCB->SCB_Ident = SCpnt->device->lun | DISC_ALLOW; | 891 | scb->ident = cmd->device->lun | DISC_ALLOW; |
852 | if (SCpnt->device->tagged_supported) { /* Tag Support */ | 892 | if (cmd->device->tagged_supported) { /* Tag Support */ |
853 | pSCB->SCB_TagMsg = SIMPLE_QUEUE_TAG; /* Do simple tag only */ | 893 | scb->tag_msg = SIMPLE_QUEUE_TAG; /* Do simple tag only */ |
854 | } else { | 894 | } else { |
855 | pSCB->SCB_TagMsg = 0; /* No tag support */ | 895 | scb->tag_msg = 0; /* No tag support */ |
856 | } | 896 | } |
857 | memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, pSCB->SCB_CDBLen); | 897 | memcpy(&scb->cdb[0], &cmd->cmnd, scb->cdb_len); |
858 | return; | ||
859 | } | 898 | } |
860 | 899 | ||
861 | /***************************************************************************** | 900 | /** |
862 | Function name : inia100_queue | 901 | * inia100_queue - queue command with host |
863 | Description : Queue a command and setup interrupts for a free bus. | 902 | * @cmd: Command block |
864 | Input : pHCB - Pointer to host adapter structure | 903 | * @done: Completion function |
865 | Output : None. | 904 | * |
866 | Return : pSRB - Pointer to SCSI request block. | 905 | * Called by the mid layer to queue a command. Process the command |
867 | *****************************************************************************/ | 906 | * block, build the host specific scb structures and if there is room |
868 | static int inia100_queue(struct scsi_cmnd * SCpnt, void (*done) (struct scsi_cmnd *)) | 907 | * queue the command down to the controller |
908 | */ | ||
909 | |||
910 | static int inia100_queue(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *)) | ||
869 | { | 911 | { |
870 | register ORC_SCB *pSCB; | 912 | struct orc_scb *scb; |
871 | ORC_HCS *pHCB; /* Point to Host adapter control block */ | 913 | struct orc_host *host; /* Point to Host adapter control block */ |
872 | 914 | ||
873 | pHCB = (ORC_HCS *) SCpnt->device->host->hostdata; | 915 | host = (struct orc_host *) cmd->device->host->hostdata; |
874 | SCpnt->scsi_done = done; | 916 | cmd->scsi_done = done; |
875 | /* Get free SCSI control block */ | 917 | /* Get free SCSI control block */ |
876 | if ((pSCB = orc_alloc_scb(pHCB)) == NULL) | 918 | if ((scb = orc_alloc_scb(host)) == NULL) |
877 | return SCSI_MLQUEUE_HOST_BUSY; | 919 | return SCSI_MLQUEUE_HOST_BUSY; |
878 | 920 | ||
879 | inia100BuildSCB(pHCB, pSCB, SCpnt); | 921 | inia100_build_scb(host, scb, cmd); |
880 | orc_exec_scb(pHCB, pSCB); /* Start execute SCB */ | 922 | orc_exec_scb(host, scb); /* Start execute SCB */ |
881 | 923 | return 0; | |
882 | return (0); | ||
883 | } | 924 | } |
884 | 925 | ||
885 | /***************************************************************************** | 926 | /***************************************************************************** |
886 | Function name : inia100_abort | 927 | Function name : inia100_abort |
887 | Description : Abort a queued command. | 928 | Description : Abort a queued command. |
888 | (commands that are on the bus can't be aborted easily) | 929 | (commands that are on the bus can't be aborted easily) |
889 | Input : pHCB - Pointer to host adapter structure | 930 | Input : host - Pointer to host adapter structure |
890 | Output : None. | 931 | Output : None. |
891 | Return : pSRB - Pointer to SCSI request block. | 932 | Return : pSRB - Pointer to SCSI request block. |
892 | *****************************************************************************/ | 933 | *****************************************************************************/ |
893 | static int inia100_abort(struct scsi_cmnd * SCpnt) | 934 | static int inia100_abort(struct scsi_cmnd * cmd) |
894 | { | 935 | { |
895 | ORC_HCS *hcsp; | 936 | struct orc_host *host; |
896 | 937 | ||
897 | hcsp = (ORC_HCS *) SCpnt->device->host->hostdata; | 938 | host = (struct orc_host *) cmd->device->host->hostdata; |
898 | return orc_abort_srb(hcsp, SCpnt); | 939 | return inia100_abort_cmd(host, cmd); |
899 | } | 940 | } |
900 | 941 | ||
901 | /***************************************************************************** | 942 | /***************************************************************************** |
902 | Function name : inia100_reset | 943 | Function name : inia100_reset |
903 | Description : Reset registers, reset a hanging bus and | 944 | Description : Reset registers, reset a hanging bus and |
904 | kill active and disconnected commands for target w/o soft reset | 945 | kill active and disconnected commands for target w/o soft reset |
905 | Input : pHCB - Pointer to host adapter structure | 946 | Input : host - Pointer to host adapter structure |
906 | Output : None. | 947 | Output : None. |
907 | Return : pSRB - Pointer to SCSI request block. | 948 | Return : pSRB - Pointer to SCSI request block. |
908 | *****************************************************************************/ | 949 | *****************************************************************************/ |
909 | static int inia100_bus_reset(struct scsi_cmnd * SCpnt) | 950 | static int inia100_bus_reset(struct scsi_cmnd * cmd) |
910 | { /* I need Host Control Block Information */ | 951 | { /* I need Host Control Block Information */ |
911 | ORC_HCS *pHCB; | 952 | struct orc_host *host; |
912 | pHCB = (ORC_HCS *) SCpnt->device->host->hostdata; | 953 | host = (struct orc_host *) cmd->device->host->hostdata; |
913 | return orc_reset_scsi_bus(pHCB); | 954 | return orc_reset_scsi_bus(host); |
914 | } | 955 | } |
915 | 956 | ||
916 | /***************************************************************************** | 957 | /***************************************************************************** |
917 | Function name : inia100_device_reset | 958 | Function name : inia100_device_reset |
918 | Description : Reset the device | 959 | Description : Reset the device |
919 | Input : pHCB - Pointer to host adapter structure | 960 | Input : host - Pointer to host adapter structure |
920 | Output : None. | 961 | Output : None. |
921 | Return : pSRB - Pointer to SCSI request block. | 962 | Return : pSRB - Pointer to SCSI request block. |
922 | *****************************************************************************/ | 963 | *****************************************************************************/ |
923 | static int inia100_device_reset(struct scsi_cmnd * SCpnt) | 964 | static int inia100_device_reset(struct scsi_cmnd * cmd) |
924 | { /* I need Host Control Block Information */ | 965 | { /* I need Host Control Block Information */ |
925 | ORC_HCS *pHCB; | 966 | struct orc_host *host; |
926 | pHCB = (ORC_HCS *) SCpnt->device->host->hostdata; | 967 | host = (struct orc_host *) cmd->device->host->hostdata; |
927 | return orc_device_reset(pHCB, SCpnt, scmd_id(SCpnt)); | 968 | return orc_device_reset(host, cmd, scmd_id(cmd)); |
928 | 969 | ||
929 | } | 970 | } |
930 | 971 | ||
931 | /***************************************************************************** | 972 | /** |
932 | Function name : inia100SCBPost | 973 | * inia100_scb_handler - interrupt callback |
933 | Description : This is callback routine be called when orc finish one | 974 | * @host: Host causing the interrupt |
934 | SCSI command. | 975 | * @scb: SCB the controller returned as needing processing |
935 | Input : pHCB - Pointer to host adapter control block. | 976 | * |
936 | pSCB - Pointer to SCSI control block. | 977 | * Perform completion processing on a control block. Do the conversions |
937 | Output : None. | 978 | * from host to SCSI midlayer error coding, save any sense data and |
938 | Return : None. | 979 | * the complete with the midlayer and recycle the scb. |
939 | *****************************************************************************/ | 980 | */ |
940 | static void inia100SCBPost(BYTE * pHcb, BYTE * pScb) | 981 | |
982 | static void inia100_scb_handler(struct orc_host *host, struct orc_scb *scb) | ||
941 | { | 983 | { |
942 | struct scsi_cmnd *pSRB; /* Pointer to SCSI request block */ | 984 | struct scsi_cmnd *cmd; /* Pointer to SCSI request block */ |
943 | ORC_HCS *pHCB; | 985 | struct orc_extended_scb *escb; |
944 | ORC_SCB *pSCB; | 986 | |
945 | ESCB *pEScb; | 987 | escb = scb->escb; |
946 | 988 | if ((cmd = (struct scsi_cmnd *) escb->srb) == NULL) { | |
947 | pHCB = (ORC_HCS *) pHcb; | 989 | printk(KERN_ERR "inia100_scb_handler: SRB pointer is empty\n"); |
948 | pSCB = (ORC_SCB *) pScb; | 990 | orc_release_scb(host, scb); /* Release SCB for current channel */ |
949 | pEScb = pSCB->SCB_EScb; | ||
950 | if ((pSRB = (struct scsi_cmnd *) pEScb->SCB_Srb) == 0) { | ||
951 | printk("inia100SCBPost: SRB pointer is empty\n"); | ||
952 | orc_release_scb(pHCB, pSCB); /* Release SCB for current channel */ | ||
953 | return; | 991 | return; |
954 | } | 992 | } |
955 | pEScb->SCB_Srb = NULL; | 993 | escb->srb = NULL; |
956 | 994 | ||
957 | switch (pSCB->SCB_HaStat) { | 995 | switch (scb->hastat) { |
958 | case 0x0: | 996 | case 0x0: |
959 | case 0xa: /* Linked command complete without error and linked normally */ | 997 | case 0xa: /* Linked command complete without error and linked normally */ |
960 | case 0xb: /* Linked command complete without error interrupt generated */ | 998 | case 0xb: /* Linked command complete without error interrupt generated */ |
961 | pSCB->SCB_HaStat = 0; | 999 | scb->hastat = 0; |
962 | break; | 1000 | break; |
963 | 1001 | ||
964 | case 0x11: /* Selection time out-The initiator selection or target | 1002 | case 0x11: /* Selection time out-The initiator selection or target |
965 | reselection was not complete within the SCSI Time out period */ | 1003 | reselection was not complete within the SCSI Time out period */ |
966 | pSCB->SCB_HaStat = DID_TIME_OUT; | 1004 | scb->hastat = DID_TIME_OUT; |
967 | break; | 1005 | break; |
968 | 1006 | ||
969 | case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus | 1007 | case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus |
970 | phase sequence was requested by the target. The host adapter | 1008 | phase sequence was requested by the target. The host adapter |
971 | will generate a SCSI Reset Condition, notifying the host with | 1009 | will generate a SCSI Reset Condition, notifying the host with |
972 | a SCRD interrupt */ | 1010 | a SCRD interrupt */ |
973 | pSCB->SCB_HaStat = DID_RESET; | 1011 | scb->hastat = DID_RESET; |
974 | break; | 1012 | break; |
975 | 1013 | ||
976 | case 0x1a: /* SCB Aborted. 07/21/98 */ | 1014 | case 0x1a: /* SCB Aborted. 07/21/98 */ |
977 | pSCB->SCB_HaStat = DID_ABORT; | 1015 | scb->hastat = DID_ABORT; |
978 | break; | 1016 | break; |
979 | 1017 | ||
980 | case 0x12: /* Data overrun/underrun-The target attempted to transfer more data | 1018 | case 0x12: /* Data overrun/underrun-The target attempted to transfer more data |
@@ -984,46 +1022,41 @@ static void inia100SCBPost(BYTE * pHcb, BYTE * pScb) | |||
984 | case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid. */ | 1022 | case 0x16: /* Invalid CCB Operation Code-The first byte of the CCB was invalid. */ |
985 | 1023 | ||
986 | default: | 1024 | default: |
987 | printk("inia100: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat); | 1025 | printk(KERN_DEBUG "inia100: %x %x\n", scb->hastat, scb->tastat); |
988 | pSCB->SCB_HaStat = DID_ERROR; /* Couldn't find any better */ | 1026 | scb->hastat = DID_ERROR; /* Couldn't find any better */ |
989 | break; | 1027 | break; |
990 | } | 1028 | } |
991 | 1029 | ||
992 | if (pSCB->SCB_TaStat == 2) { /* Check condition */ | 1030 | if (scb->tastat == 2) { /* Check condition */ |
993 | memcpy((unsigned char *) &pSRB->sense_buffer[0], | 1031 | memcpy((unsigned char *) &cmd->sense_buffer[0], |
994 | (unsigned char *) &pEScb->ESCB_SGList[0], SENSE_SIZE); | 1032 | (unsigned char *) &escb->sglist[0], SENSE_SIZE); |
995 | } | 1033 | } |
996 | pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16); | 1034 | cmd->result = scb->tastat | (scb->hastat << 16); |
997 | 1035 | scsi_dma_unmap(cmd); | |
998 | if (pSRB->use_sg) { | 1036 | cmd->scsi_done(cmd); /* Notify system DONE */ |
999 | pci_unmap_sg(pHCB->pdev, | 1037 | orc_release_scb(host, scb); /* Release SCB for current channel */ |
1000 | (struct scatterlist *)pSRB->request_buffer, | ||
1001 | pSRB->use_sg, pSRB->sc_data_direction); | ||
1002 | } else if (pSRB->request_bufflen != 0) { | ||
1003 | pci_unmap_single(pHCB->pdev, pSRB->SCp.dma_handle, | ||
1004 | pSRB->request_bufflen, | ||
1005 | pSRB->sc_data_direction); | ||
1006 | } | ||
1007 | |||
1008 | pSRB->scsi_done(pSRB); /* Notify system DONE */ | ||
1009 | |||
1010 | orc_release_scb(pHCB, pSCB); /* Release SCB for current channel */ | ||
1011 | } | 1038 | } |
1012 | 1039 | ||
1013 | /* | 1040 | /** |
1014 | * Interrupt handler (main routine of the driver) | 1041 | * inia100_intr - interrupt handler |
1042 | * @irqno: Interrupt value | ||
1043 | * @devid: Host adapter | ||
1044 | * | ||
1045 | * Entry point for IRQ handling. All the real work is performed | ||
1046 | * by orc_interrupt. | ||
1015 | */ | 1047 | */ |
1016 | static irqreturn_t inia100_intr(int irqno, void *devid) | 1048 | static irqreturn_t inia100_intr(int irqno, void *devid) |
1017 | { | 1049 | { |
1018 | struct Scsi_Host *host = (struct Scsi_Host *)devid; | 1050 | struct Scsi_Host *shost = (struct Scsi_Host *)devid; |
1019 | ORC_HCS *pHcb = (ORC_HCS *)host->hostdata; | 1051 | struct orc_host *host = (struct orc_host *)shost->hostdata; |
1020 | unsigned long flags; | 1052 | unsigned long flags; |
1053 | irqreturn_t res; | ||
1021 | 1054 | ||
1022 | spin_lock_irqsave(host->host_lock, flags); | 1055 | spin_lock_irqsave(shost->host_lock, flags); |
1023 | orc_interrupt(pHcb); | 1056 | res = orc_interrupt(host); |
1024 | spin_unlock_irqrestore(host->host_lock, flags); | 1057 | spin_unlock_irqrestore(shost->host_lock, flags); |
1025 | 1058 | ||
1026 | return IRQ_HANDLED; | 1059 | return res; |
1027 | } | 1060 | } |
1028 | 1061 | ||
1029 | static struct scsi_host_template inia100_template = { | 1062 | static struct scsi_host_template inia100_template = { |
@@ -1044,12 +1077,12 @@ static int __devinit inia100_probe_one(struct pci_dev *pdev, | |||
1044 | const struct pci_device_id *id) | 1077 | const struct pci_device_id *id) |
1045 | { | 1078 | { |
1046 | struct Scsi_Host *shost; | 1079 | struct Scsi_Host *shost; |
1047 | ORC_HCS *pHCB; | 1080 | struct orc_host *host; |
1048 | unsigned long port, bios; | 1081 | unsigned long port, bios; |
1049 | int error = -ENODEV; | 1082 | int error = -ENODEV; |
1050 | u32 sz; | 1083 | u32 sz; |
1051 | unsigned long dBiosAdr; | 1084 | unsigned long biosaddr; |
1052 | char *pbBiosAdr; | 1085 | char *bios_phys; |
1053 | 1086 | ||
1054 | if (pci_enable_device(pdev)) | 1087 | if (pci_enable_device(pdev)) |
1055 | goto out; | 1088 | goto out; |
@@ -1068,55 +1101,55 @@ static int __devinit inia100_probe_one(struct pci_dev *pdev, | |||
1068 | } | 1101 | } |
1069 | 1102 | ||
1070 | /* <02> read from base address + 0x50 offset to get the bios value. */ | 1103 | /* <02> read from base address + 0x50 offset to get the bios value. */ |
1071 | bios = ORC_RDWORD(port, 0x50); | 1104 | bios = inw(port + 0x50); |
1072 | 1105 | ||
1073 | 1106 | ||
1074 | shost = scsi_host_alloc(&inia100_template, sizeof(ORC_HCS)); | 1107 | shost = scsi_host_alloc(&inia100_template, sizeof(struct orc_host)); |
1075 | if (!shost) | 1108 | if (!shost) |
1076 | goto out_release_region; | 1109 | goto out_release_region; |
1077 | 1110 | ||
1078 | pHCB = (ORC_HCS *)shost->hostdata; | 1111 | host = (struct orc_host *)shost->hostdata; |
1079 | pHCB->pdev = pdev; | 1112 | host->pdev = pdev; |
1080 | pHCB->HCS_Base = port; | 1113 | host->base = port; |
1081 | pHCB->HCS_BIOS = bios; | 1114 | host->BIOScfg = bios; |
1082 | spin_lock_init(&pHCB->BitAllocFlagLock); | 1115 | spin_lock_init(&host->allocation_lock); |
1083 | 1116 | ||
1084 | /* Get total memory needed for SCB */ | 1117 | /* Get total memory needed for SCB */ |
1085 | sz = ORC_MAXQUEUE * sizeof(ORC_SCB); | 1118 | sz = ORC_MAXQUEUE * sizeof(struct orc_scb); |
1086 | pHCB->HCS_virScbArray = pci_alloc_consistent(pdev, sz, | 1119 | host->scb_virt = pci_alloc_consistent(pdev, sz, |
1087 | &pHCB->HCS_physScbArray); | 1120 | &host->scb_phys); |
1088 | if (!pHCB->HCS_virScbArray) { | 1121 | if (!host->scb_virt) { |
1089 | printk("inia100: SCB memory allocation error\n"); | 1122 | printk("inia100: SCB memory allocation error\n"); |
1090 | goto out_host_put; | 1123 | goto out_host_put; |
1091 | } | 1124 | } |
1092 | memset(pHCB->HCS_virScbArray, 0, sz); | 1125 | memset(host->scb_virt, 0, sz); |
1093 | 1126 | ||
1094 | /* Get total memory needed for ESCB */ | 1127 | /* Get total memory needed for ESCB */ |
1095 | sz = ORC_MAXQUEUE * sizeof(ESCB); | 1128 | sz = ORC_MAXQUEUE * sizeof(struct orc_extended_scb); |
1096 | pHCB->HCS_virEscbArray = pci_alloc_consistent(pdev, sz, | 1129 | host->escb_virt = pci_alloc_consistent(pdev, sz, |
1097 | &pHCB->HCS_physEscbArray); | 1130 | &host->escb_phys); |
1098 | if (!pHCB->HCS_virEscbArray) { | 1131 | if (!host->escb_virt) { |
1099 | printk("inia100: ESCB memory allocation error\n"); | 1132 | printk("inia100: ESCB memory allocation error\n"); |
1100 | goto out_free_scb_array; | 1133 | goto out_free_scb_array; |
1101 | } | 1134 | } |
1102 | memset(pHCB->HCS_virEscbArray, 0, sz); | 1135 | memset(host->escb_virt, 0, sz); |
1103 | 1136 | ||
1104 | dBiosAdr = pHCB->HCS_BIOS; | 1137 | biosaddr = host->BIOScfg; |
1105 | dBiosAdr = (dBiosAdr << 4); | 1138 | biosaddr = (biosaddr << 4); |
1106 | pbBiosAdr = phys_to_virt(dBiosAdr); | 1139 | bios_phys = phys_to_virt(biosaddr); |
1107 | if (init_orchid(pHCB)) { /* Initialize orchid chip */ | 1140 | if (init_orchid(host)) { /* Initialize orchid chip */ |
1108 | printk("inia100: initial orchid fail!!\n"); | 1141 | printk("inia100: initial orchid fail!!\n"); |
1109 | goto out_free_escb_array; | 1142 | goto out_free_escb_array; |
1110 | } | 1143 | } |
1111 | 1144 | ||
1112 | shost->io_port = pHCB->HCS_Base; | 1145 | shost->io_port = host->base; |
1113 | shost->n_io_port = 0xff; | 1146 | shost->n_io_port = 0xff; |
1114 | shost->can_queue = ORC_MAXQUEUE; | 1147 | shost->can_queue = ORC_MAXQUEUE; |
1115 | shost->unique_id = shost->io_port; | 1148 | shost->unique_id = shost->io_port; |
1116 | shost->max_id = pHCB->HCS_MaxTar; | 1149 | shost->max_id = host->max_targets; |
1117 | shost->max_lun = 16; | 1150 | shost->max_lun = 16; |
1118 | shost->irq = pHCB->HCS_Intr = pdev->irq; | 1151 | shost->irq = pdev->irq; |
1119 | shost->this_id = pHCB->HCS_SCSI_ID; /* Assign HCS index */ | 1152 | shost->this_id = host->scsi_id; /* Assign HCS index */ |
1120 | shost->sg_tablesize = TOTAL_SG_ENTRY; | 1153 | shost->sg_tablesize = TOTAL_SG_ENTRY; |
1121 | 1154 | ||
1122 | /* Initial orc chip */ | 1155 | /* Initial orc chip */ |
@@ -1137,36 +1170,36 @@ static int __devinit inia100_probe_one(struct pci_dev *pdev, | |||
1137 | scsi_scan_host(shost); | 1170 | scsi_scan_host(shost); |
1138 | return 0; | 1171 | return 0; |
1139 | 1172 | ||
1140 | out_free_irq: | 1173 | out_free_irq: |
1141 | free_irq(shost->irq, shost); | 1174 | free_irq(shost->irq, shost); |
1142 | out_free_escb_array: | 1175 | out_free_escb_array: |
1143 | pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ESCB), | 1176 | pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_extended_scb), |
1144 | pHCB->HCS_virEscbArray, pHCB->HCS_physEscbArray); | 1177 | host->escb_virt, host->escb_phys); |
1145 | out_free_scb_array: | 1178 | out_free_scb_array: |
1146 | pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ORC_SCB), | 1179 | pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_scb), |
1147 | pHCB->HCS_virScbArray, pHCB->HCS_physScbArray); | 1180 | host->scb_virt, host->scb_phys); |
1148 | out_host_put: | 1181 | out_host_put: |
1149 | scsi_host_put(shost); | 1182 | scsi_host_put(shost); |
1150 | out_release_region: | 1183 | out_release_region: |
1151 | release_region(port, 256); | 1184 | release_region(port, 256); |
1152 | out_disable_device: | 1185 | out_disable_device: |
1153 | pci_disable_device(pdev); | 1186 | pci_disable_device(pdev); |
1154 | out: | 1187 | out: |
1155 | return error; | 1188 | return error; |
1156 | } | 1189 | } |
1157 | 1190 | ||
1158 | static void __devexit inia100_remove_one(struct pci_dev *pdev) | 1191 | static void __devexit inia100_remove_one(struct pci_dev *pdev) |
1159 | { | 1192 | { |
1160 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 1193 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
1161 | ORC_HCS *pHCB = (ORC_HCS *)shost->hostdata; | 1194 | struct orc_host *host = (struct orc_host *)shost->hostdata; |
1162 | 1195 | ||
1163 | scsi_remove_host(shost); | 1196 | scsi_remove_host(shost); |
1164 | 1197 | ||
1165 | free_irq(shost->irq, shost); | 1198 | free_irq(shost->irq, shost); |
1166 | pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ESCB), | 1199 | pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_extended_scb), |
1167 | pHCB->HCS_virEscbArray, pHCB->HCS_physEscbArray); | 1200 | host->escb_virt, host->escb_phys); |
1168 | pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ORC_SCB), | 1201 | pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(struct orc_scb), |
1169 | pHCB->HCS_virScbArray, pHCB->HCS_physScbArray); | 1202 | host->scb_virt, host->scb_phys); |
1170 | release_region(shost->io_port, 256); | 1203 | release_region(shost->io_port, 256); |
1171 | 1204 | ||
1172 | scsi_host_put(shost); | 1205 | scsi_host_put(shost); |