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