Replace spl*() with critical sections.
[dragonfly.git] / sys / dev / raid / ips / ips.c
1 /*-
2  * Written by: David Jeffery
3  * Copyright (c) 2002 Adaptec Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD: src/sys/dev/ips/ips.c,v 1.12 2004/05/30 04:01:29 scottl Exp $
28  * $DragonFly: src/sys/dev/raid/ips/ips.c,v 1.11 2005/06/07 00:51:13 y0netan1 Exp $
29  */
30
31 #include <dev/raid/ips/ips.h>
32 #include <sys/stat.h>
33 #include <sys/time.h>
34 #include <sys/thread2.h>
35 #include <machine/clock.h>
36
37 static d_open_t ips_open;
38 static d_close_t ips_close;
39 static d_ioctl_t ips_ioctl;
40
41 MALLOC_DEFINE(M_IPSBUF, "ipsbuf", "IPS driver buffer");
42
43 static struct cdevsw ips_cdevsw = {
44         .d_name         = "ips",
45         .d_maj          = IPS_CDEV_MAJOR,
46         .d_flags        = D_DISK,
47         .d_port         = NULL,
48         .d_clone        = NULL,
49         .old_open       = ips_open,
50         .old_close      = ips_close,
51         .old_ioctl      = ips_ioctl,
52 };
53
54 static const char *ips_adapter_name[] = {
55         "N/A",
56         "ServeRAID (copperhead)",
57         "ServeRAID II (copperhead refresh)",
58         "ServeRAID onboard (copperhead)",
59         "ServeRAID onboard (copperhead)",
60         "ServeRAID 3H (clarinet)",
61         "ServeRAID 3L (clarinet lite)",
62         "ServeRAID 4H (trombone)",
63         "ServeRAID 4M (morpheus)",
64         "ServeRAID 4L (morpheus lite)",
65         "ServeRAID 4Mx (neo)",
66         "ServeRAID 4Lx (neo lite)",
67         "ServeRAID 5i II (sarasota)",
68         "ServeRAID 5i (sarasota)",
69         "ServeRAID 6M (marco)",
70         "ServeRAID 6i (sebring)"
71 };
72
73
74 static int
75 ips_open(dev_t dev, int flags, int fmt, d_thread_t *td)
76 {
77         ips_softc_t *sc = dev->si_drv1;
78
79         sc->state |= IPS_DEV_OPEN;
80         return 0;
81 }
82
83 static int
84 ips_close(dev_t dev, int flags, int fmt, d_thread_t *td)
85 {
86         ips_softc_t *sc = dev->si_drv1;
87
88         sc->state &= ~IPS_DEV_OPEN;
89         return 0;
90 }
91
92 static int
93 ips_ioctl(dev_t dev, u_long command, caddr_t addr, int32_t flags,
94     d_thread_t *td)
95 {
96         ips_softc_t *sc;
97
98         sc = dev->si_drv1;
99         return ips_ioctl_request(sc, command, addr, flags);
100 }
101
102 static void
103 ips_cmd_dmaload(void *cmdptr, bus_dma_segment_t *segments, int segnum,
104     int error)
105 {
106         ips_command_t *command = cmdptr;
107
108         PRINTF(10, "ips: in ips_cmd_dmaload\n");
109         if (!error)
110                 command->command_phys_addr = segments[0].ds_addr;
111
112 }
113
114 /* is locking needed? what locking guarentees are there on removal? */
115 static __inline__ int
116 ips_cmdqueue_free(ips_softc_t *sc)
117 {
118         int i, error = -1;
119         ips_command_t *command;
120
121         crit_enter();
122         if (sc->used_commands == 0) {
123                 for (i = 0; i < sc->max_cmds; i++) {
124                         command = &sc->commandarray[i];
125                         if (command->command_phys_addr == 0)
126                                 continue;
127                         bus_dmamap_unload(sc->command_dmatag,
128                             command->command_dmamap);
129                         bus_dmamem_free(sc->command_dmatag,
130                             command->command_buffer,
131                             command->command_dmamap);
132                 }
133                 error = 0;
134                 sc->state |= IPS_OFFLINE;
135         }
136         crit_exit();
137         return error;
138 }
139
140 /* places all ips command structs on the free command queue.  No locking as if someone else tries
141  * to access this during init, we have bigger problems */
142 static __inline__ int
143 ips_cmdqueue_init(ips_softc_t *sc)
144 {
145         int i;
146         ips_command_t *command;
147
148         SLIST_INIT(&sc->free_cmd_list);
149         STAILQ_INIT(&sc->cmd_wait_list);
150         for (i = 0; i < sc->max_cmds; i++) {
151                 command = &sc->commandarray[i];
152                 command->id = i;
153                 command->sc = sc;
154                 if (bus_dmamem_alloc(sc->command_dmatag,
155                     &command->command_buffer, BUS_DMA_NOWAIT,
156                     &command->command_dmamap))
157                         goto error;
158                 bus_dmamap_load(sc->command_dmatag, command->command_dmamap,
159                     command->command_buffer, IPS_COMMAND_LEN, ips_cmd_dmaload,
160                     command, BUS_DMA_NOWAIT);
161                 if (command->command_phys_addr == 0) {
162                         bus_dmamem_free(sc->command_dmatag,
163                             command->command_buffer, command->command_dmamap);
164                         goto error;
165                 }
166                 SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
167         }
168         sc->state &= ~IPS_OFFLINE;
169         return 0;
170 error:
171         ips_cmdqueue_free(sc);
172         return ENOMEM;
173 }
174
175 static int
176 ips_add_waiting_command(ips_softc_t *sc, int (*callback)(ips_command_t *),
177     void *data)
178 {
179         ips_command_t *command;
180         ips_wait_list_t *waiter;
181
182         waiter = malloc(sizeof(ips_wait_list_t), M_IPSBUF, M_INTWAIT);
183         crit_enter();
184         if (sc->state & IPS_OFFLINE) {
185                 crit_exit();
186                 free(waiter, M_IPSBUF);
187                 return EIO;
188         }
189         command = SLIST_FIRST(&sc->free_cmd_list);
190         if (command && !(sc->state & IPS_TIMEOUT)) {
191                 SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
192                 sc->used_commands++;
193                 crit_exit();
194                 clear_ips_command(command);
195                 bzero(command->command_buffer, IPS_COMMAND_LEN);
196                 free(waiter, M_IPSBUF);
197                 command->arg = data;
198                 return callback(command);
199         }
200         DEVICE_PRINTF(1, sc->dev, "adding command to the wait queue\n");
201         waiter->callback = callback;
202         waiter->data = data;
203         STAILQ_INSERT_TAIL(&sc->cmd_wait_list, waiter, next);
204         crit_exit();
205         return 0;
206 }
207
208 static void
209 ips_run_waiting_command(ips_softc_t *sc)
210 {
211         ips_wait_list_t *waiter;
212         ips_command_t   *command;
213         int (*callback)(ips_command_t*);
214
215         crit_enter();
216         waiter = STAILQ_FIRST(&sc->cmd_wait_list);
217         command = SLIST_FIRST(&sc->free_cmd_list);
218         if (waiter == NULL || command == NULL) {
219                 crit_exit();
220                 return;
221         }
222         DEVICE_PRINTF(1, sc->dev, "removing command from wait queue\n");
223         SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
224         STAILQ_REMOVE_HEAD(&sc->cmd_wait_list, next);
225         sc->used_commands++;
226         crit_exit();
227         clear_ips_command(command);
228         bzero(command->command_buffer, IPS_COMMAND_LEN);
229         command->arg = waiter->data;
230         callback = waiter->callback;
231         free(waiter, M_IPSBUF);
232         callback(command);
233         return;
234 }
235
236 /*
237  * returns a free command struct if one is available.
238  * It also blanks out anything that may be a wild pointer/value.
239  * Also, command buffers are not freed.  They are
240  * small so they are saved and kept dmamapped and loaded.
241  */
242 int
243 ips_get_free_cmd(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data,
244     unsigned long flags)
245 {
246         ips_command_t *command;
247
248         crit_enter();
249         if (sc->state & IPS_OFFLINE) {
250                 crit_exit();
251                 return EIO;
252         }
253         command = SLIST_FIRST(&sc->free_cmd_list);
254         if (!command || (sc->state & IPS_TIMEOUT)) {
255                 crit_exit();
256                 if (flags & IPS_NOWAIT_FLAG)
257                         return EAGAIN;
258                 return ips_add_waiting_command(sc, callback, data);
259         }
260         SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
261         sc->used_commands++;
262         crit_exit();
263         clear_ips_command(command);
264         bzero(command->command_buffer, IPS_COMMAND_LEN);
265         command->arg = data;
266         return callback(command);
267 }
268
269 /* adds a command back to the free command queue */
270 void
271 ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command)
272 {
273         crit_enter();
274         SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
275         sc->used_commands--;
276         crit_exit();
277         if (!(sc->state & IPS_TIMEOUT))
278                 ips_run_waiting_command(sc);
279 }
280 static const char *
281 ips_diskdev_statename(u_int8_t state)
282 {
283         static char statebuf[20];
284
285         switch(state) {
286         case IPS_LD_OFFLINE:
287                 return("OFFLINE");
288                 break;
289         case IPS_LD_OKAY:
290                 return("OK");
291                 break;
292         case IPS_LD_DEGRADED:
293                 return("DEGRADED");
294                 break;
295         case IPS_LD_FREE:
296                 return("FREE");
297                 break;
298         case IPS_LD_SYS:
299                 return("SYS");
300                 break;
301         case IPS_LD_CRS:
302                 return("CRS");
303                 break;
304         }
305         sprintf(statebuf, "UNKNOWN(0x%02x)", state);
306         return (statebuf);
307 }
308
309 static int
310 ips_diskdev_init(ips_softc_t *sc)
311 {
312         int i;
313
314         for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
315                 if (sc->drives[i].state == IPS_LD_FREE)
316                         continue;
317                 device_printf(sc->dev,
318                     "Logical Drive %d: RAID%d sectors: %u, state %s\n", i,
319                     sc->drives[i].raid_lvl, sc->drives[i].sector_count,
320                     ips_diskdev_statename(sc->drives[i].state));
321                 if (sc->drives[i].state == IPS_LD_OKAY ||
322                     sc->drives[i].state == IPS_LD_DEGRADED) {
323                         sc->diskdev[i] = device_add_child(sc->dev, NULL, -1);
324                         device_set_ivars(sc->diskdev[i], (void *)(uintptr_t)i);
325                 }
326         }
327         if (bus_generic_attach(sc->dev))
328                 device_printf(sc->dev, "Attaching bus failed\n");
329         return 0;
330 }
331
332 static int
333 ips_diskdev_free(ips_softc_t *sc)
334 {
335         int i;
336         int error = 0;
337
338         for (i = 0; i < IPS_MAX_NUM_DRIVES; i++) {
339                 if (sc->diskdev[i] != NULL) {
340                         error = device_delete_child(sc->dev, sc->diskdev[i]);
341                         if (error)
342                                 return error;
343                 }
344         }
345         bus_generic_detach(sc->dev);
346         return 0;
347 }
348
349 /*
350  * ips_timeout is periodically called to make sure no commands sent
351  * to the card have become stuck.  If it finds a stuck command, it
352  * sets a flag so the driver won't start any more commands and then
353  * is periodically called to see if all outstanding commands have
354  * either finished or timed out.  Once timed out, an attempt to
355  * reinitialize the card is made.  If that fails, the driver gives
356  * up and declares the card dead.
357  */
358 static void
359 ips_timeout(void *arg)
360 {
361         ips_command_t *command;
362         ips_softc_t *sc = arg;
363         int i, state = 0;
364
365         command = &sc->commandarray[0];
366         crit_enter();
367         for (i = 0; i < sc->max_cmds; i++) {
368                 if (!command[i].timeout)
369                         continue;
370                 command[i].timeout--;
371                 if (command[i].timeout == 0) {
372                         if (!(sc->state & IPS_TIMEOUT)) {
373                                 sc->state |= IPS_TIMEOUT;
374                                 device_printf(sc->dev, "WARNING: command timeout. Adapter is in toaster mode, resetting to known state\n");
375                         }
376                         command[i].status.value = IPS_ERROR_STATUS;
377                         command[i].callback(&command[i]);
378                         /* hmm, this should be enough cleanup */
379                 } else
380                         state = 1;
381         }
382         if (!state && (sc->state & IPS_TIMEOUT)) {
383                 if (sc->ips_adapter_reinit(sc, 1)) {
384                         device_printf(sc->dev, "AIEE! adapter reset failed, "
385                             "giving up and going home! Have a nice day.\n");
386                         sc->state |= IPS_OFFLINE;
387                         sc->state &= ~IPS_TIMEOUT;
388                         /*
389                          * Grr, I hate this solution. I run waiting commands
390                          * one at a time and error them out just before they
391                          * would go to the card. This sucks.
392                          */
393                 } else
394                         sc->state &= ~IPS_TIMEOUT;
395                 ips_run_waiting_command(sc);
396         }
397         if (sc->state != IPS_OFFLINE)
398                 callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
399         crit_exit();
400 }
401
402 /* check card and initialize it */
403 int
404 ips_adapter_init(ips_softc_t *sc)
405 {
406         int i;
407         dev_t dev;
408
409         DEVICE_PRINTF(1, sc->dev, "initializing\n");
410         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
411                                 /* alignemnt */ 1,
412                                 /* boundary  */ 0,
413                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
414                                 /* highaddr  */ BUS_SPACE_MAXADDR,
415                                 /* filter    */ NULL,
416                                 /* filterarg */ NULL,
417                                 /* maxsize   */ IPS_COMMAND_LEN +
418                                                     IPS_MAX_SG_LEN,
419                                 /* numsegs   */ 1,
420                                 /* maxsegsize*/ IPS_COMMAND_LEN +
421                                                     IPS_MAX_SG_LEN,
422                                 /* flags     */ 0,
423                                 &sc->command_dmatag) != 0) {
424                 device_printf(sc->dev, "can't alloc command dma tag\n");
425                 goto error;
426         }
427         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
428                                 /* alignemnt */ 1,
429                                 /* boundary  */ 0,
430                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
431                                 /* highaddr  */ BUS_SPACE_MAXADDR,
432                                 /* filter    */ NULL,
433                                 /* filterarg */ NULL,
434                                 /* maxsize   */ IPS_MAX_IOBUF_SIZE,
435                                 /* numsegs   */ IPS_MAX_SG_ELEMENTS,
436                                 /* maxsegsize*/ IPS_MAX_IOBUF_SIZE,
437                                 /* flags     */ 0,
438                                 &sc->sg_dmatag) != 0) {
439                 device_printf(sc->dev, "can't alloc SG dma tag\n");
440                 goto error;
441         }
442         /*
443          * create one command buffer until we know how many commands this card
444          * can handle
445          */
446         sc->max_cmds = 1;
447         ips_cmdqueue_init(sc);
448         callout_init(&sc->timer);
449         if (sc->ips_adapter_reinit(sc, 0))
450                 goto error;
451         /* initialize ffdc values */
452         microtime(&sc->ffdc_resettime);
453         sc->ffdc_resetcount = 1;
454         if ((i = ips_ffdc_reset(sc)) != 0) {
455                 device_printf(sc->dev,
456                     "failed to send ffdc reset to device (%d)\n", i);
457                 goto error;
458         }
459         if ((i = ips_get_adapter_info(sc)) != 0) {
460                 device_printf(sc->dev, "failed to get adapter configuration "
461                     "data from device (%d)\n", i);
462                 goto error;
463         }
464         /* no error check as failure doesn't matter */
465         ips_update_nvram(sc);
466         if (sc->adapter_type > 0 && sc->adapter_type <= IPS_ADAPTER_MAX_T) {
467                 device_printf(sc->dev, "adapter type: %s\n",
468                     ips_adapter_name[sc->adapter_type]);
469         }
470         if ((i = ips_get_drive_info(sc)) != 0) {
471                 device_printf(sc->dev, "failed to get drive "
472                     "configuration data from device (%d)\n", i);
473                 goto error;
474         }
475         ips_cmdqueue_free(sc);
476         if (sc->adapter_info.max_concurrent_cmds)
477                 sc->max_cmds = min(128, sc->adapter_info.max_concurrent_cmds);
478         else
479                 sc->max_cmds = 32;
480         if (ips_cmdqueue_init(sc)) {
481                 device_printf(sc->dev,
482                     "failed to initialize command buffers\n");
483                 goto error;
484         }
485         cdevsw_add(&ips_cdevsw, -1, device_get_unit(sc->dev));
486         dev = make_dev(&ips_cdevsw, device_get_unit(sc->dev),
487                                    UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
488                                    "ips%d", device_get_unit(sc->dev));
489         dev->si_drv1 = sc;
490         ips_diskdev_init(sc);
491         callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
492         return 0;
493 error:
494         ips_adapter_free(sc);
495         return ENXIO;
496 }
497
498 /*
499  * see if we should reinitialize the card and wait for it to timeout
500  * or complete initialization
501  */
502 int
503 ips_morpheus_reinit(ips_softc_t *sc, int force)
504 {
505         u_int32_t tmp;
506         int i;
507
508         tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
509         if (!force && (ips_read_4(sc, MORPHEUS_REG_OMR0) >= IPS_POST1_OK) &&
510             (ips_read_4(sc, MORPHEUS_REG_OMR1) != 0xdeadbeef) && !tmp) {
511                 ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
512                 return 0;
513         }
514         ips_write_4(sc, MORPHEUS_REG_OIMR, 0xff);
515         ips_read_4(sc, MORPHEUS_REG_OIMR);
516         device_printf(sc->dev,
517             "resetting adapter, this may take up to 5 minutes\n");
518         ips_write_4(sc, MORPHEUS_REG_IDR, 0x80000000);
519         DELAY(5000000);
520         pci_read_config(sc->dev, 0, 4);
521         tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
522         for (i = 0; i < 45 && !(tmp & MORPHEUS_BIT_POST1); i++) {
523                 DELAY(1000000);
524                 DEVICE_PRINTF(2, sc->dev, "post1: %d\n", i);
525                 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
526         }
527         if (tmp & MORPHEUS_BIT_POST1)
528                 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST1);
529
530         if (i == 45 || ips_read_4(sc, MORPHEUS_REG_OMR0) < IPS_POST1_OK) {
531                 device_printf(sc->dev,
532                     "Adapter error during initialization.\n");
533                 return 1;
534         }
535         for (i = 0; i < 240 && !(tmp & MORPHEUS_BIT_POST2); i++) {
536                 DELAY(1000000);
537                 DEVICE_PRINTF(2, sc->dev, "post2: %d\n", i);
538                 tmp = ips_read_4(sc, MORPHEUS_REG_OISR);
539         }
540         if (tmp & MORPHEUS_BIT_POST2)
541                 ips_write_4(sc, MORPHEUS_REG_OISR, MORPHEUS_BIT_POST2);
542
543         if (i == 240 || !ips_read_4(sc, MORPHEUS_REG_OMR1)) {
544                 device_printf(sc->dev, "adapter failed config check\n");
545                 return 1;
546         }
547         ips_write_4(sc, MORPHEUS_REG_OIMR, 0);
548         if (force && ips_clear_adapter(sc)) {
549                 device_printf(sc->dev, "adapter clear failed\n");
550                 return 1;
551         }
552         return 0;
553 }
554
555 /* clean up so we can unload the driver. */
556 int
557 ips_adapter_free(ips_softc_t *sc)
558 {
559         int error = 0;
560
561         if (sc->state & IPS_DEV_OPEN)
562                 return EBUSY;
563         if ((error = ips_diskdev_free(sc)))
564                 return error;
565         if (ips_cmdqueue_free(sc)) {
566                 device_printf(sc->dev,
567                     "trying to exit when command queue is not empty!\n");
568                 return EBUSY;
569         }
570         DEVICE_PRINTF(1, sc->dev, "free\n");
571         crit_enter();
572         callout_stop(&sc->timer);
573         crit_exit();
574         if (sc->sg_dmatag)
575                 bus_dma_tag_destroy(sc->sg_dmatag);
576         if (sc->command_dmatag)
577                 bus_dma_tag_destroy(sc->command_dmatag);
578         cdevsw_remove(&ips_cdevsw, -1, device_get_unit(sc->dev));
579         return 0;
580 }
581
582 void
583 ips_morpheus_intr(void *void_sc)
584 {
585         ips_softc_t *sc = (ips_softc_t *)void_sc;
586         u_int32_t oisr, iisr;
587         ips_cmd_status_t status;
588         ips_command_t *command;
589         int cmdnumber;
590
591         iisr =ips_read_4(sc, MORPHEUS_REG_IISR);
592         oisr =ips_read_4(sc, MORPHEUS_REG_OISR);
593         PRINTF(9, "interrupt registers in:%x out:%x\n", iisr, oisr);
594         if (!(oisr & MORPHEUS_BIT_CMD_IRQ)) {
595                 DEVICE_PRINTF(2, sc->dev, "got a non-command irq\n");
596                 return;
597         }
598         while ((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR))
599                != 0xffffffff) {
600                 cmdnumber = status.fields.command_id;
601                 command = &sc->commandarray[cmdnumber];
602                 command->status.value = status.value;
603                 command->timeout = 0;
604                 command->callback(command);
605                 DEVICE_PRINTF(9, sc->dev, "got command %d\n", cmdnumber);
606         }
607         return;
608 }
609
610 void
611 ips_issue_morpheus_cmd(ips_command_t *command)
612 {
613         crit_enter();
614         /* hmmm, is there a cleaner way to do this? */
615         if (command->sc->state & IPS_OFFLINE) {
616                 crit_exit();
617                 command->status.value = IPS_ERROR_STATUS;
618                 command->callback(command);
619                 return;
620         }
621         command->timeout = 10;
622         ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
623         crit_exit();
624 }
625
626 static void
627 ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,
628                               int segnum, int error)
629 {
630         ips_copper_queue_t *queue = queueptr;
631
632         if (error)
633                 return;
634         queue->base_phys_addr = segments[0].ds_addr;
635 }
636
637 static int
638 ips_copperhead_queue_init(ips_softc_t *sc)
639 {
640         bus_dma_tag_t dmatag;
641         bus_dmamap_t dmamap;
642         int error;
643
644         if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
645                                 /* alignemnt */ 1,
646                                 /* boundary  */ 0,
647                                 /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
648                                 /* highaddr  */ BUS_SPACE_MAXADDR,
649                                 /* filter    */ NULL,
650                                 /* filterarg */ NULL,
651                                 /* maxsize   */ sizeof(ips_copper_queue_t),
652                                 /* numsegs   */ 1,
653                                 /* maxsegsize*/ sizeof(ips_copper_queue_t),
654                                 /* flags     */ 0,
655                                 &dmatag) != 0) {
656                 device_printf(sc->dev, "can't alloc dma tag for statue queue\n");
657                 error = ENOMEM;
658                 goto exit;
659         }
660         if (bus_dmamem_alloc(dmatag, (void *)&(sc->copper_queue),
661             BUS_DMA_NOWAIT, &dmamap)) {
662                 error = ENOMEM;
663                 goto exit;
664         }
665         bzero(sc->copper_queue, sizeof(ips_copper_queue_t));
666         sc->copper_queue->dmatag = dmatag;
667         sc->copper_queue->dmamap = dmamap;
668         sc->copper_queue->nextstatus = 1;
669         bus_dmamap_load(dmatag, dmamap, &(sc->copper_queue->status[0]),
670             IPS_MAX_CMD_NUM * 4, ips_copperhead_queue_callback,
671             sc->copper_queue, BUS_DMA_NOWAIT);
672         if (sc->copper_queue->base_phys_addr == 0) {
673                 error = ENOMEM;
674                 goto exit;
675         }
676         ips_write_4(sc, COPPER_REG_SQSR, sc->copper_queue->base_phys_addr);
677         ips_write_4(sc, COPPER_REG_SQER, sc->copper_queue->base_phys_addr +
678             IPS_MAX_CMD_NUM * 4);
679         ips_write_4(sc, COPPER_REG_SQHR, sc->copper_queue->base_phys_addr + 4);
680         ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr);
681         return 0;
682 exit:
683         bus_dmamem_free(dmatag, sc->copper_queue, dmamap);
684         bus_dma_tag_destroy(dmatag);
685         return error;
686 }
687
688 /*
689  * see if we should reinitialize the card and wait for it to timeout or
690  * complete initialization FIXME
691  */
692 int
693 ips_copperhead_reinit(ips_softc_t *sc, int force)
694 {
695         u_int32_t postcode = 0, configstatus = 0;
696         int       i, j;
697
698         ips_write_1(sc, COPPER_REG_SCPR, 0x80);
699         ips_write_1(sc, COPPER_REG_SCPR, 0);
700         device_printf(sc->dev,
701             "reinitializing adapter, this could take several minutes.\n");
702         for (j = 0; j < 2; j++) {
703                 postcode <<= 8;
704                 for (i = 0; i < 45; i++) {
705                         if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
706                                 postcode |= ips_read_1(sc, COPPER_REG_ISPR);
707                                 ips_write_1(sc, COPPER_REG_HISR,
708                                     COPPER_GHI_BIT);
709                                 break;
710                         } else
711                                 DELAY(1000000);
712                 }
713                 if (i == 45)
714                         return 1;
715         }
716         for (j = 0; j < 2; j++) {
717                 configstatus <<= 8;
718                 for (i = 0; i < 240; i++) {
719                         if (ips_read_1(sc, COPPER_REG_HISR) & COPPER_GHI_BIT) {
720                                 configstatus |= ips_read_1(sc, COPPER_REG_ISPR);
721                                 ips_write_1(sc, COPPER_REG_HISR,
722                                     COPPER_GHI_BIT);
723                                 break;
724                         } else
725                                 DELAY(1000000);
726                 }
727                 if (i == 240)
728                         return 1;
729         }
730         for (i = 0; i < 240; i++) {
731                 if (!(ips_read_1(sc, COPPER_REG_CBSP) & COPPER_OP_BIT))
732                         break;
733                 else
734                         DELAY(1000000);
735         }
736         if (i == 240)
737                 return 1;
738         ips_write_2(sc, COPPER_REG_CCCR, 0x1000 | COPPER_ILE_BIT);
739         ips_write_1(sc, COPPER_REG_SCPR, COPPER_EBM_BIT);
740         ips_copperhead_queue_init(sc);
741         ips_write_1(sc, COPPER_REG_HISR, COPPER_GHI_BIT);
742         i = ips_read_1(sc, COPPER_REG_SCPR);
743         ips_write_1(sc, COPPER_REG_HISR, COPPER_EI_BIT);
744         if (configstatus == 0) {
745                 device_printf(sc->dev, "adapter initialization failed\n");
746                 return 1;
747         }
748         if (force && ips_clear_adapter(sc)) {
749                 device_printf(sc->dev, "adapter clear failed\n");
750                 return 1;
751         }
752         return 0;
753 }
754
755 static u_int32_t
756 ips_copperhead_cmd_status(ips_softc_t *sc)
757 {
758         u_int32_t value;
759         int statnum;
760
761         statnum = sc->copper_queue->nextstatus++;
762         if (sc->copper_queue->nextstatus == IPS_MAX_CMD_NUM)
763                 sc->copper_queue->nextstatus = 0;
764         crit_enter();
765         value = sc->copper_queue->status[statnum];
766         ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr +
767             4 * statnum);
768         crit_exit();
769         return value;
770 }
771
772 void
773 ips_copperhead_intr(void *void_sc)
774 {
775         ips_softc_t *sc = (ips_softc_t *)void_sc;
776         ips_cmd_status_t status;
777         int cmdnumber;
778
779         while (ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT) {
780                 status.value = ips_copperhead_cmd_status(sc);
781                 cmdnumber = status.fields.command_id;
782                 sc->commandarray[cmdnumber].status.value = status.value;
783                 sc->commandarray[cmdnumber].timeout = 0;
784                 sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
785                 PRINTF(9, "ips: got command %d\n", cmdnumber);
786         }
787         return;
788 }
789
790 void
791 ips_issue_copperhead_cmd(ips_command_t *command)
792 {
793         int i;
794
795         crit_enter();
796         /* hmmm, is there a cleaner way to do this? */
797         if (command->sc->state & IPS_OFFLINE) {
798                 crit_exit();
799                 command->status.value = IPS_ERROR_STATUS;
800                 command->callback(command);
801                 return;
802         }
803         command->timeout = 10;
804         for (i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
805             i++) {
806                 if (i == 20) {
807                         printf("sem bit still set, can't send a command\n");
808                         crit_exit();
809                         return;
810                 }
811                 DELAY(500);     /* need to do a delay here */
812         }
813         ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
814         ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);
815         crit_exit();
816 }