1 /* $NetBSD: sbp2.c,v 1.20 2005/02/27 00:27:17 perry Exp $ */
2
3 /*
4 * Copyright (c) 2001,2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by James Chacon.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: sbp2.c,v 1.20 2005/02/27 00:27:17 perry Exp $");
41
42 #include <sys/param.h>
43 #include <sys/kernel.h>
44 #include <sys/device.h>
45 #include <sys/systm.h>
46 #include <sys/malloc.h>
47 #include <sys/lock.h>
48
49 #include <machine/bus.h>
50 #include <machine/limits.h>
51
52 #include <dev/std/ieee1212reg.h>
53 #include <dev/std/ieee1212var.h>
54 #include <dev/ieee1394/ieee1394reg.h>
55 #include <dev/ieee1394/ieee1394var.h>
56 #include <dev/ieee1394/sbp2reg.h>
57 #include <dev/ieee1394/sbp2var.h>
58 #include <dev/ieee1394/sbpscsireg.h>
59
60 static void sbp2_print_data(struct p1212_data *);
61 static void sbp2_print_dir(struct p1212_dir *);
62 static void sbp2_login(struct sbp2 *, struct sbp2_lun *);
63 static void sbp2_login_ans(struct ieee1394_abuf *, int);
64 static void sbp2_login_resp(struct ieee1394_abuf *, int);
65 static struct sbp2_lun *sbp2_alloc_lun(u_int32_t, u_int32_t, u_int32_t,
66 u_int32_t, u_int32_t);
67 static void sbp2_logout(struct sbp2 *, struct sbp2_lun *);
68 static void sbp2_relogin(struct ieee1394_softc *, void *);
69 static struct sbp2_orb *sbp2_alloc_orb(void);
70 static void sbp2_free_orb(struct sbp2_orb *);
71 static void sbp2_alloc_data_mapping(struct sbp2 *, struct sbp2_mapping *,
72 u_char *, u_int32_t, u_int8_t);
73 static void sbp2_free_data_mapping(struct sbp2 *, struct sbp2_mapping *);
74 static u_int64_t sbp2_alloc_addr(struct sbp2 *);
75 static void sbp2_free_addr(struct sbp2 *, u_int64_t);
76 static void sbp2_orb_resp(struct ieee1394_abuf *, int);
77 static void sbp2_data_resp(struct ieee1394_abuf *, int);
78 static void sbp2_enable_status(struct ieee1394_abuf *, int);
79 static void sbp2_null_resp(struct ieee1394_abuf *, int);
80 static void sbp2_doorbell_reset(struct ieee1394_abuf *, int);
81 static void sbp2_status_resp(struct sbp2_status *, void *);
82 static struct sbp2_pagetable *sbp2_alloc_pt(struct uio *, u_int8_t,
83 struct sbp2_orb *);
84 static void sbp2_pt_resp(struct ieee1394_abuf *, int);
85 static void sbp2_free_pt(struct sbp2_pagetable *);
86
87 #ifdef SBP2_DEBUG
88 static void sbp2_agent_status(struct ieee1394_abuf *, int);
89 #endif
90
91 static CIRCLEQ_HEAD(, sbp2_orb) sbp2_freeorbs =
92 CIRCLEQ_HEAD_INITIALIZER(sbp2_freeorbs);
93 static struct simplelock sbp2_freeorbs_lock = SIMPLELOCK_INITIALIZER;
94 static struct sbp2_orb status_orb;
95 static TAILQ_HEAD(, sbp2_map) sbp2_maps =
96 TAILQ_HEAD_INITIALIZER(sbp2_maps);
97 static struct simplelock sbp2_maps_lock = SIMPLELOCK_INITIALIZER;
98
99 #ifdef SBP2_DEBUG
100 #define DPRINTF(x) if (sbp2debug) printf x
101 #define DPRINTFN(n,x) if (sbp2debug>(n)) printf x
102 int sbp2debug = 3;
103 #else
104 #define DPRINTF(x)
105 #define DPRINTFN(n,x)
106 #endif
107
108 static void
109 sbp2_print_data(struct p1212_data *data)
110 {
111 switch (data->com.key.key_value) {
112 case SBP2_KEYVALUE_Command_Set:
113 printf("SBP2 Command Set: ");
114 if (data->com.key.val == SBPSCSI_COMMAND_SET)
115 printf("SCSI 2\n");
116 else
117 printf("0x%08x\n", data->val);
118 break;
119 case SBP2_KEYVALUE_Unit_Characteristics:
120 printf("SBP2 Unit Characteristics: 0x%08x\n",data->com.key.val);
121 break;
122 case SBP2_KEYVALUE_Command_Set_Revision:
123 printf("SBP2 Command Set Revision: 0x%08x\n",data->com.key.val);
124 break;
125 case SBP2_KEYVALUE_Command_Set_Spec_Id:
126 printf("SBP2 Command Set Spec Id: 0x%08x\n", data->com.key.val);
127 break;
128 case SBP2_KEYVALUE_Firmware_Revision:
129 printf("SBP2 Firmware Revision: 0x%08x\n", data->com.key.val);
130 break;
131 case SBP2_KEYVALUE_Reconnect_Timeout:
132 printf("SBP2 Reconnect Timeout: 0x%08x\n", data->com.key.val);
133 break;
134 case SBP2_KEYVALUE_Unit_Unique_Id:
135 printf("SBP2 Unit Unique Id: 0x%08x\n", data->com.key.val);
136 break;
137 case P1212_KEYVALUE_Unit_Dependent_Info:
138 if (data->com.key.key_type == P1212_KEYTYPE_Immediate)
139 printf("SBP2 Logical Unit Number: 0x%08x\n",
140 data->com.key.val);
141 else if (data->com.key.key_type == P1212_KEYTYPE_Offset)
142 printf("SBP2 Management Agent: 0x%08x\n",
143 data->com.key.val);
144 break;
145 default:
146 printf("Unknown SBP2 key and value: 0x%08x 0x%08x\n",
147 data->com.key.key_value, data->com.key.val);
148 break;
149 }
150 return;
151 }
152
153 static void
154 sbp2_print_dir(struct p1212_dir *dir)
155 {
156 switch(dir->com.key.key_type) {
157 case SBP2_KEYVALUE_Logical_Unit_Directory:
158 printf("Logical Unit\n");
159 break;
160 default:
161 printf("Unknown SBP2 key and value: 0x%08x 0x%08x\n",
162 dir->com.key.key_value, dir->com.key.val);
163 break;
164 }
165 return;
166 }
167
168 #define VALID_SBP2_IMM(data) { \
169 if (data->com.key.key_type != P1212_KEYTYPE_Immediate) { \
170 DPRINTF(("Unknown SBP2 key and value: 0x%08x 0x%08x\n", \
171 data->com.key.key_value, data->com.key.val)); \
172 break; \
173 } \
174 }
175
176 struct sbp2 *
177 sbp2_init(struct ieee1394_softc *sc, struct p1212_dir *udir)
178 {
179 struct sbp2 *sbp2;
180 struct sbp2_map *sbp2_map;
181 struct p1212_data *data;
182 struct p1212_dir *dir;
183 struct sbp2_lun *lun;
184 u_int32_t *luns;
185 int32_t cmd_spec_id, cmd_set, cmd_set_rev;
186 int i, luncnt, found;
187
188 sbp2 = malloc(sizeof (struct sbp2), M_1394DATA, M_WAITOK|M_ZERO);
189 luns = NULL;
190 luncnt = 0;
191
192 sbp2->sc = sc;
193 sc->sc1394_callback.sc1394_reset = sbp2_relogin;
194 sc->sc1394_callback.sc1394_resetarg = sbp2;
195 simple_lock_init(&sbp2->orblist_lock);
196
197 found = 0;
198 simple_lock(&sbp2_maps_lock);
199 if (!TAILQ_EMPTY(&sbp2_maps)) {
200 TAILQ_FOREACH(sbp2_map, &sbp2_maps, map_list) {
201 if (sbp2_map->sc_bus ==
202 (struct ieee1394_softc *)sc->sc1394_dev.dv_parent) {
203 sbp2_map->refcnt++;
204 found = 1;
205 sbp2->map = sbp2_map;
206 break;
207 }
208 }
209 }
210 simple_unlock(&sbp2_maps_lock);
211 if (!found) {
212 sbp2_map = malloc(sizeof (struct sbp2_map), M_1394DATA,
213 M_WAITOK|M_ZERO);
214 simple_lock_init(&sbp2_map->maplock);
215 simple_lock(&sbp2_map->maplock);
216 simple_lock(&sbp2_maps_lock);
217 TAILQ_INSERT_TAIL(&sbp2_maps, sbp2_map, map_list);
218 simple_unlock(&sbp2_maps_lock);
219 sbp2_map->sc_bus =
220 (struct ieee1394_softc *)sc->sc1394_dev.dv_parent;
221 sbp2_map->refcnt = 1;
222 sbp2->map = sbp2_map;
223 simple_unlock(&sbp2_map->maplock);
224
225 status_orb.cmd.ab_addr = sbp2_alloc_addr(sbp2);
226 status_orb.cmd.ab_length = SBP2_STATUS_SIZE;
227 status_orb.cmd.ab_data = malloc(SBP2_STATUS_SIZE, M_1394DATA,
228 M_WAITOK|M_ZERO);
229 status_orb.cmd.ab_req = sc;
230 status_orb.cmd.ab_cb = sbp2_orb_resp;
231 status_orb.cmd.ab_cbarg = &status_orb;
232 status_orb.cmd.ab_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK;
233 status_orb.state = SBP2_ORB_STATUS_STATE;
234 status_orb.sbp2 = sbp2;
235 sc->sc1394_callback.sc1394_inreg(&status_orb.cmd, 0);
236 }
237
238 TAILQ_INIT(&sbp2->luns);
239 CIRCLEQ_INIT(&sbp2->orbs);
240
241 TAILQ_FOREACH(data, &udir->data_root, data) {
242 switch (data->com.key.key_value) {
243 case SBP2_KEYVALUE_Command_Set_Spec_Id:
244 VALID_SBP2_IMM(data);
245 sbp2->cmd_spec_id = data->com.key.val;
246 data->print = sbp2_print_data;
247 break;
248 case SBP2_KEYVALUE_Command_Set:
249 VALID_SBP2_IMM(data);
250 sbp2->cmd_set = data->com.key.val;
251 data->print = sbp2_print_data;
252 break;
253 case SBP2_KEYVALUE_Unit_Characteristics:
254 VALID_SBP2_IMM(data);
255 sbp2->orb_size = (data->com.key.val & 0xff);
256 sbp2->orb_timeout = ((data->com.key.val >> 8) & 0xff);
257 data->print = sbp2_print_data;
258 break;
259 case SBP2_KEYVALUE_Command_Set_Revision:
260 VALID_SBP2_IMM(data);
261 sbp2->cmd_set_rev = data->com.key.val;
262 data->print = sbp2_print_data;
263 break;
264 case SBP2_KEYVALUE_Firmware_Revision:
265 VALID_SBP2_IMM(data);
266 sbp2->firmware_rev = data->com.key.val;
267 data->print = sbp2_print_data;
268 break;
269 case SBP2_KEYVALUE_Reconnect_Timeout:
270 VALID_SBP2_IMM(data);
271 sbp2->max_reconnect = (data->com.key.val & 0xffff);
272 data->print = sbp2_print_data;
273 break;
274 case SBP2_KEYVALUE_Logical_Unit_Number:
275 /*
276 * This is either lun or management reg offset
277 * depending on type.
278 */
279
280 if (data->com.key.key_type == P1212_KEYTYPE_Immediate) {
281
282 /* Save until done with data entries. */
283 luncnt++;
284 luns = realloc(luns, sizeof(u_int32_t) * luncnt,
285 M_1394DATA, M_WAITOK);
286 luns[luncnt - 1] = data->com.key.val;
287 data->print = sbp2_print_data;
288 }
289 if (data->com.key.key_type == P1212_KEYTYPE_Offset) {
290 if (data->com.key.val < SBP2_MIN_MGMT_OFFSET) {
291 DPRINTF(("Management reg offset too "
292 "small: 0x%08x\n",
293 data->com.key.val));
294 break;
295 }
296 sbp2->mgmtreg = (data->com.key.val * 4) +
297 CSR_BASE;
298 data->print = sbp2_print_data;
299 }
300 break;
301 case SBP2_KEYVALUE_Unit_Unique_Id:
302 if (data->com.key.key_type != P1212_KEYTYPE_Leaf) {
303 DPRINTF(("Unknown SBP2 key and value: "
304 "0x%08x 0x%08x\n", \
305 data->com.key.key_value,
306 data->com.key.val)); \
307 break;
308 }
309 #ifdef DIAGNOSTIC
310 if (data->leafdata == NULL) {
311 printf ("sbp2: No leaf data?\n");
312 break;
313 }
314 if (data->leafdata->len != 2) {
315 printf ("sbp2: Unique ID must be length 2\n");
316 break;
317 }
318 #endif
319 memcpy (&sbp2->uniq_id, &data->leafdata->data[0], 4);
320 memcpy (&sbp2->uniq_id+4, &data->leafdata->data[1], 4);
321 data->print = sbp2_print_data;
322 break;
323 default:
324 break;
325 }
326 }
327
328 for (i = 0; i < luncnt; i++) {
329 lun = sbp2_alloc_lun(luns[i], sbp2->orb_size,
330 sbp2->cmd_spec_id, sbp2->cmd_set, sbp2->cmd_set_rev);
331 sbp2->luncnt++;
332 TAILQ_INSERT_TAIL(&sbp2->luns, lun, lun_list);
333 }
334 free(luns, M_1394DATA);
335
336 /*
337 * A little complicated since entries can come in any order in a ROM
338 * directory.
339 *
340 * For each logical unit directory, scan it for overriding command set
341 * values. Then go back and for each logical unit found setup a lun
342 * with the appropriate default or overriden cmd_set values.
343 */
344
345 TAILQ_FOREACH(dir, &udir->subdir_root, dir) {
346 if (dir->com.key.key_value ==
347 SBP2_KEYVALUE_Logical_Unit_Directory) {
348 dir->print = sbp2_print_dir;
349 cmd_spec_id = -1;
350 cmd_set = -1;
351 cmd_set_rev = -1;
352 TAILQ_FOREACH(data, &dir->data_root, data) {
353 switch(data->com.key.key_value) {
354 case SBP2_KEYVALUE_Command_Set_Spec_Id:
355 cmd_spec_id = data->com.key.val;
356 data->print = sbp2_print_data;
357 break;
358 case SBP2_KEYVALUE_Command_Set:
359 cmd_set = data->com.key.val;
360 data->print = sbp2_print_data;
361 break;
362 case SBP2_KEYVALUE_Command_Set_Revision:
363 cmd_set_rev = data->com.key.val;
364 data->print = sbp2_print_data;
365 break;
366 default:
367 break;
368 }
369 }
370 if (cmd_spec_id == -1)
371 cmd_spec_id = sbp2->cmd_spec_id;
372 if (cmd_set == -1)
373 cmd_set = sbp2->cmd_set;
374 if (cmd_set_rev == -1)
375 cmd_set_rev = sbp2->cmd_set_rev;
376
377 TAILQ_FOREACH(data, &dir->data_root, data) {
378 if (data->com.key.key_value ==
379 SBP2_KEYVALUE_Logical_Unit_Number) {
380 lun = sbp2_alloc_lun(data->com.key.val,
381 sbp2->orb_size, cmd_spec_id,
382 cmd_set, cmd_set_rev);
383 TAILQ_INSERT_TAIL(&sbp2->luns, lun,
384 lun_list);
385 sbp2->luncnt++;
386 data->print = sbp2_print_data;
387 }
388 }
389 }
390 }
391 return sbp2;
392 }
393
394 #undef VALID_SBP2_IMM
395
396 static struct sbp2_lun *
397 sbp2_alloc_lun(u_int32_t luninfo, u_int32_t orb_size, u_int32_t cmd_spec_id,
398 u_int32_t cmd_set, u_int32_t cmd_set_rev)
399 {
400 struct sbp2_lun *lun;
401
402 lun = malloc(sizeof(struct sbp2_lun), M_1394DATA, M_WAITOK|M_ZERO);
403
404 lun->cmd_spec_id = cmd_spec_id;
405 lun->cmd_set = cmd_set;
406 lun->cmd_set_rev = cmd_set_rev;
407
408 lun->lun = luninfo & 0xffff;
409 lun->ordered = ((luninfo >> 22) & 0x1);
410 lun->dev_type = ((luninfo >> 16) & 0x1f);
411 lun->command.ab_data = malloc(orb_size, M_1394DATA, M_WAITOK|M_ZERO);
412 lun->doorbell.ab_data = malloc(orb_size, M_1394DATA, M_WAITOK|M_ZERO);
413 lun->status.ab_data = malloc(orb_size, M_1394DATA, M_WAITOK|M_ZERO);
414 return lun;
415 }
416
417 static void
418 sbp2_login(struct sbp2 *sbp2, struct sbp2_lun *lun)
419 {
420 struct sbp2_orb *orb;
421 u_int64_t respaddr, orbaddr;
422
423 orb = sbp2_alloc_orb();
424
425 lun->command.ab_length = 8;
426 lun->command.ab_req = sbp2->sc;
427 lun->command.ab_cb = sbp2_null_resp;
428 lun->command.ab_cbarg = sbp2;
429
430 orbaddr = sbp2_alloc_addr(sbp2);
431 lun->command.ab_addr = sbp2->mgmtreg;
432 lun->command.ab_data[0] = IEEE1394_CREATE_ADDR_HIGH(orbaddr);
433 lun->command.ab_data[1] = IEEE1394_CREATE_ADDR_LOW(orbaddr);
434 lun->command.ab_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK;
435
436 respaddr = sbp2_alloc_addr(sbp2);
437 orb->cmd.ab_req = sbp2->sc;
438 orb->cmd.ab_length = SBP2_LOGIN_SIZE;
439 orb->cmd.ab_tcode = IEEE1394_TCODE_READ_REQ_BLOCK;
440 orb->cmd.ab_data[0] = 0;
441 orb->cmd.ab_data[1] = 0;
442 orb->cmd.ab_data[2] = IEEE1394_CREATE_ADDR_HIGH(respaddr);
443 orb->cmd.ab_data[3] = IEEE1394_CREATE_ADDR_LOW(respaddr);
444 orb->cmd.ab_data[4] |= SBP2_LOGIN_SET_EXCLUSIVE;
445 orb->cmd.ab_data[4] |= SBP2_ORB_NOTIFY_MASK;
446
447 /* Ask for reasonable reconnect time. */
448 orb->cmd.ab_data[4] |= SBP2_LOGIN_SET_RECONNECT(SBP2_RECONNECT);
449 orb->cmd.ab_data[4] |= lun->loginid;
450 orb->cmd.ab_data[4] = htonl(orb->cmd.ab_data[4]);
451
452 /* Allow max login response. */
453 orb->cmd.ab_data[5] = htonl(SBP2_LOGIN_MAX_RESP);
454 orb->cmd.ab_data[6] = IEEE1394_CREATE_ADDR_HIGH(status_orb.cmd.ab_addr);
455 orb->cmd.ab_data[7] = IEEE1394_CREATE_ADDR_LOW(status_orb.cmd.ab_addr);
456
457 orb->cmd.ab_addr = orbaddr;
458 orb->cmd.ab_cb = sbp2_login_ans;
459 orb->cmd.ab_cbarg = orb;
460 orb->sbp2 = sbp2;
461
462 lun->doorbell.ab_addr = respaddr;
463 lun->doorbell.ab_length = SBP2_LOGIN_MAX_RESP;
464 lun->doorbell.ab_data = malloc (SBP2_LOGIN_MAX_RESP, M_1394DATA,
465 M_WAITOK|M_ZERO);
466 lun->doorbell.ab_req = sbp2->sc;
467 lun->doorbell.ab_cb = sbp2_login_resp;
468 lun->doorbell.ab_cbarg = lun;
469 lun->doorbell.ab_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK;
470
471 sbp2->sc->sc1394_callback.sc1394_inreg(&orb->cmd, 0);
472 sbp2->sc->sc1394_callback.sc1394_inreg(&lun->doorbell, 0);
473 sbp2->sc->sc1394_callback.sc1394_write(&lun->command);
474
475 simple_lock(&sbp2->orblist_lock);
476 orb = sbp2_alloc_orb();
477 orb->cmd.ab_addr = sbp2_alloc_addr(sbp2);
478 orb->cmd.ab_req = sbp2->sc;
479 orb->cmd.ab_tcode = IEEE1394_TCODE_READ_REQ_BLOCK;
480 orb->cmd.ab_length = (sbp2->orb_size * 4);
481 orb->cmd.ab_data[0] = htonl(SBP2_ORB_NULL_POINTER);
482 orb->cmd.ab_data[4] = htonl(SBP2_ORB_FMT_DUMMY_MASK);
483
484 /*
485 * Go ahead and set the notify bit. Some SBP2 devices always
486 * seem to return status on a dummy orb regardless so don't 2nd guess.
487 */
488
489 orb->cmd.ab_data[4] |= htonl(SBP2_ORB_NOTIFY_MASK);
490 orb->cmd.ab_subok = 1;
491 orb->cmd.ab_cb = sbp2_orb_resp;
492 orb->cmd.ab_cbarg = orb;
493 orb->sbp2 = sbp2;
494
495 orb->cb = sbp2_status_resp;
496 CIRCLEQ_INSERT_HEAD(&sbp2->orbs, orb, orb_list);
497 simple_unlock(&sbp2->orblist_lock);
498 sbp2->sc->sc1394_callback.sc1394_inreg(&orb->cmd, 0);
499
500 return;
501 }
502
503 static void
504 sbp2_login_ans(struct ieee1394_abuf *ab, int rcode)
505 {
506 struct ieee1394_softc *sc = ab->ab_req;
507 struct sbp2_orb *orb = ab->ab_cbarg;
508
509 /* Got a read so allocate the buffer and write out the response. */
510
511 if (orb->state != SBP2_ORB_INIT_STATE) {
512 orb->cmd.ab_tcode = IEEE1394_TCODE_READ_REQ_BLOCK;
513 sbp2_free_orb(orb);
514 return;
515 }
516
517 if (rcode) {
518 DPRINTF(("sbp2_login: Bad return code: %d\n", rcode));
519 orb->cmd.ab_tcode = IEEE1394_TCODE_READ_REQ_BLOCK;
520 sbp2_free_orb(orb);
521 return;
522 }
523
524 orb->cmd.ab_tcode = IEEE1394_TCODE_READ_RESP_BLOCK;
525 orb->state = SBP2_ORB_SENT_STATE;
526 sc->sc1394_callback.sc1394_write(&orb->cmd);
527 return;
528 }
529
530 static void
531 sbp2_login_resp(struct ieee1394_abuf *ab, int rcode)
532 {
533 struct ieee1394_softc *sc = ab->ab_req;
534 struct sbp2_lun *lun = ab->ab_cbarg;
535 struct sbp2_orb *orb;
536 struct sbp2 *sbp2 = lun->command.ab_cbarg;
537
538 #ifdef SBP2_DEBUG
539 int i;
540 #endif
541
542 sc->sc1394_callback.sc1394_unreg(&lun->doorbell, 1);
543
544 if (rcode) {
545 DPRINTF(("Bad return code: %d\n", rcode));
546 return;
547 }
548
549 DPRINTF(("csr: 0x%016qx\n", (quad_t)ab->ab_addr));
550 #ifdef SBP2_DEBUG
551 if (sbp2debug > 2)
552 for (i = 0; i < (ab->ab_retlen / 4); i++)
553 DPRINTF(("%d: 0x%08x\n", i, ntohl(ab->ab_data[i])));
554 #endif
555
556 lun->cmdreg = SBP2_LOGINRESP_CREATE_CMDREG(ntohl(ab->ab_data[1]),
557 ntohl(ab->ab_data[2]));
558 if (SBP2_LOGINRESP_GET_LENGTH(ntohl(ab->ab_data[0])) ==
559 SBP2_LOGIN_MAX_RESP)
560 lun->reconnect =
561 SBP2_LOGINRESP_GET_RECONNECT(ntohl(ab->ab_data[3]));
562 lun->loginid = SBP2_LOGINRESP_GET_LOGINID(ntohl(ab->ab_data[0]));
563 lun->login_flag = SBP2_LOGGED_IN;
564
565 lun->doorbell.ab_addr = lun->cmdreg + SBP2_CMDREG_AGENT_RESET;
566 lun->doorbell.ab_length = 4;
567 lun->doorbell.ab_req = sc;
568 lun->doorbell.ab_cb = sbp2_enable_status;
569 lun->doorbell.ab_cbarg = lun;
570 lun->doorbell.ab_tcode = IEEE1394_TCODE_WRITE_REQ_QUAD;
571 lun->doorbell.ab_data[0] = 0xffffffff;
572
573 /*
574 * Reset the state engine, plug the address of the first orb into
575 * the orb pointer and off we go.
576 */
577
578 lun->command.ab_addr = lun->cmdreg + SBP2_CMDREG_ORB_POINTER;
579 lun->command.ab_length = 8;
580 lun->command.ab_req = sc;
581 lun->command.ab_cb = sbp2_doorbell_reset;
582 lun->command.ab_cbarg = lun;
583 lun->command.ab_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK;
584 simple_lock(&sbp2->orblist_lock);
585 orb = CIRCLEQ_LAST(&sbp2->orbs);
586 simple_lock(&orb->orb_lock);
587 lun->command.ab_data[0] = IEEE1394_CREATE_ADDR_HIGH(orb->cmd.ab_addr);
588 lun->command.ab_data[1] = IEEE1394_CREATE_ADDR_LOW(orb->cmd.ab_addr);
589 simple_unlock(&orb->orb_lock);
590 simple_unlock(&sbp2->orblist_lock);
591 sc->sc1394_callback.sc1394_write(&lun->doorbell);
592 sc->sc1394_callback.sc1394_write(&lun->command);
593 lun->state = SBP2_STATE_ACTIVE;
594
595 return;
596 }
597
598 static void
599 sbp2_enable_status(struct ieee1394_abuf *ab, int rcode)
600 {
601 struct sbp2_lun *lun = ab->ab_cbarg;
602
603 lun->doorbell.ab_cb = sbp2_doorbell_reset;
604 lun->doorbell.ab_addr = lun->cmdreg +
605 SBP2_CMDREG_UNSOLICITED_STATUS_ENABLE;
606 ab->ab_req->sc1394_callback.sc1394_write(&lun->doorbell);
607 return;
608 }
609
610 static void
611 sbp2_doorbell_reset(struct ieee1394_abuf *ab, int rcode)
612 {
613 struct sbp2_lun *lun = ab->ab_cbarg;
614
615 if (lun->cmdreg)
616 lun->doorbell.ab_addr = lun->cmdreg + SBP2_CMDREG_DOORBELL;
617 return;
618 }
619
620 static void
621 sbp2_null_resp(struct ieee1394_abuf *ab, int rcode)
622 {
623 return;
624 }
625
626 static void
627 sbp2_status_resp(struct sbp2_status *status, void *arg)
628 {
629 DPRINTFN(1, ("Got a status response in sbp2_status_resp\n"));
630 DPRINTFN(1, ("status: resp 0x%04x, sbp_status 0x%04x\n", status->resp,
631 status->sbp_status));
632 }
633
634 int
635 sbp2_match(struct p1212_dir *udir)
636 {
637 struct p1212_key **keys;
638
639 keys = p1212_find(udir, P1212_KEYTYPE_Immediate,
640 P1212_KEYVALUE_Unit_Spec_Id, 0);
641 if (keys && keys[0]->val == SBP2_UNIT_SPEC_ID) {
642 keys = p1212_find(udir, P1212_KEYTYPE_Immediate,
643 P1212_KEYVALUE_Unit_Sw_Version, 0);
644 if (keys && keys[0]->val == SBP2_UNIT_SW_VERSION)
645 return 1;
646 }
647 return 0;
648 }
649
650 static void
651 sbp2_logout(struct sbp2 *sbp2, struct sbp2_lun *lun)
652 {
653 DPRINTF(("Called sbp2_logout\n"));
654 return;
655 }
656
657 void
658 sbp2_free(struct sbp2 *sbp2)
659 {
660 struct sbp2_orb *orb;
661 struct sbp2_lun *lun;
662
663 while (!CIRCLEQ_EMPTY(&sbp2->orbs)) {
664 orb = CIRCLEQ_FIRST(&sbp2->orbs);
665 (void)sbp2_abort(orb);
666 }
667 while (TAILQ_FIRST(&sbp2->luns) != NULL) {
668 lun = TAILQ_FIRST(&sbp2->luns);
669 TAILQ_REMOVE(&sbp2->luns, lun, lun_list);
670 if (lun->login_flag)
671 sbp2_logout(sbp2, lun);
672 free(lun, M_1394DATA);
673 }
674 simple_lock(&sbp2_maps_lock);
675 if (!--sbp2->map->refcnt) {
676 TAILQ_REMOVE(&sbp2_maps, sbp2->map, map_list);
677 free(sbp2->map, M_1394DATA);
678 }
679 simple_unlock(&sbp2_maps_lock);
680 sbp2->sc->sc1394_callback.sc1394_unreg(&status_orb.cmd, 1);
681 free(status_orb.cmd.ab_data, M_1394DATA);
682 }
683
684 #ifdef FW_DEBUG
685 extern int fwdebug;
686 #endif
687
688 void *
689 sbp2_runcmd(struct sbp2 *sbp2, struct sbp2_cmd *cmd)
690 {
691 #ifdef DIAGNOSTIC
692 int found = 0;
693 #endif
694 struct sbp2_orb *orb, *toporb;
695 struct ieee1394_softc *psc =
696 (struct ieee1394_softc *) sbp2->sc->sc1394_dev.dv_parent;
697 struct sbp2_lun *lun;
698 struct uio io;
699 struct iovec iov;
700 u_int32_t t;
701 u_int64_t addr;
702
703 #if defined(FW_DEBUG) && defined(SBP2_DEBUG)
704 if (sbp2debug > 2)
705 fwdebug = 3;
706 #endif
707 TAILQ_FOREACH(lun, &sbp2->luns, lun_list)
708 if (lun->lun == cmd->lun) {
709 #ifdef DIAGNOSTIC
710 found = 1;
711 #endif
712 break;
713 }
714
715 #ifdef DIAGNOSTIC
716 if (!found) {
717 DPRINTF(("Got a request for an invalid lun: %d\n", cmd->lun));
718 return NULL;
719 }
720 if (cmd->cmdlen % 4) {
721 DPRINTF(("cmdlen is not 4 byte aligned: %d\n", cmd->cmdlen));
722 return NULL;
723 }
724 if ((cmd->cmdlen / 4) > (sbp2->orb_size - 5)) {
725 DPRINTF(("cmdlen too large: len - %d max - %d\n",
726 cmd->cmdlen / 4, sbp2->orb_size - 5));
727 return NULL;
728 }
729 #endif
730 if (lun->login_flag != SBP2_LOGGED_IN)
731 sbp2_login(sbp2, lun);
732
733 orb = sbp2_alloc_orb();
734
735 orb->cmd.ab_addr = sbp2_alloc_addr(sbp2);
736 orb->cb = cmd->cb;
737 orb->cb_arg = cmd->cb_arg;
738 orb->cmd.ab_subok = 1;
739
740 orb->cmd.ab_req = sbp2->sc;
741 orb->cmd.ab_tcode = IEEE1394_TCODE_READ_REQ_BLOCK;
742 orb->cmd.ab_length = (sbp2->orb_size * 4);
743 orb->cmd.ab_data[0] = htonl(SBP2_ORB_NULL_POINTER);
744 orb->cmd.ab_data[4] |= SBP2_ORB_NOTIFY_MASK;
745
746 if (cmd->rw == SBP_WRITE)
747 orb->cmd.ab_data[4] |= SBP2_ORB_RW_MASK;
748 orb->cmd.ab_data[4] |= SBP2_ORB_SET_SPEED(sbp2->sc->sc1394_link_speed);
749 orb->cmd.ab_data[4] = htonl(orb->cmd.ab_data[4]);
750
751 memcpy(&orb->cmd.ab_data[5], cmd->cmd, cmd->cmdlen);
752
753 orb->cmd.ab_cb = sbp2_orb_resp;
754 orb->cmd.ab_cbarg = orb;
755 orb->lun = lun;
756 orb->sbp2 = sbp2;
757
758 if (cmd->data) {
759 if ((cmd->datalen == 0) || (cmd->datalen > SBP2_MAXPHYS)) {
760 /* Handle uio and large data chunks via page tables. */
761 if (cmd->datalen) {
762 io.uio_iov = &iov;
763 io.uio_iovcnt = 1;
764 io.uio_offset = 0;
765 io.uio_resid = cmd->datalen;
766 io.uio_segflg = UIO_SYSSPACE;
767 if (cmd->rw == SBP_WRITE)
768 io.uio_rw = UIO_WRITE;
769 else
770 io.uio_rw = UIO_READ;
771 io.uio_procp = NULL;
772 iov.iov_base = cmd->data;
773 iov.iov_len = cmd->datalen;
774 orb->pt = sbp2_alloc_pt(&io, cmd->rw, orb);
775 } else
776 orb->pt =
777 sbp2_alloc_pt((struct uio *)cmd->data,
778 cmd->rw, orb);
779 if (orb->pt == NULL) {
780 sbp2_free_orb (orb);
781 return NULL;
782 }
783 orb->cmd.ab_data[2] =
784 IEEE1394_CREATE_ADDR_HIGH(orb->pt->pt_ent.ab_addr);
785 orb->cmd.ab_data[2] |=
786 htonl((0xffc0 | psc->sc1394_node_id) << 16);
787 orb->cmd.ab_data[3] =
788 IEEE1394_CREATE_ADDR_LOW(orb->pt->pt_ent.ab_addr);
789 t = SBP2_ORB_SET_MAXTRANS(sbp2->sc->sc1394_link_speed);
790 orb->cmd.ab_data[4] |= htonl(t);
791 orb->cmd.ab_data[4] |= htonl(SBP2_ORB_PAGETABLE_MASK);
792 orb->cmd.ab_data[4] |= htonl(orb->pt->pt_cnt);
793 } else {
794 sbp2_alloc_data_mapping(sbp2, &orb->data_map, cmd->data,
795 cmd->datalen, cmd->rw);
796 orb->data_map.orb = orb;
797 orb->data.ab_length = cmd->datalen;
798 orb->data.ab_addr = orb->data_map.fwaddr;
799 orb->data.ab_cb = sbp2_data_resp;
800 orb->data.ab_cbarg = &orb->data_map;
801 orb->data.ab_data = (u_int32_t *)cmd->data;
802 orb->data.ab_req = sbp2->sc;
803 if (cmd->rw == SBP_WRITE)
804 orb->data.ab_tcode =
805 IEEE1394_TCODE_WRITE_REQ_BLOCK;
806 else
807 orb->data.ab_tcode =
808 IEEE1394_TCODE_READ_REQ_BLOCK;
809 orb->cmd.ab_data[2] =
810 IEEE1394_CREATE_ADDR_HIGH(orb->data.ab_addr);
811 orb->cmd.ab_data[2] |=
812 htonl((0xffc0 | psc->sc1394_node_id) << 16);
813 orb->cmd.ab_data[3] =
814 IEEE1394_CREATE_ADDR_LOW(orb->data.ab_addr);
815 t = SBP2_ORB_SET_MAXTRANS(sbp2->sc->sc1394_link_speed);
816 orb->cmd.ab_data[4] |= htonl(t);
817 orb->cmd.ab_data[4] |= htonl(cmd->datalen);
818 sbp2->sc->sc1394_callback.sc1394_inreg(&orb->data, 1);
819 }
820 }
821
822 simple_lock(&sbp2->orblist_lock);
823 toporb = CIRCLEQ_FIRST(&sbp2->orbs);
824 simple_lock(&toporb->orb_lock);
825 addr = orb->cmd.ab_addr;
826 toporb->cmd.ab_data[0] = IEEE1394_CREATE_ADDR_HIGH(addr);
827 toporb->cmd.ab_data[1] = IEEE1394_CREATE_ADDR_LOW(addr);
828 sbp2->sc->sc1394_callback.sc1394_inreg(&orb->cmd, 0);
829 if ((lun->state == SBP2_STATE_SUSPENDED) ||
830 ((lun->state == SBP2_STATE_ACTIVE) &&
831 (toporb->state != SBP2_ORB_INIT_STATE))) {
832 DPRINTFN(1, ("Ringing doorbell\n"));
833 toporb->state = SBP2_ORB_INIT_STATE;
834 toporb->db = 1;
835 toporb->dback = 0;
836 sbp2->sc->sc1394_callback.sc1394_write(&lun->doorbell);
837 } else if (lun->state == SBP2_STATE_DEAD) {
838 CIRCLEQ_FOREACH(toporb, &orb->sbp2->orbs, orb_list) {
839 toporb->ack = 0;
840 toporb->status_rec = 0;
841 toporb->db = 0;
842 toporb->dback = 0;
843 }
844 toporb = CIRCLEQ_LAST(&sbp2->orbs);
845 lun->doorbell.ab_addr = lun->cmdreg + SBP2_CMDREG_AGENT_RESET;
846 lun->doorbell.ab_cb = sbp2_enable_status;
847 lun->command.ab_data[0] =
848 IEEE1394_CREATE_ADDR_HIGH(toporb->cmd.ab_addr);
849 lun->command.ab_data[1] =
850 IEEE1394_CREATE_ADDR_LOW(toporb->cmd.ab_addr);
851 toporb->state = SBP2_ORB_INIT_STATE;
852 sbp2->sc->sc1394_callback.sc1394_write(&lun->doorbell);
853 sbp2->sc->sc1394_callback.sc1394_write(&lun->command);
854 }
855 lun->state = SBP2_STATE_ACTIVE;
856
857 CIRCLEQ_INSERT_HEAD(&sbp2->orbs, orb, orb_list);
858 simple_unlock(&toporb->orb_lock);
859 simple_unlock(&sbp2->orblist_lock);
860
861 return orb;
862 }
863
864 #ifdef SBP2_DEBUG
865 static void
866 sbp2_agent_status(struct ieee1394_abuf *abuf, int status)
867 {
868 DPRINTF(("sbp2_agent_status: 0x%08x\n", ntohl(abuf->ab_data[0])));
869 return;
870 }
871 #endif
872
873 static void
874 sbp2_orb_resp(struct ieee1394_abuf *abuf, int status)
875 {
876 struct sbp2_orb *statorb, *orb;
877 u_int64_t addr;
878 int found = 0;
879 u_int32_t t;
880
881 orb = abuf->ab_cbarg;
882
883 DPRINTFN(1, ("orb addr: 0x%016qx\n", orb->cmd.ab_addr));
884 DPRINTFN(1, ("orb next ptr: 0x%08x%08x\n", ntohl(orb->cmd.ab_data[0]), ntohl(orb->cmd.ab_data[1])));
885 DPRINTFN(1, ("retlen: %d, length: %d\n", abuf->ab_retlen,
886 abuf->ab_length));
887
888 #ifdef SBP2_DEBUG
889 if ((sbp2debug > 3) && orb->lun) {
890 orb->lun->status.ab_addr =
891 orb->lun->cmdreg + SBP2_CMDREG_AGENT_STATE;
892 orb->lun->status.ab_cb = sbp2_agent_status;
893 orb->lun->status.ab_cbarg = orb->lun;
894 orb->lun->status.ab_length = 4;
895 orb->lun->status.ab_req = orb->sbp2->sc;
896 orb->lun->status.ab_tcode = IEEE1394_TCODE_READ_REQ_QUAD;
897 orb->sbp2->sc->sc1394_callback.sc1394_read(&orb->lun->status);
898 }
899 #endif
900 simple_lock(&orb->orb_lock);
901
902 switch (orb->state) {
903 case SBP2_ORB_INIT_STATE:
904 if (abuf->ab_tcode == IEEE1394_TCODE_READ_REQ_BLOCK) {
905 orb->state = SBP2_ORB_STATUS_STATE;
906 abuf->ab_tcode = IEEE1394_TCODE_READ_RESP_BLOCK;
907 abuf->ab_length = abuf->ab_retlen;
908 abuf->ab_req->sc1394_callback.sc1394_write(&orb->cmd);
909 break;
910 }
911
912 /* FALL THRU */
913
914 case SBP2_ORB_STATUS_STATE:
915
916 /*
917 * If it's not the fifo addr then just resend the orb out as
918 * the doorbell was rung to reread.
919 */
920
921 if (orb->cmd.ab_addr != status_orb.cmd.ab_addr) {
922 /* An ack from a write */
923
924 /*
925 * Change engine state once this has been processed
926 * and it's next pointer is the null pointer.
927 */
928
929 if ((orb->cmd.ab_data[0] ==
930 ntohl(SBP2_ORB_NULL_POINTER)) &&
931 (orb->lun->state == SBP2_STATE_ACTIVE))
932 orb->lun->state = SBP2_STATE_SUSPENDED;
933 if (orb->ack == 0)
934 orb->ack = 1;
935 else if ((orb->db == 1) && (orb->dback == 0))
936 orb->dback = 1;
937 else
938 panic ("Unknown packet received!");
939 } else {
940
941 /*
942 * The orb passed in is the generic status. Find the
943 * one it goes with so status can be filled in and
944 * passed back up.
945 */
946
947 addr = ntohl(abuf->ab_data[0]);
948 addr &= 0x0000ffff;
949 addr = (addr << 32);
950 addr |= ntohl(abuf->ab_data[1]);
951 simple_lock(&orb->sbp2->orblist_lock);
952 CIRCLEQ_FOREACH(statorb, &orb->sbp2->orbs, orb_list) {
953 if (addr == statorb->cmd.ab_addr) {
954 found = 1;
955 break;
956 }
957 }
958 simple_unlock(&orb->sbp2->orblist_lock);
959 simple_lock(&statorb->orb_lock);
960
961 /* XXX: Need to handle unsolicited correctly. */
962 if (SBP2_STATUS_GET_DEAD(ntohl(abuf->ab_data[0]))) {
963 DPRINTFN(1, ("Transitioning to dead state\n"));
964 statorb->lun->state = SBP2_STATE_DEAD;
965 }
966 if (!found) {
967 #ifdef SBP2_DEBUG
968 u_int32_t i = ntohl(abuf->ab_data[0]);
969 #endif
970 DPRINTF(("Got a status block for an unknown "
971 "orb addr: 0x%016qx\n", addr));
972 DPRINTF(("resp: 0x%x status: 0x%x len: 0x%x\n",
973 SBP2_STATUS_GET_RESP(i),
974 SBP2_STATUS_GET_STATUS(i),
975 SBP2_STATUS_GET_LEN(i) - 1));
976 return;
977 }
978
979 /*
980 * After it's been sent turn this into a dummy orb.
981 * That way if the engine stalls and has to be
982 * restarted this orb getting reread won't cause
983 * duplicate work.
984 */
985
986 statorb->cmd.ab_data[4] |=
987 htonl(SBP2_ORB_FMT_DUMMY_MASK);
988 statorb->status.resp =
989 SBP2_STATUS_GET_RESP(ntohl(abuf->ab_data[0]));
990 statorb->status.sbp_status =
991 SBP2_STATUS_GET_STATUS(ntohl(abuf->ab_data[0]));
992 statorb->status.datalen =
993 SBP2_STATUS_GET_LEN(ntohl(abuf->ab_data[0])) - 1;
994 if (statorb->status.datalen)
995 statorb->status.data = &abuf->ab_data[2];
996 if ((statorb->status.resp ==
997 SBP2_STATUS_TRANSPORT_FAIL) &&
998 (statorb->status.sbp_status ==
999 SBP2_STATUS_UNSPEC_ERROR)) {
1000 t = statorb->status.sbp_status;
1001 statorb->status.object =
1002 SBP2_STATUS_GET_OBJECT(t);
1003 statorb->status.bus_error =
1004 SBP2_STATUS_GET_BUS_ERROR(t);
1005 }
1006 statorb->status_rec = 1;
1007 simple_unlock(&statorb->orb_lock);
1008 statorb->cb(&statorb->status, statorb->cb_arg);
1009 statorb->cb = sbp2_status_resp;
1010 orb = statorb;
1011 }
1012
1013 /* If it's not the null pointer orb, free it. */
1014 simple_lock(&orb->orb_lock);
1015 if ((orb->cmd.ab_data[0] == ntohl(SBP2_ORB_NULL_POINTER)))
1016 break;
1017 /* Check conditions for free'ing an orb */
1018 if ((orb->status_rec == 0) || (orb->ack == 0) ||
1019 ((orb->db == 1) && (orb->dback == 0)))
1020 break;
1021 simple_lock(&orb->sbp2->orblist_lock);
1022
1023 /*
1024 * Always leave the last orb on the list so the doorbell can
1025 * be rang.
1026 */
1027
1028 if (orb != CIRCLEQ_FIRST(&orb->sbp2->orbs)) {
1029 orb->cmd.ab_tcode = IEEE1394_TCODE_READ_REQ_BLOCK;
1030
1031 CIRCLEQ_REMOVE(&orb->sbp2->orbs, orb, orb_list);
1032 simple_unlock(&orb->sbp2->orblist_lock);
1033 simple_unlock(&orb->orb_lock);
1034 sbp2_free_orb(orb);
1035 return;
1036 }
1037 simple_unlock(&orb->sbp2->orblist_lock);
1038 break;
1039 case SBP2_ORB_FREE_STATE:
1040 break;
1041 default:
1042 panic("Invalid orb state: %d\n", orb->state);
1043 break;
1044 }
1045 simple_unlock(&orb->orb_lock);
1046 }
1047
1048 static void
1049 sbp2_data_resp(struct ieee1394_abuf *abuf, int rcode)
1050 {
1051 struct sbp2_orb *orb;
1052 struct sbp2_mapping *data_map;
1053 u_int32_t offset;
1054 unsigned char *addr;
1055
1056 switch (abuf->ab_tcode) {
1057
1058 case IEEE1394_TCODE_WRITE_REQ_BLOCK:
1059 return;
1060 break;
1061 case IEEE1394_TCODE_READ_REQ_BLOCK:
1062 data_map = abuf->ab_cbarg;
1063 orb = data_map->orb;
1064
1065 simple_lock(&orb->orb_lock);
1066
1067 addr = data_map->laddr;
1068 offset = abuf->ab_retaddr - data_map->fwaddr;
1069
1070 orb->resp.ab_addr = abuf->ab_retaddr;
1071 orb->resp.ab_tcode = IEEE1394_TCODE_READ_RESP_BLOCK;
1072 orb->resp.ab_tlabel = abuf->ab_tlabel;
1073 orb->resp.ab_length = abuf->ab_retlen;
1074 orb->resp.ab_req = abuf->ab_req;
1075 orb->resp.ab_data = (u_int32_t *)(addr + offset);
1076 orb->resp.ab_cb = sbp2_null_resp;
1077 orb->resp.ab_cbarg = data_map;
1078 orb->sbp2->sc->sc1394_callback.sc1394_write(&orb->resp);
1079 simple_unlock(&orb->orb_lock);
1080 break;
1081 default:
1082 panic("Invalid tcode: 0x%0x\n", abuf->ab_tcode);
1083 }
1084 }
1085
1086 void *
1087 sbp2_abort(void *handle)
1088 {
1089 struct sbp2_orb *orb = handle;
1090 void *arg;
1091
1092 DPRINTF(("Called sbp2_abort\n"));
1093
1094 simple_lock(&orb->sbp2->orblist_lock);
1095 simple_lock(&orb->orb_lock);
1096
1097 arg = orb->cb_arg;
1098 CIRCLEQ_REMOVE(&orb->sbp2->orbs, orb, orb_list);
1099
1100 simple_unlock(&orb->orb_lock);
1101 simple_unlock(&orb->sbp2->orblist_lock);
1102
1103 sbp2_free_orb(orb);
1104
1105 return arg;
1106 }
1107
1108 static void
1109 sbp2_relogin(struct ieee1394_softc *sc, void *arg)
1110 {
1111 struct sbp2 *sbp2 = arg;
1112
1113 DPRINTF(("Called sbp2_relogin\n"));
1114 if (sbp2)
1115 return;
1116 }
1117
1118 void
1119 sbp2_reset_lun(struct sbp2 *sbp2, u_int16_t lun)
1120 {
1121 DPRINTF(("Called sbp2_reset_lun\n"));
1122 return;
1123 }
1124
1125 static struct sbp2_orb *
1126 sbp2_alloc_orb(void)
1127 {
1128 struct sbp2_orb *orb = NULL;
1129 int i;
1130
1131 simple_lock(&sbp2_freeorbs_lock);
1132 if (CIRCLEQ_EMPTY(&sbp2_freeorbs)) {
1133 DPRINTFN(2, ("Alloc'ing more orbs\n"));
1134 for (i = 0; i < SBP2_NUM_ALLOC; i++) {
1135 simple_unlock(&sbp2_freeorbs_lock);
1136 orb = malloc(sizeof(struct sbp2_orb), M_1394DATA,
1137 M_WAITOK|M_ZERO);
1138 orb->cmd.ab_data = malloc(SBP2_MAX_ORB, M_1394DATA,
1139 M_WAITOK|M_ZERO);
1140 simple_lock_init(&orb->orb_lock);
1141 simple_lock(&sbp2_freeorbs_lock);
1142 CIRCLEQ_INSERT_TAIL(&sbp2_freeorbs, orb, orb_list);
1143 }
1144 simple_unlock(&sbp2_freeorbs_lock);
1145 orb = malloc(sizeof(struct sbp2_orb), M_DEVBUF,
1146 M_WAITOK|M_ZERO);
1147 orb->cmd.ab_data = malloc(SBP2_MAX_ORB, M_1394DATA,
1148 M_WAITOK|M_ZERO);
1149 simple_lock_init(&orb->orb_lock);
1150 return orb;
1151 } else {
1152 orb = CIRCLEQ_FIRST(&sbp2_freeorbs);
1153 CIRCLEQ_REMOVE(&sbp2_freeorbs, orb, orb_list);
1154 }
1155 simple_unlock(&sbp2_freeorbs_lock);
1156 orb->state = SBP2_ORB_INIT_STATE;
1157 return orb;
1158 }
1159
1160 static void
1161 sbp2_free_orb(struct sbp2_orb *orb)
1162 {
1163
1164 simple_lock(&orb->orb_lock);
1165 DPRINTFN(2, ("Freeing orb at addr: 0x%016qx status_rec: 0x%0x\n",
1166 orb->cmd.ab_addr, orb->status_rec));
1167 orb->sbp2->sc->sc1394_callback.sc1394_unreg(&orb->cmd, 0);
1168 if (orb->data_map.laddr) {
1169 orb->sbp2->sc->sc1394_callback.sc1394_unreg(&orb->data, 1);
1170 sbp2_free_data_mapping(orb->sbp2, &orb->data_map);
1171 }
1172 if (orb->pt)
1173 sbp2_free_pt(orb->pt);
1174
1175 sbp2_free_addr(orb->sbp2, orb->cmd.ab_addr);
1176
1177 simple_lock(&sbp2_freeorbs_lock);
1178 memset(orb->cmd.ab_data, 0, SBP2_MAX_ORB);
1179 memset(&orb->status, 0, sizeof(struct sbp2_status));
1180 memset(&orb->data_map, 0, sizeof(struct sbp2_mapping));
1181 orb->sbp2 = NULL;
1182 orb->pt = NULL;
1183 orb->lun = NULL;
1184 orb->cb = NULL;
1185 orb->cb_arg = NULL;
1186 orb->status_rec = 0;
1187 orb->db = 0;
1188 orb->dback = 0;
1189 orb->ack = 0;
1190 orb->state = SBP2_ORB_FREE_STATE;
1191 CIRCLEQ_INSERT_TAIL(&sbp2_freeorbs, orb, orb_list);
1192 simple_unlock(&sbp2_freeorbs_lock);
1193 simple_unlock(&orb->orb_lock);
1194 }
1195
1196 static void
1197 sbp2_alloc_data_mapping(struct sbp2 *sbp2, struct sbp2_mapping *map,
1198 u_char *data, u_int32_t datalen, u_int8_t rw)
1199 {
1200 int byte, bitpos, found;
1201 u_int32_t size, count, startbyte, startbit;
1202 unsigned char bit;
1203
1204 size = datalen / SBP_DATA_BLOCK_SIZE;
1205 if (datalen % SBP_DATA_BLOCK_SIZE)
1206 size++;
1207
1208 map->laddr = data;
1209 map->size = datalen;
1210 map->rw = rw;
1211
1212 simple_lock(&sbp2->map->maplock);
1213 count = found = 0;
1214 startbyte = 0;
1215 startbit = 0;
1216 for (byte = 0; byte < sizeof(sbp2->map->datamap); byte++) {
1217 for (bitpos = 0; bitpos < CHAR_BIT; bitpos++) {
1218 bit = 0x1 << bitpos;
1219 if ((sbp2->map->datamap[byte] & bit) == 0) {
1220 if (++count == size) {
1221 found = 1;
1222 break;
1223 }
1224 } else {
1225 count = 0;
1226 if (bitpos != (CHAR_BIT - 1)) {
1227 startbyte = byte;
1228 startbit = bitpos + 1;
1229 } else {
1230 startbyte = byte + 1;
1231 startbit = 0;
1232 }
1233 }
1234 }
1235 if (found)
1236 break;
1237 }
1238
1239 /* Gets a little complicated to handle crossing bytes on the ends. */
1240
1241 /* Handle the bits on the front end if they start in the middle */
1242 if (startbit) {
1243 count = CHAR_BIT - startbit;
1244 if (size < count)
1245 count = size;
1246 for (bitpos = 0; bitpos < count; bitpos++) {
1247 bit = 0x1 << (bitpos + startbit);
1248 size--;
1249 sbp2->map->datamap[startbyte] |= bit;
1250 }
1251 startbyte++;
1252 }
1253
1254 /* Allocate bytes at a time */
1255 if (size) {
1256 count = startbyte + (size / CHAR_BIT);
1257 for (byte = startbyte; byte < count; byte++) {
1258 sbp2->map->datamap[byte] = 0xff;
1259 size -= CHAR_BIT;
1260 }
1261 /* If any bits are left allocate them out of the next byte */
1262 if (size) {
1263 #ifdef DEBUG
1264 if (size >= CHAR_BIT)
1265 panic ("Too many bits left to allocate: %d",
1266 size);
1267 #endif
1268 for (bitpos = 0; bitpos < size; bitpos++) {
1269 bit = 0x1 << bitpos;
1270 sbp2->map->datamap[byte] |= bit;
1271 }
1272 }
1273 }
1274
1275 /* Adjust back one if the bits started 1 byte back */
1276 if (startbit)
1277 startbyte--;
1278 map->fwaddr = SBP_DATA_BEG +
1279 (((startbyte * CHAR_BIT) + startbit) * SBP_DATA_BLOCK_SIZE);
1280
1281 simple_unlock(&sbp2->map->maplock);
1282 }
1283
1284 static u_int64_t
1285 sbp2_alloc_addr(struct sbp2 *sbp2)
1286 {
1287 u_int64_t addr;
1288 int byte, bitpos, found;
1289 unsigned char bit;
1290
1291 found = 0;
1292 simple_lock(&sbp2->map->maplock);
1293
1294 addr = SBP_ADDR_BEG + (sbp2->map->next_addr * SBP_ADDR_BLOCK_SIZE);
1295 byte = sbp2->map->next_addr / CHAR_BIT;
1296 bitpos = sbp2->map->next_addr % CHAR_BIT;
1297 bit = 0x1 << bitpos;
1298
1299 #ifdef DIAGNOSTIC
1300 if (sbp2->map->addrmap[byte] & bit)
1301 panic("Already allocated address 0x%016" PRIx64, addr);
1302 #endif
1303 sbp2->map->addrmap[byte] |= bit;
1304
1305 for (; byte < (sizeof(sbp2->map->addrmap) - byte); byte++) {
1306 for (bitpos = 0; bitpos < CHAR_BIT; bitpos++) {
1307 bit = 0x1 << bitpos;
1308 if ((sbp2->map->addrmap[byte] & bit) == 0) {
1309 found = 1;
1310 break;
1311 }
1312 }
1313 if (found)
1314 break;
1315 }
1316 sbp2->map->next_addr = (byte * CHAR_BIT) + bitpos;
1317
1318 simple_unlock(&sbp2->map->maplock);
1319
1320 #ifdef DIAGNOSTIC
1321 if (sbp2->map->next_addr >= SBP_ADDR_MAX)
1322 panic("XXX: Used 64k of sbp addr's.\n");
1323 #endif
1324 return addr;
1325 }
1326
1327 static void
1328 sbp2_free_data_mapping(struct sbp2 *sbp2, struct sbp2_mapping *map)
1329 {
1330 int byte, bitpos;
1331 u_int32_t size, count, startbyte, off, startbit;
1332 unsigned char bit;
1333
1334 simple_lock(&sbp2->map->maplock);
1335
1336 size = map->size / SBP_DATA_BLOCK_SIZE;
1337 if (map->size % SBP_DATA_BLOCK_SIZE)
1338 size++;
1339 off = ((int)(map->fwaddr - SBP_DATA_BEG) / SBP_DATA_BLOCK_SIZE);
1340
1341 startbyte = off / CHAR_BIT;
1342 startbit = off % CHAR_BIT;
1343
1344 /*
1345 * 3 parts. Any bits in the middle of the first byte.
1346 * Then bytes until whole bytes are done.
1347 * Finally, any left over remaining bits.
1348 */
1349
1350 if (startbit) {
1351 count = CHAR_BIT - startbit;
1352 if (size < count)
1353 count = size;
1354 for (bitpos = 0; bitpos < count; bitpos++) {
1355 bit = 0x1 << (bitpos + startbit);
1356 #ifdef DIAGNOSTIC
1357 if (!(sbp2->map->datamap[startbyte] & bit))
1358 panic("Freeing addr not allocated: 0x%016"
1359 PRIx64, map->fwaddr);
1360 #endif
1361 bit = ~bit;
1362 size--;
1363 sbp2->map->datamap[startbyte] &= bit;
1364 }
1365 startbyte++;
1366 }
1367
1368 if (size) {
1369 count = startbyte + (size / CHAR_BIT);
1370 for (byte = startbyte; byte < count; byte++) {
1371 #ifdef DIAGNOSTIC
1372 if (!(sbp2->map->datamap[byte]))
1373 panic("Freeing addr not allocated: 0x%016"
1374 PRIx64, map->fwaddr);
1375 #endif
1376 size -= CHAR_BIT;
1377 sbp2->map->datamap[byte] = 0;
1378 }
1379 /* If any bits are left free them out of the next byte */
1380 if (size) {
1381 #ifdef DEBUG
1382 if (size >= CHAR_BIT)
1383 panic ("Too many bits left to free: %d", size);
1384 #endif
1385 for (bitpos = 0; bitpos < size; bitpos++) {
1386 bit = 0x1 << bitpos;
1387 #ifdef DIAGNOSTIC
1388 if (!(sbp2->map->datamap[byte] & bit))
1389 panic("Freeing addr not allocated: "
1390 "0x%016" PRIx64, map->fwaddr);
1391 #endif
1392 bit = ~bit;
1393 sbp2->map->datamap[byte] &= bit;
1394 }
1395 }
1396 }
1397 if (startbit)
1398 startbyte--;
1399
1400 simple_unlock(&sbp2->map->maplock);
1401
1402 return;
1403 }
1404
1405 static void
1406 sbp2_free_addr(struct sbp2 *sbp2, u_int64_t addr)
1407 {
1408 int off, byte, bitpos;
1409 unsigned char bit;
1410
1411 off = ((int)(addr - SBP_ADDR_BEG) / SBP_ADDR_BLOCK_SIZE);
1412
1413 byte = off / CHAR_BIT;
1414 bitpos = off % CHAR_BIT;
1415 bit = 0x1 << bitpos;
1416
1417 simple_lock(&sbp2->map->maplock);
1418 #ifdef DIAGNOSTIC
1419 if (!(sbp2->map->addrmap[byte] & bit))
1420 panic("Freeing addr not allocated: 0x%016" PRIx64, addr);
1421 #endif
1422 bit = ~bit;
1423 sbp2->map->addrmap[byte] &= bit;
1424 if (sbp2->map->next_addr > off)
1425 sbp2->map->next_addr = off;
1426 simple_unlock(&sbp2->map->maplock);
1427 }
1428
1429 static struct sbp2_pagetable *
1430 sbp2_alloc_pt(struct uio *io, u_int8_t rw, struct sbp2_orb *orb)
1431 {
1432 struct sbp2_pagetable *pt;
1433 struct sbp2_mapping *map;
1434 struct ieee1394_softc *sc;
1435 ssize_t len;
1436 char *addr;
1437 int i, j, k, cnt;
1438
1439 pt = malloc (sizeof (*pt), M_1394DATA, M_ZERO | M_WAITOK);
1440
1441 /* Compute number of entries. */
1442
1443 for (i = 0; i < io->uio_iovcnt; i++) {
1444 if (io->uio_iov[i].iov_len <= SBP2_PHYS_SEGMENT)
1445 pt->pt_cnt++;
1446 else {
1447 pt->pt_cnt +=
1448 io->uio_iov[i].iov_len / SBP2_PHYS_SEGMENT;
1449 if (io->uio_iov[i].iov_len % SBP2_PHYS_SEGMENT)
1450 pt->pt_cnt++;
1451 }
1452 #ifdef DEBUG
1453 /* Overflow'd 16 bits. */
1454 if (pt->pt_cnt == 0) {
1455 DPRINTFN(1, ("pt_cnt overflow\n"));
1456 free (pt, M_1394DATA);
1457 return NULL;
1458 }
1459 #endif
1460 }
1461
1462 sc = orb->sbp2->sc;
1463
1464 pt->pt_ent.ab_data = malloc (SBP2_PTENT_SIZE * pt->pt_cnt, M_1394DATA,
1465 M_ZERO | M_WAITOK);
1466 sbp2_alloc_data_mapping(orb->sbp2, &pt->pt_map,
1467 (char *)pt->pt_ent.ab_data, SBP2_PTENT_SIZE * pt->pt_cnt, SBP_READ);
1468
1469 pt->pt_ent.ab_addr = pt->pt_map.fwaddr;
1470
1471 pt->pt_ent.ab_length = SBP2_PTENT_SIZE * pt->pt_cnt;
1472 pt->pt_ent.ab_tcode = IEEE1394_TCODE_READ_REQ_BLOCK;
1473 pt->pt_ent.ab_req = sc;
1474 pt->pt_ent.ab_cb = sbp2_pt_resp;
1475 pt->pt_ent.ab_cbarg = orb;
1476 pt->pt_data = malloc (sizeof (struct ieee1394_abuf) * pt->pt_cnt,
1477 M_1394DATA, M_ZERO | M_WAITOK);
1478
1479 j = 0;
1480 for (i = 0; i < io->uio_iovcnt; i++) {
1481 if (io->uio_iov[i].iov_len <= SBP2_PHYS_SEGMENT) {
1482 cnt = 1;
1483 } else {
1484 cnt = io->uio_iov[i].iov_len / SBP2_PHYS_SEGMENT;
1485 if (io->uio_iov[i].iov_len % SBP2_PHYS_SEGMENT)
1486 cnt++;
1487 }
1488 len = io->uio_iov[i].iov_len;
1489 for (k = 0; k < cnt; k++) {
1490 #ifdef DIAGNOSTIC
1491 if (len == 0)
1492 panic ("len is zero");
1493 #endif
1494 map = malloc (sizeof (struct sbp2_mapping), M_1394DATA,
1495 M_ZERO | M_WAITOK);
1496 pt->pt_data[j].ab_cbarg = map;
1497 addr = (char *)io->uio_iov[i].iov_base +
1498 (k * SBP2_PHYS_SEGMENT);
1499 if (len > SBP2_PHYS_SEGMENT) {
1500 len -= SBP2_PHYS_SEGMENT;
1501 sbp2_alloc_data_mapping(orb->sbp2, map, addr,
1502 SBP2_PHYS_SEGMENT, rw);
1503 pt->pt_data[j].ab_length = SBP2_PHYS_SEGMENT;
1504 pt->pt_ent.ab_data[j * SBP2_PTENT_SIZEQ] =
1505 SBP2_PT_MAKELEN(SBP2_PHYS_SEGMENT);
1506 } else {
1507 sbp2_alloc_data_mapping(orb->sbp2, map, addr,
1508 len, rw);
1509 pt->pt_data[j].ab_length = len;
1510 pt->pt_ent.ab_data[j * SBP2_PTENT_SIZEQ] =
1511 SBP2_PT_MAKELEN(len);
1512 len -= len;
1513 }
1514 pt->pt_data[j].ab_addr = map->fwaddr;
1515 pt->pt_data[j].ab_req = sc;
1516 if (rw == SBP_WRITE)
1517 pt->pt_data[j].ab_tcode =
1518 IEEE1394_TCODE_WRITE_REQ_BLOCK;
1519 else
1520 pt->pt_data[j].ab_tcode =
1521 IEEE1394_TCODE_READ_REQ_BLOCK;
1522 map->orb = orb;
1523 pt->pt_data[j].ab_cb = sbp2_data_resp;
1524 pt->pt_data[j].ab_data = (u_int32_t *)addr;
1525 pt->pt_ent.ab_data[j * SBP2_PTENT_SIZEQ] |=
1526 IEEE1394_CREATE_ADDR_HIGH(map->fwaddr);
1527 pt->pt_ent.ab_data[(j * SBP2_PTENT_SIZEQ) + 1] =
1528 IEEE1394_CREATE_ADDR_LOW(map->fwaddr);
1529 sc->sc1394_callback.sc1394_inreg(&pt->pt_data[j], 1);
1530 j++;
1531 }
1532 }
1533 sc->sc1394_callback.sc1394_inreg(&pt->pt_ent, 1);
1534 return pt;
1535 }
1536
1537 static void
1538 sbp2_pt_resp(struct ieee1394_abuf *abuf, int rcode)
1539 {
1540 struct sbp2_orb *orb = abuf->ab_cbarg;
1541 struct sbp2_pagetable *pt = orb->pt;
1542 u_int32_t offset;
1543
1544 if (rcode) {
1545 DPRINTF(("sbp2_pt_resp: Bad return code: %d\n", rcode));
1546 return;
1547 }
1548
1549 simple_lock(&orb->orb_lock);
1550
1551 /*
1552 * The target is allowed to read these 1 entry at a time so construct
1553 * responses in a different abuf to allow for this.
1554 */
1555
1556 offset = abuf->ab_retaddr - abuf->ab_addr;
1557 pt->pt_resp.ab_addr = abuf->ab_retaddr;
1558 pt->pt_resp.ab_tcode = IEEE1394_TCODE_READ_RESP_BLOCK;
1559 pt->pt_resp.ab_tlabel = abuf->ab_tlabel;
1560 pt->pt_resp.ab_length = abuf->ab_retlen;
1561 pt->pt_resp.ab_req = abuf->ab_req;
1562 pt->pt_resp.ab_data = (u_int32_t *)((u_int8_t *)abuf->ab_data + offset);
1563 pt->pt_resp.ab_cb = sbp2_null_resp;
1564 pt->pt_resp.ab_cbarg = orb;
1565 abuf->ab_req->sc1394_callback.sc1394_write(&pt->pt_resp);
1566 simple_unlock(&orb->orb_lock);
1567 return;
1568 }
1569
1570 static void
1571 sbp2_free_pt(struct sbp2_pagetable *pt)
1572 {
1573 struct sbp2_orb *orb = pt->pt_ent.ab_cbarg;
1574 struct ieee1394_softc *sc = orb->sbp2->sc;
1575 int i;
1576
1577 sc->sc1394_callback.sc1394_unreg(&pt->pt_ent, 1);
1578 sbp2_free_data_mapping(orb->sbp2, &pt->pt_map);
1579
1580 for (i = 0; i < pt->pt_cnt; i++) {
1581 sc->sc1394_callback.sc1394_unreg(&pt->pt_data[i], 1);
1582 sbp2_free_data_mapping(orb->sbp2, pt->pt_data[i].ab_cbarg);
1583 free (pt->pt_data[i].ab_cbarg, M_1394DATA);
1584 }
1585 free (pt->pt_data, M_1394DATA);
1586 free (pt->pt_ent.ab_data, M_1394DATA);
1587 free (pt, M_1394DATA);
1588 }
Cache object: e92f008047b31f51574675ff4db36766
|