Clean up autoconf of SBP2 devices Index: cardbus/fwohci_cardbus.c =================================================================== RCS file: /cvsroot/syssrc/sys/dev/cardbus/fwohci_cardbus.c,v retrieving revision 1.3 diff -w -u -r1.3 fwohci_cardbus.c --- fwohci_cardbus.c 2001/11/15 09:48:02 1.3 +++ fwohci_cardbus.c 2001/12/31 00:31:06 @@ -46,9 +46,7 @@ #include -#if defined pciinc #include -#endif #include #include @@ -64,16 +62,16 @@ cardbus_function_tag_t sc_cf; cardbus_devfunc_t sc_ct; void *sc_ih; + bus_addr_t sc_base_reg; }; static int fwohci_cardbus_match(struct device *, struct cfdata *, void *); static void fwohci_cardbus_attach(struct device *, struct device *, void *); +static int fwohci_cardbus_detach(struct device *, int); struct cfattach fwohci_cardbus_ca = { - sizeof(struct fwohci_cardbus_softc), fwohci_cardbus_match, fwohci_cardbus_attach, -#if 0 - fwohci_cardbus_detach, fwohci_activate -#endif + sizeof(struct fwohci_cardbus_softc), fwohci_cardbus_match, + fwohci_cardbus_attach, fwohci_cardbus_detach }; #define CARDBUS_OHCI_MAP_REGISTER PCI_OHCI_MAP_REGISTER @@ -114,7 +112,7 @@ if (Cardbus_mapreg_map(ct, CARDBUS_OHCI_MAP_REGISTER, CARDBUS_MAPREG_TYPE_MEM, 0, &sc->sc_sc.sc_memt, &sc->sc_sc.sc_memh, - NULL, &sc->sc_sc.sc_memsize)) { + &sc->sc_base_reg, &sc->sc_sc.sc_memsize)) { printf("%s: can't map OCHI register space\n", devname); return; } @@ -156,10 +154,36 @@ } printf("%s: interrupting at %d\n", devname, ca->ca_intrline); - /* XXX NULL should be replaced by some call to Cardbus coed */ + /* XXX this might be neccery for PCI card too ? */ + if (PCI_VENDOR(ca->ca_id) == PCI_VENDOR_VIATECH) { + switch (PCI_PRODUCT(ca->ca_id)) { + case PCI_PRODUCT_VIATECH_VT6306: + sc->sc_sc.sc_quirks |= FWOHCI_QUIRK_WAIT_SETTLE; + break; + } + } + + /* XXX NULL should be replaced by some call to Cardbus code */ if (fwohci_init(&sc->sc_sc, NULL) != 0) { cardbus_intr_disestablish(cc, cf, sc->sc_ih); - bus_space_unmap(sc->sc_sc.sc_memt, sc->sc_sc.sc_memh, + Cardbus_mapreg_unmap(sc->sc_ct, sc->sc_base_reg, + sc->sc_sc.sc_memt, sc->sc_sc.sc_memh, + sc->sc_sc.sc_memsize); + } +} + +static int +fwohci_cardbus_detach(struct device *self, int flags) +{ + struct fwohci_cardbus_softc *sc = (struct fwohci_cardbus_softc *)self; + int rv; + + if ((rv = fwohci_detach(&sc->sc_sc)) == 0) { + cardbus_intr_disestablish(sc->sc_cc, sc->sc_cf, sc->sc_ih); + Cardbus_mapreg_unmap(sc->sc_ct, sc->sc_base_reg, + sc->sc_sc.sc_memt, sc->sc_sc.sc_memh, sc->sc_sc.sc_memsize); } + + return rv; } Index: ieee1394/TODO =================================================================== RCS file: /cvsroot/syssrc/sys/dev/ieee1394/TODO,v retrieving revision 1.6 diff -w -u -r1.6 TODO --- TODO 2001/05/17 05:30:37 1.6 +++ TODO 2001/12/31 00:31:06 @@ -39,3 +39,6 @@ init/see all devices on resets sometimes. Make fwohci detach correctly (for cardbus/etc type interfaces) + +Add hooks so fwnode and its children knows there there have been a bus +reset. Needed for SBP2 and reconnect. Index: ieee1394/files.ieee1394 =================================================================== RCS file: /cvsroot/syssrc/sys/dev/ieee1394/files.ieee1394,v retrieving revision 1.5 diff -w -u -r1.5 files.ieee1394 --- files.ieee1394 2001/05/13 05:01:43 1.5 +++ files.ieee1394 2001/12/31 00:31:06 @@ -3,6 +3,11 @@ file dev/ieee1394/fwlynx.c fwlynx file dev/ieee1394/fwohci.c fwohci +device fwctl { } +attach fwctl at fwbus + +file dev/ieee1394/fwctldev.c fwctl + device fwnode { } attach fwnode at fwbus Index: ieee1394/fwctldev.c =================================================================== RCS file: fwctldev.c diff -N fwctldev.c --- /dev/null Sun May 20 17:40:04 2001 +++ fwctldev.c Sun Dec 30 16:31:06 2001 @@ -0,0 +1,194 @@ +#include +#include +#include +#include +#include +#include +#include + + +#include +#include + +#include "ioconf.h" + +cdev_decl(fwctl); + +struct fwctldev_softc; + +/* XXX */ +struct fwohci_softc; +void fwohci_phy_busreset(struct fwohci_softc *); + + +LIST_HEAD(,fwctldev_softc) fwctldevs; + + +struct fwctldev_softc { + struct device sc_device; + int sc_flags; +#define FWCTLDEV_OPEN 1 +}; + +int fwctldev_match(struct device *, struct cfdata *, void *); +void fwctldev_attach(struct device *, struct device *, void *); +int fwctldev_detach(struct device *, int); + +static struct fwctldev_softc * fwctl_find(dev_t); + + +struct cfattach fwctl_ca = { + sizeof(struct fwctldev_softc), fwctldev_match, fwctldev_attach, + fwctldev_detach +}; + + +int +fwctldev_match(struct device *parent, struct cfdata *match, void *aux) +{ + struct ieee1394_attach_args *fwa = aux; + + if (strcmp(fwa->name, "fwctl") == 0) + return 1; + return 0; +} + +void +fwctldev_attach(struct device *parent, struct device *self, void *aux) +{ + /* struct fwctldev_softc *sc = (struct fwctldev_softc *)self; */ + printf("\n"); +} + +int +fwctldev_detach(struct device *self, int flags) +{ + int maj, mn; + + /* locate the major number */ + for (maj = 0; maj < nchrdev; maj++) + if (cdevsw[maj].d_open == fwctlopen) + break; + + if (maj == nchrdev) { +#if 0 + panic("fwctl: failed to find major numer for device"); +#endif + return 0; + } + + mn = self->dv_unit; + vdevgone(maj, mn, mn, VCHR); + + return 0; +} + +static struct fwctldev_softc * +fwctl_find(dev_t dev) +{ + struct fwctldev_softc *sc; + + if (minor(dev) >= fwctl_cd.cd_ndevs) + return NULL; + sc = fwctl_cd.cd_devs[minor(dev)]; + if (sc == NULL) + return NULL; + + return sc; +} + +int +fwctlopen(dev_t dev, int oflags, int devtype, struct proc *p) +{ + struct fwctldev_softc *sc; + + if ((sc = fwctl_find(dev)) == NULL) + return ENODEV; + + sc->sc_flags |= FWCTLDEV_OPEN; + + return 0; +} + +int +fwctlclose(dev_t dev, int fflag, int devtype, struct proc *p) +{ + struct fwctldev_softc *sc; + + if ((sc = fwctl_find(dev)) == NULL) + panic("fwctl dev doesn't exist when closing ?"); + + if ((sc->sc_flags & FWCTLDEV_OPEN) == 0) + panic("fwctl dev never opened ?"); + + sc->sc_flags &= ~FWCTLDEV_OPEN; + + return 0; +} + +int +fwctlread(dev_t dev, struct uio *uio, int ioflag) +{ + return EOPNOTSUPP; +} + +int +fwctlwrite(dev_t dev, struct uio *uio, int ioflag) +{ + return EOPNOTSUPP; +} + +int +fwctlioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) +{ + /* XXX gross hack */ + + struct ieee1394_softc *parent_sc; + struct fwctldev_softc *sc; + + if ((sc = fwctl_find(dev)) == NULL) + panic("ioctl on unopened device ?"); + + switch (cmd) { + case FWCTL_GET_GUID: { + struct fwctl_guid *guid = (struct fwctl_guid *)data; + + memcpy(&guid->guid, parent_sc->sc1394_guid, + sizeof(parent_sc->sc1394_guid)); + + break; + } + case FWCTL_FORCE_RESET: { + fwohci_phy_busreset((struct fwohci_softc *)parent_sc); + break; + } + default: + return EOPNOTSUPP; + } + + return 0; +} + +void +fwctlstop(struct tty *tp, int rw) +{ + return; +} + +struct tty * +fwctltty(dev_t dev) +{ + return NULL; +} + +int +fwctlpoll(dev_t dev, int events, struct proc *p) +{ + return 0; +} + +paddr_t +fwctlmmap (dev_t dev, off_t off, int flag) +{ + return NULL; +} Index: ieee1394/fwctldev.h =================================================================== RCS file: fwctldev.h diff -N fwctldev.h --- /dev/null Sun May 20 17:40:04 2001 +++ fwctldev.h Sun Dec 30 16:31:06 2001 @@ -0,0 +1,10 @@ + + +struct fwctl_guid { + u_int8_t guid[8]; +}; + + +#define FWCTL_GET_GUID _IOR ('F', 0, struct fwctl_guid) +#define FWCTL_FORCE_RESET _IOR ('F', 0, int) + Index: ieee1394/fwnode.c =================================================================== RCS file: /cvsroot/syssrc/sys/dev/ieee1394/fwnode.c,v retrieving revision 1.7 diff -w -u -r1.7 fwnode.c --- fwnode.c 2001/11/15 09:48:08 1.7 +++ fwnode.c 2001/12/31 00:31:07 @@ -63,25 +63,22 @@ int fwnode_match(struct device *, struct cfdata *, void *); void fwnode_attach(struct device *, struct device *, void *); int fwnode_detach(struct device *, int); + static void fwnode_configrom_input(struct ieee1394_abuf *, int); -static u_int16_t calc_crc(u_int32_t, u_int32_t *, int, int); static int fwnode_parse_configrom (struct fwnode_softc *); static int fwnode_parse_directory(struct fwnode_softc *, u_int32_t *, struct configrom_dir *); -static void fwnode_print_configrom_tree(struct fwnode_softc *, - struct configrom_dir *, int); +static void fwnode_config_tree(struct fwnode_softc *, + struct configrom_dir *); static int fwnode_parse_leaf(u_int32_t *, struct configrom_data *); -static int fwnode_match_dev_type(struct fwnode_softc *, - struct configrom_data *); -static int sbp2_print_data(struct configrom_data *); -static int sbp2_print_dir(u_int8_t); -static void sbp2_init(struct fwnode_softc *, struct fwnode_device_cap *); static int fwnode_print(void *, const char *); -static void fwnode_match_subdevs(struct fwnode_softc *); -static void sbp2_login(struct ieee1394_abuf *, int); -static void sbp2_login_resp(struct ieee1394_abuf *, int); +static u_int16_t + calc_crc(u_int32_t, u_int32_t *, int, int); #ifdef FW_DEBUG +static void fwnode_print_configrom_tree(struct fwnode_softc *, + struct configrom_dir *, int); + #define DPRINTF(x) if (fwnodedebug) printf x #define DPRINTFN(n,x) if (fwnodedebug>(n)) printf x int fwnodedebug = 1; @@ -125,7 +122,8 @@ sc->sc1394_inreg = fwa->inreg; TAILQ_INIT(&sc->sc_configrom_root); - TAILQ_INIT(&sc->sc_dev_cap_head); + + LIST_INIT(&sc->sc_children); /* XXX. Fix the fw code to use the generic routines. */ sc->sc_sc1394.sc1394_ifinreg = psc->sc1394_ifinreg; @@ -150,10 +148,11 @@ fwnode_detach(struct device *self, int flags) { struct fwnode_softc *sc = (struct fwnode_softc *)self; + struct fwnode_child_softc *child; struct configrom_dir *dir, *sdir; struct configrom_data *data; - struct fwnode_device_cap *devcap; + if (sc->sc_sc1394.sc1394_configrom && sc->sc_sc1394.sc1394_configrom_len) free(sc->sc_sc1394.sc1394_configrom, M_1394DATA); @@ -196,12 +195,14 @@ dir = NULL; free(sdir, M_1394DATA); } - while ((devcap = TAILQ_FIRST(&sc->sc_dev_cap_head))) { - TAILQ_REMOVE(&sc->sc_dev_cap_head, devcap, dev_list); - if (devcap->dev_data) - free(devcap->dev_data, M_1394DATA); - free(devcap, M_1394DATA); + + + while(LIST_FIRST(&sc->sc_children) != NULL) { + child = LIST_FIRST(&sc->sc_children); + LIST_REMOVE(child, sc_node); + config_detach(&child->sc_device, DETACH_FORCE); } + return 0; } @@ -226,6 +227,9 @@ dirs = NULL; + DPRINTF(("fwnode_configrom_input: %d rcode: %d\n", + (int)ab->ab_cbarg, rcode)); + if (rcode != IEEE1394_RCODE_COMPLETE) { DPRINTF(("Aborting configrom input, rcode: %d\n", rcode)); goto fail; @@ -288,6 +292,9 @@ * later. */ + DPRINTF(("fwnode_configrom_input: fetching rom: %d\n", + newlen)); + sc->sc_sc1394.sc1394_configrom = ab->ab_data; sc->sc_sc1394.sc1394_configrom_len = 0; memset(ab->ab_data, 0, crclen); @@ -597,7 +604,7 @@ #ifdef FW_DEBUG fwnode_print_configrom_tree(sc, root, 0); #endif - fwnode_match_subdevs(sc); + fwnode_config_tree(sc, root); } else return 1; return 0; @@ -658,9 +665,6 @@ data->leafdata = NULL; TAILQ_INSERT_TAIL(&head->data_root, data, data); - if (type != P1212_KEYTYPE_Leaf) - if (fwnode_match_dev_type(sc, data)) - return 1; if (type == P1212_KEYTYPE_Leaf) { crclen = P1212_DIRENT_GET_LEN((ntohl(addr[i + data->val]))); @@ -792,71 +796,7 @@ return 0; } -static int -fwnode_match_dev_type(struct fwnode_softc *sc, struct configrom_data *data) -{ - /* XXX: This whole structure needs to be gut'd and redone. - Only after reading in the whole tree should sections of the tree - be passed along to config_found. */ - - struct fwnode_device_cap *devcap; - int done, found_sbp2; - - done = found_sbp2 = 0; - - switch (data->key_value) { - case P1212_KEYVALUE_Unit_Spec_Id: - if (data->val == SBP2_UNIT_SPEC_ID) - found_sbp2 = 1; - break; - case P1212_KEYVALUE_Unit_Sw_Version: - if (data->val == SBP2_UNIT_SW_VERSION) - found_sbp2 = 1; - break; - case P1212_KEYVALUE_Unit_Dependent_Info: - if (data->key_type == P1212_KEYTYPE_Offset) - found_sbp2 = 1; - default: - break; - } - if (found_sbp2) { - TAILQ_FOREACH(devcap, &sc->sc_dev_cap_head, dev_list) { - - if ((devcap->dev_type == DEVTYPE_SBP2) && found_sbp2) { - if (!devcap->dev_valid) { - done = 1; - devcap->dev_valid = 1; - } else { - DPRINTF(("found_sbp2: 0x%08x\n", - data->val)); - devcap->dev_data = - malloc(4, M_1394DATA, M_WAITOK); - ((u_int32_t *)devcap->dev_data)[0] = - data->val; - done = 1; - } - } - } - - /* If one wasn't found get a struct started. */ - if (!done) { - devcap = malloc(sizeof(*devcap), M_1394DATA, M_WAITOK); - devcap->dev_valid = 0; - devcap->dev_spec = 0; - devcap->dev_info = 0; - devcap->dev_data = NULL; - if (found_sbp2) { - devcap->dev_type = DEVTYPE_SBP2; - devcap->dev_print_data = sbp2_print_data; - devcap->dev_print_dir = sbp2_print_dir; - devcap->dev_init = sbp2_init; - } - TAILQ_INSERT_TAIL(&sc->sc_dev_cap_head, devcap, - dev_list); - } - } - return 0; -} +#ifdef FW_DEBUG static void fwnode_print_configrom_tree(struct fwnode_softc *sc, struct configrom_dir *dir, @@ -866,7 +806,7 @@ struct configrom_data *data; struct configrom_dir *subdir; struct configrom_leafdata *leaf; - struct fwnode_device_cap *devcap; + u_int32_t unit_spec; char *space; /* Set the indent string up. 4 spaces per level. */ @@ -875,38 +815,69 @@ space[i] = 0x20; space[indent * 4] = 0; - if (dir->dir_type) { - found = 0; - TAILQ_FOREACH(devcap, &sc->sc_dev_cap_head, dev_list) { - if (devcap->dev_print_dir(dir->dir_type)) { - found = 1; - break; - } - } - if (!found) { + if (dir->dir_type) printf("%sUnit ", space); - } - } else + else printf("Root "); printf("directory:\n\n"); + + unit_spec = 0; + TAILQ_FOREACH(data, &dir->data_root, data) { - found = 0; printf("%s", space); - /* - * Try any capable devices first. - * If none match just give up and print out the value. - * - */ - - TAILQ_FOREACH(devcap, &sc->sc_dev_cap_head, dev_list) { - if (devcap->dev_print_data(data)) { found = 1; + + if (data->key_value == P1212_KEYVALUE_Unit_Spec_Id) + unit_spec = data->val; + +#define KV_PRINT(key,str) case key: printf(str, data->val); break + + switch (data->key_value) { + case SBP2_KEYVALUE_Command_Set: + printf("SBP2 Command Set: "); + if (data->val == 0x104d8) + printf("SCSI 2\n"); + else + printf("0x%08x\n", data->val); break; + KV_PRINT(SBP2_KEYVALUE_Unit_Characteristics, + "SBP2 Unit Characteristics: 0x%08x\n"); + KV_PRINT(SBP2_KEYVALUE_Command_Set_Revision, + "SBP2 Command Set Revision: 0x%08x\n"); + KV_PRINT(SBP2_KEYVALUE_Command_Set_Spec_Id, + "SBP2 Command Set Spec Id: 0x%08x\n"); + KV_PRINT(SBP2_KEYVALUE_Firmware_Revision, + "SBP2 Firmware Revision: 0x%08x\n"); + KV_PRINT(SBP2_KEYVALUE_Reconnect_Timeout, + "SBP2 Reconnect Timeout: 0x%08x\n"); + KV_PRINT(SBP2_KEYVALUE_Unit_Unique_Id, + "SBP2 Unit Unique Id: 0x%08x\n"); + + case P1212_KEYVALUE_Unit_Dependent_Info: + if (unit_spec == SBP2_UNIT_SPEC_ID) { + switch (data->key_type) { + KV_PRINT(P1212_KEYTYPE_Immediate, + "SBP2 Logical Unit Number: 0x%08x\n"); + KV_PRINT(P1212_KEYTYPE_Offset, + "SBP2 Management Agent: 0x%08x\n"); + default: + found = 0; + break; } + } else { + found = 0; } + break; +#undef KV_PRINT + default: + found = 0; + break; + } + if (found) continue; + if (data->key_value >= (sizeof(p1212_keyvalue_strings) / sizeof(char *))) printf("Unknown type 0x%04hx: ", @@ -948,221 +919,86 @@ } free(space, M_1394DATA); } +#endif /* FW_DEBUG */ -/* XXX: All the sbp2 routines are a complete hack simply to probe a device for - the moment to make sure all the other code is good. This should all be gutted - out to it's own file and properly abstracted. -*/ - -static int -sbp2_print_data(struct configrom_data *data) +static void +fwnode_config_tree(struct fwnode_softc *sc, struct configrom_dir *dir) { + struct fwnode_match_arg arg; + struct configrom_dir *subdir; + struct configrom_data *data; + + arg.fwma_valid = 0; + arg.fwma_dir = dir; + arg.fwma_fwnode = sc; + + TAILQ_FOREACH(data, &dir->data_root, data) { switch (data->key_value) { - case SBP2_KEYVALUE_Command_Set: - printf("SBP2 Command Set: "); - if (data->val == 0x104d8) - printf("SCSI 2\n"); - else - printf("0x%08x\n", data->val); - break; - case SBP2_KEYVALUE_Unit_Characteristics: - printf("SBP2 Unit Characteristics: 0x%08x\n", data->val); - break; - case SBP2_KEYVALUE_Command_Set_Revision: - printf("SBP2 Command Set Revision: 0x%08x\n", data->val); - break; - case SBP2_KEYVALUE_Command_Set_Spec_Id: - printf("SBP2 Command Set Spec Id: 0x%08x\n", data->val); - break; - case SBP2_KEYVALUE_Firmware_Revision: - printf("SBP2 Firmware Revision: 0x%08x\n", data->val); - break; - case SBP2_KEYVALUE_Reconnect_Timeout: - printf("SBP2 Reconnect Timeout: 0x%08x\n", data->val); - break; - case SBP2_KEYVALUE_Unit_Unique_Id: - printf("SBP2 Unit Unique Id: 0x%08x\n", data->val); + case P1212_KEYVALUE_Unit_Spec_Id: + arg.fwma_valid |= FWMA_SPEC_ID; + arg.fwma_spec_id = data->val; break; - case P1212_KEYVALUE_Unit_Dependent_Info: - if (data->key_type == P1212_KEYTYPE_Immediate) - printf("SBP2 Logical Unit Number: 0x%08x\n", data->val); - else if (data->key_type == P1212_KEYTYPE_Offset) - printf("SBP2 Management Agent: 0x%08x\n", data->val); + case P1212_KEYVALUE_Unit_Sw_Version: + arg.fwma_valid |= FWMA_SW_VERSION; + arg.fwma_sw_version = data->val; break; - default: - return 0; - } - return 1; -} + case P1212_KEYVALUE_Textual_Descriptor: { + struct configrom_leafdata *l; -static int -sbp2_print_dir(u_int8_t dir_type) -{ - switch(dir_type) { - case SBP2_KEYVALUE_Logical_Unit_Directory: - printf("Logical Unit "); + if (data->key_type != P1212_KEYTYPE_Leaf || + data->leafdata == NULL) break; - default: - return 0; - } - return 1; -} -static void -sbp2_init(struct fwnode_softc *sc, struct fwnode_device_cap *devcap) -{ - struct ieee1394_abuf *ab, *ab2; - u_int32_t loc = ((int32_t *)devcap->dev_data)[0]; - - ab = malloc(sizeof(struct ieee1394_abuf), M_1394DATA, M_WAITOK); - memset(ab, 0, sizeof(struct ieee1394_abuf)); - ab->ab_data = malloc(8, M_1394DATA, M_WAITOK); - memset(ab->ab_data, 0, 8); - ab2 = malloc(sizeof(struct ieee1394_abuf), M_1394DATA, M_WAITOK); - memset(ab2, 0, sizeof(struct ieee1394_abuf)); - - loc *= 4; - ab->ab_length = 8; - ab->ab_req = (struct ieee1394_softc *)sc; - ab->ab_retlen = 0; - ab->ab_cb = NULL; - ab->ab_cbarg = NULL; - ab->ab_csr = CSR_BASE + loc; - ab->ab_data[0] = htonl(0x4000); - ab->ab_data[1] = 0; - ab->ab_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK; - - ab2->ab_length = 32; - ab2->ab_tcode = IEEE1394_TCODE_READ_REQ_BLOCK; - ab2->ab_retlen = 0; - ab2->ab_data = NULL; - ab2->ab_csr = 0x0000400000000000; - ab2->ab_cb = sbp2_login; - ab2->ab_cbarg = devcap; - ab2->ab_req = (struct ieee1394_softc *)sc; - - sc->sc1394_inreg(ab2, FALSE); - sc->sc1394_write(ab); - return; -} + l = data->leafdata; -static void -sbp2_login(struct ieee1394_abuf *ab, int rcode) -{ - struct fwnode_softc *sc = (struct fwnode_softc *)ab->ab_req; - /* struct fwnode_device_cap *devcap = ab->ab_cbarg;*/ - struct ieee1394_abuf *statab, *respab; + /* not text */ + if (l->desc_type != 0) + break; - /* Got a read so allocate the buffer and write out the response. */ + /* not ASCII */ + if (l->char_width || l->char_set || l->char_lang) + break; - if (rcode) { -#ifdef FW_DEBUG - printf ("sbp2_login: Bad return code: %d\n", rcode); -#endif - if (ab->ab_data) - free (ab->ab_data, M_1394DATA); - free(ab, M_1394DATA); + arg.fwma_valid |= FWMA_TEXT_DESC; + arg.fwma_text_desc = l->text; } - - ab->ab_data = malloc(32, M_1394DATA, M_WAITOK); - respab = malloc(sizeof(struct ieee1394_abuf), M_1394DATA, M_WAITOK); - statab = malloc(sizeof(struct ieee1394_abuf), M_1394DATA, M_WAITOK); - memset(respab, 0, sizeof(struct ieee1394_abuf)); - memset(statab, 0, sizeof(struct ieee1394_abuf)); - - statab->ab_length = 32; - statab->ab_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK; - statab->ab_retlen = 0; - statab->ab_data = NULL; - statab->ab_csr = 0x0000400000000030; - statab->ab_cb = sbp2_login_resp; - statab->ab_cbarg = ab->ab_cbarg; - statab->ab_req = ab->ab_req; - - sc->sc1394_inreg(statab, TRUE); - - respab->ab_length = 16; - respab->ab_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK; - respab->ab_retlen = 0; - respab->ab_data = NULL; - respab->ab_csr = 0x0000400000000020; - respab->ab_cb = sbp2_login_resp; - respab->ab_cbarg = ab->ab_cbarg; - respab->ab_req = ab->ab_req; - - sc->sc1394_inreg(respab, TRUE); - - memset(ab->ab_data, 0, 32); - ab->ab_data[2] = htonl(0x4000); - ab->ab_data[3] = htonl(0x20); - ab->ab_data[4] = htonl(0x90000000); - ab->ab_data[5] = htonl(0x00000010); - ab->ab_data[6] = htonl(0x4000); - ab->ab_data[7] = htonl(0x30); - ab->ab_retlen = 0; - ab->ab_cb = NULL; - ab->ab_cbarg = NULL; - ab->ab_tcode = IEEE1394_TCODE_READ_RESP_BLOCK; - ab->ab_length = 32; - - sc->sc1394_write(ab); + default: + break; } - -static void -sbp2_login_resp(struct ieee1394_abuf *ab, int rcode) -{ - /* struct fwnode_device_cap *devcap = (struct fwnode_device_cap *)ab->ab_cbarg;*/ -#ifdef FW_DEBUG - int i; -#endif - - if (rcode) { - DPRINTF(("Bad return code: %d\n", rcode)); - if (ab->ab_data) - free(ab->ab_data, M_1394DATA); - free(ab, M_1394DATA); } - DPRINTF(("csr: 0x%016qx\n", ab->ab_csr)); -#ifdef FW_DEBUG - for (i = 0; i < (ab->ab_retlen / 4); i++) - printf("%d: 0x%08x\n", i, ntohl(ab->ab_data[i])); -#endif + /* Did we find something interesting ? */ + if ((arg.fwma_valid & (FWMA_SPEC_ID|FWMA_SW_VERSION)) != 0) { + struct fwnode_child_softc *child; - free(ab->ab_data, M_1394DATA); - free(ab, M_1394DATA); + child = (struct fwnode_child_softc *) + config_found_sm(&sc->sc_sc1394.sc1394_dev, + &arg, fwnode_print, NULL); + if (child) + LIST_INSERT_HEAD(&sc->sc_children, child, sc_node); } -static void -fwnode_match_subdevs(struct fwnode_softc *sc) -{ - struct fwnode_device_cap *devcap; - - TAILQ_FOREACH(devcap, &sc->sc_dev_cap_head, dev_list) { - switch(devcap->dev_type) { - case DEVTYPE_UNKNOWN: - DPRINTF(("%s: Unknown device %d\n", - sc->sc_sc1394.sc1394_dev.dv_xname, - devcap->dev_spec)); - break; - case DEVTYPE_SBP2: - devcap->dev_init(sc, devcap); - break; - default: - panic("Unknown devcap type: %d", devcap->dev_type); - fwnode_print(NULL, NULL); - break; - } - } + /* + * XXX how deep can the tree be (in reality), we can overrun + * the kernel stack + */ + TAILQ_FOREACH(subdir, &dir->subdir_root, dir) + fwnode_config_tree(sc, subdir); } static int fwnode_print(void *aux, const char *pnp) { - char *name = aux; + struct fwnode_match_arg *arg = aux; + + if (pnp) { + printf("unknown at %s:", pnp); + if (arg->fwma_valid & FWMA_TEXT_DESC) + printf(" %s:", arg->fwma_text_desc); + printf(" specid %d sw version %d", + arg->fwma_spec_id, arg->fwma_sw_version); + } - if (pnp) - printf("%s at %s", name, pnp); return UNCONF; } Index: ieee1394/fwnodevar.h =================================================================== RCS file: /cvsroot/syssrc/sys/dev/ieee1394/fwnodevar.h,v retrieving revision 1.3 diff -w -u -r1.3 fwnodevar.h --- fwnodevar.h 2001/05/11 06:07:40 1.3 +++ fwnodevar.h 2001/12/31 00:31:07 @@ -70,19 +70,19 @@ u_int32_t refs; }; -struct fwnode_device_cap { - int (*dev_print_data)(struct configrom_data *); - int (*dev_print_dir)(u_int8_t); - void (*dev_init)(struct fwnode_softc *, struct fwnode_device_cap *); - void *dev_data; - int dev_type; - int dev_spec; - int dev_info; /* Lun, etc. */ - int dev_valid; - struct device *dev_subdev; - TAILQ_ENTRY(fwnode_device_cap) dev_list; +struct fwnode_match_arg { + int fwma_valid; +#define FWMA_SPEC_ID 0x01 +#define FWMA_SW_VERSION 0x02 +#define FWMA_TEXT_DESC 0x04 + u_int32_t fwma_spec_id; + u_int32_t fwma_sw_version; + char *fwma_text_desc; + struct configrom_dir *fwma_dir; + struct fwnode_softc *fwma_fwnode; }; + struct fwnode_softc { struct ieee1394_softc sc_sc1394; @@ -92,8 +92,15 @@ int (*sc1394_write)(struct ieee1394_abuf *); int (*sc1394_inreg)(struct ieee1394_abuf *, int); - TAILQ_HEAD(, fwnode_device_cap) sc_dev_cap_head; TAILQ_HEAD(, configrom_dir) sc_configrom_root; + + LIST_HEAD(, fwnode_child_softc) sc_children; +}; + +struct fwnode_child_softc { + struct device sc_device; + struct fwnode_softc *sc_fwnode; + LIST_ENTRY(fwnode_child_softc) sc_node; }; #endif /* _DEV_IEEE1394_FWNODEVAR_H */ Index: ieee1394/fwohci.c =================================================================== RCS file: /cvsroot/syssrc/sys/dev/ieee1394/fwohci.c,v retrieving revision 1.46 diff -w -u -r1.46 fwohci.c --- fwohci.c 2001/11/15 09:48:08 1.46 +++ fwohci.c 2001/12/31 00:31:09 @@ -120,7 +120,7 @@ static u_int8_t fwohci_phy_read(struct fwohci_softc *, u_int8_t); static void fwohci_phy_write(struct fwohci_softc *, u_int8_t, u_int8_t); -static void fwohci_phy_busreset(struct fwohci_softc *); +void fwohci_phy_busreset(struct fwohci_softc *); static void fwohci_phy_input(struct fwohci_softc *, struct fwohci_pkt *); static int fwohci_handler_set(struct fwohci_softc *, int, u_int32_t, u_int32_t, @@ -133,6 +133,8 @@ static int fwohci_at_output(struct fwohci_softc *, struct fwohci_ctx *, struct fwohci_pkt *); static void fwohci_at_done(struct fwohci_softc *, struct fwohci_ctx *, int); +#define FWOHCI_AT_DONE_FORCE 0x1 +#define FWOHCI_AT_DONE_NO_WRITE 0x2 static void fwohci_atrs_output(struct fwohci_softc *, int, struct fwohci_pkt *, struct fwohci_pkt *); @@ -181,7 +183,7 @@ #define DPRINTF(x) if (fwdebug) printf x #define DPRINTFN(n,x) if (fwdebug>(n)) printf x -int fwdebug = 0; +int fwdebug = 1; #else #define DPRINTF(x) #define DPRINTFN(n,x) @@ -281,6 +283,50 @@ return 0; } +int +fwohci_detach(struct fwohci_softc *sc) +{ + struct ieee1394_softc *iea; + + sc->sc_dying = 1; + wakeup(fwohci_event_thread); + if (tsleep(sc, PWAIT, "fwohcidet", hz * 60)) + printf("%s: fw event thread didn't die\n", + sc->sc_sc1394.sc1394_dev.dv_xname); + + callout_stop(&sc->sc_selfid_callout); + + LIST_FOREACH(iea, &sc->sc_nodelist, sc1394_node) + iea->sc1394_node_id = 0xffff; + fwohci_check_nodes(sc); + + fwohci_at_done(sc, sc->sc_ctx_atrq, + FWOHCI_AT_DONE_FORCE|FWOHCI_AT_DONE_NO_WRITE); + fwohci_at_done(sc, sc->sc_ctx_atrs, + FWOHCI_AT_DONE_FORCE|FWOHCI_AT_DONE_NO_WRITE); + + config_detach(sc->sc_sc1394.sc1394_if, 0); + config_detach(sc->sc_sc1394.sc1394_ctl, 0); + + fwohci_ctx_free(sc, sc->sc_ctx_arrq); + fwohci_ctx_free(sc, sc->sc_ctx_arrs); + fwohci_ctx_free(sc, sc->sc_ctx_atrq); + fwohci_ctx_free(sc, sc->sc_ctx_atrs); + free(sc->sc_ctx_ir, M_DEVBUF); + + fwohci_buf_free(sc, &sc->sc_buf_cnfrom); + fwohci_buf_free(sc, &sc->sc_buf_selfid); + + shutdownhook_disestablish(sc->sc_shutdownhook); + powerhook_disestablish(sc->sc_powerhook); + + evcnt_detach(&sc->sc_intrcnt); + evcnt_detach(&sc->sc_isocnt); + evcnt_detach(&sc->sc_isopktcnt); + + return 0; +} + static int fwohci_if_setiso(struct device *self, u_int32_t channel, u_int32_t tag, u_int32_t direction, void (*handler)(struct device *, struct mbuf *)) @@ -319,6 +365,9 @@ for (;;) { intmask = OHCI_CSR_READ(sc, OHCI_REG_IntEventClear); + if (intmask == 0xffffffff) /* XXX card removed */ + return 1; + /* * On a bus reset, everything except bus reset gets * cleared. That can't get cleared until the selfid @@ -434,12 +483,6 @@ } /* - * Enable Link Power - */ - - OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LPS); - - /* * Allocate DMA Context */ fwohci_ctx_alloc(sc, &sc->sc_ctx_arrq, OHCI_BUF_ARRQ_CNT, @@ -476,13 +519,23 @@ sc->sc_sc1394.sc1394_if = config_found(&sc->sc_sc1394.sc1394_dev, "fw", fwohci_print); + sc->sc_sc1394.sc1394_ctl = config_found(&sc->sc_sc1394.sc1394_dev, + "fwctl", fwohci_print); + /* Main loop. It's not coming back normally. */ fwohci_event_thread(sc); + /* Wakeup parent if needed */ + wakeup(sc); + kthread_exit(0); } +#ifndef FWOHCI_DELAY +#define FWOHCI_DELAY 1 +#endif + static void fwohci_event_thread(struct fwohci_softc *sc) { @@ -496,10 +549,21 @@ */ fwohci_hw_init(sc); + splx(s); + + if (sc->sc_quirks & FWOHCI_QUIRK_WAIT_SETTLE) { + printf("%s: waiting %d seconds for device to settle\n", + sc->sc_sc1394.sc1394_dev.dv_xname, FWOHCI_DELAY); + tsleep(fwohci_event_thread, PRIBIO, "fwohciset", + FWOHCI_DELAY * hz); + /* we sleep and the hardware went away under our feet */ + if (sc->sc_dying) + return; + } + /* Initial Bus Reset */ fwohci_phy_busreset(sc); - splx(s); while (!sc->sc_dying) { s = splbio(); @@ -632,7 +696,35 @@ DELAY(10); } +#ifdef FW_DEBUG + val = OHCI_CSR_READ(sc, OHCI_REG_HCControlSet); + if (val & OHCI_HCControl_LPS) + printf("%s: HCControl_LPS is there after reset\n", + sc->sc_sc1394.sc1394_dev.dv_xname); +#endif + + /* + * Wait for LPS turns on, this means the SCLK from the phy is + * present (OHCI1.1: sec 4). Linux driver claims that some + * turn on LPS directly (apprently without waiting for + * SCLK/readyness). If this is the case with your chip, a + * quirk should be added for it. + */ + OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LPS); + /* wait up to 2 seconds for LPS to wake up */ + for (i = 0; i < OHCI_LOOP_LONG; i++) { + val = OHCI_CSR_READ(sc, OHCI_REG_HCControlSet); + if (val & OHCI_HCControl_LPS) + break; + DELAY(100); + } + if (i == OHCI_LOOP_LONG) + printf("%s: waited forever for LPS\n", + sc->sc_sc1394.sc1394_dev.dv_xname); + else + printf("%s: waited %d interations for LPS\n", + sc->sc_sc1394.sc1394_dev.dv_xname, i); /* * First, initilize CSRs with undefined value to default settings. @@ -690,6 +782,19 @@ OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet, OHCI_Int_MasterEnable); OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_LinkEnable); + /* wait up to 2 seconds for LinkEnable to wake up */ + for (i = 0; i < OHCI_LOOP_LONG; i++) { + val = OHCI_CSR_READ(sc, OHCI_REG_HCControlSet); + if (val & OHCI_HCControl_LinkEnable) + break; + DELAY(100); + } + if (i == OHCI_LOOP_LONG) + printf("%s: waited forever for LinkEnable\n", + sc->sc_sc1394.sc1394_dev.dv_xname); + else + printf("%s: waited %d interations for LinkEnable\n", + sc->sc_sc1394.sc1394_dev.dv_xname, i); /* * Start the receivers @@ -737,6 +842,7 @@ OHCI_BusOptions_CMC | OHCI_BusOptions_IRMC); OHCI_CSR_WRITE(sc, OHCI_REG_BusOptions, val); fwohci_phy_busreset(sc); + /* XXX not permited to clear LPS or LinkEnable from software !!! */ OHCI_CSR_WRITE(sc, OHCI_REG_HCControlClear, OHCI_HCControl_LinkEnable); OHCI_CSR_WRITE(sc, OHCI_REG_HCControlClear, OHCI_HCControl_LPS); OHCI_CSR_WRITE(sc, OHCI_REG_HCControlSet, OHCI_HCControl_SoftReset); @@ -789,7 +895,7 @@ /* * Initiate Bus Reset */ -static void +void fwohci_phy_busreset(struct fwohci_softc *sc) { int s; @@ -1237,8 +1343,8 @@ /* * Initialize for Asynchronous Transmit Queue. */ - fwohci_at_done(sc, sc->sc_ctx_atrq, 1); - fwohci_at_done(sc, sc->sc_ctx_atrs, 1); + fwohci_at_done(sc, sc->sc_ctx_atrq, FWOHCI_AT_DONE_FORCE); + fwohci_at_done(sc, sc->sc_ctx_atrs, FWOHCI_AT_DONE_FORCE); } static void @@ -1984,7 +2090,7 @@ } static void -fwohci_at_done(struct fwohci_softc *sc, struct fwohci_ctx *fc, int force) +fwohci_at_done(struct fwohci_softc *sc, struct fwohci_ctx *fc, int flags) { struct fwohci_buf *fb; struct fwohci_desc *fd; @@ -1994,8 +2100,10 @@ while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) { fd = fb->fb_desc; #ifdef FW_DEBUG - DPRINTFN(1, ("fwohci_at_done: %sdesc %ld (%d)", - force ? "force " : "", (long)(fd - sc->sc_desc), + DPRINTFN(1, ("fwohci_at_done: %sdesc %s %ld (%d)", + (flags & FWOHCI_AT_DONE_FORCE) ? "force " : "", + (flags & FWOHCI_AT_DONE_NO_WRITE) ? "nowrite " : "", + (long)(fd - sc->sc_desc), fb->fb_nseg)); for (i = 0; i < fb->fb_nseg * 4; i++) DPRINTFN(2, ("%s%08x", i&7?" ":"\n ", @@ -2004,10 +2112,12 @@ #endif if (fb->fb_nseg > 2) fd += fb->fb_nseg - 1; - if (!force && !(fd->fd_status & OHCI_CTXCTL_ACTIVE)) + if ((flags & FWOHCI_AT_DONE_FORCE) == 0 && + !(fd->fd_status & OHCI_CTXCTL_ACTIVE)) break; TAILQ_REMOVE(&fc->fc_buf, fb, fb_list); - if (fc->fc_branch == &fd->fd_branch) { + if ((flags & FWOHCI_AT_DONE_NO_WRITE) == 0 && + (fc->fc_branch == &fd->fd_branch)) { OHCI_ASYNC_DMA_WRITE(sc, fc->fc_ctx, OHCI_SUBREG_ContextControlClear, OHCI_CTXCTL_RUN); fc->fc_branch = NULL; @@ -3263,6 +3373,10 @@ u_int32_t *cur, high, lo; int i, tcode, rcode, status, rv; + DPRINTF(("fwohci_read_resp: tcode: %d status: %d valid: %d\n", + pkt->fp_tcode, pkt->fp_status & OHCI_DESC_STATUS_ACK_MASK, + fcb->abuf_valid)); + /* * Both the ACK handling and normal response callbacks are handled here. * The main reason for this is the various error conditions that can @@ -3340,6 +3454,7 @@ ab->ab_req->sc1394_node_id, sc->sc_tlabel, fwohci_read_multi_resp, fcb); if (rv) { + DPRINTF(("fwohci_read_resp: failed to set r_m_r\b")); (*ab->ab_cb)(ab, -1); goto cleanup; } @@ -3350,11 +3465,13 @@ fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, ab->ab_req->sc1394_node_id, sc->sc_tlabel, NULL, NULL); + DPRINTF(("fwohci_read_resp: failed to set at_output")); (*ab->ab_cb)(ab, -1); goto cleanup; } fcb->count++; sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f; + DPRINTF(("read: new packet in queue: %d\n", fcb->count)); return IEEE1394_RCODE_COMPLETE; } else if ((rcode != -1) || ((status != -1) && (status != OHCI_CTXCTL_EVENT_ACK_COMPLETE) && @@ -3416,18 +3533,25 @@ u_int32_t high, lo; int rcode, rv; + DPRINTF(("fwochi_read_multi_resp: tcode: %d status: %d rcode: %d\n", + pkt->fp_tcode, pkt->fp_status, + (pkt->fp_hdr[1] & 0x0000f000) >> 12)); + /* * Bad return codes from the wire, just return what's already in the * buf. */ /* Make sure a response packet didn't arrive after a bad ACK. */ - if (fcb->abuf_valid == 0) + if (fcb->abuf_valid == 0) { + DPRINTF(("read_multi_resp: buf not valid")); return IEEE1394_RCODE_COMPLETE; + } rcode = (pkt->fp_hdr[1] & 0x0000f000) >> 12; if (rcode) { + DPRINTF(("read_multi_resp: rcode = %d", rcode)); (*ab->ab_cb)(ab, rcode); goto cleanup; } @@ -3441,6 +3565,10 @@ pkt->fp_iov[0].iov_base, 4); ab->ab_retlen += 4; } + + DPRINTF(("read_multi_resp: retlen: %d len: %d\n", + ab->ab_retlen, ab->ab_length)); + /* Still more, loop and read 4 more bytes. */ if (ab->ab_retlen < ab->ab_length) { memset(&newpkt, 0, sizeof(newpkt)); @@ -3467,11 +3595,13 @@ rv = fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, ab->ab_req->sc1394_node_id, sc->sc_tlabel, fwohci_read_multi_resp, fcb); - if (rv) + if (rv) { + DPRINTF(("read_multi_r: failed to output handler\n")); (*ab->ab_cb)(ab, -1); - else { + } else { rv = fwohci_at_output(sc, sc->sc_ctx_atrq, &newpkt); if (rv) { + DPRINTF(("read_multi_r: failed at_output\n")); fwohci_handler_set(sc, IEEE1394_TCODE_READ_RESP_QUAD, ab->ab_req->sc1394_node_id, sc->sc_tlabel, @@ -3480,6 +3610,8 @@ } else { sc->sc_tlabel = (sc->sc_tlabel + 1) & 0x3f; fcb->count++; + DPRINTF(("multi: new packet in queue: %d\n", + fcb->count)); return IEEE1394_RCODE_COMPLETE; } } Index: ieee1394/fwohcivar.h =================================================================== RCS file: /cvsroot/syssrc/sys/dev/ieee1394/fwohcivar.h,v retrieving revision 1.15 diff -w -u -r1.15 fwohcivar.h --- fwohcivar.h 2001/07/17 11:01:04 1.15 +++ fwohcivar.h 2001/12/31 00:31:09 @@ -56,6 +56,7 @@ OHCI_BUF_ATRS_CNT + OHCI_BUF_IR_CNT + 1 + 1) #define OHCI_LOOP 1000 +#define OHCI_LOOP_LONG 20000 #define OHCI_SELFID_TIMEOUT (hz * 3) #define OHCI_ASYNC_STREAM 0x40 @@ -174,6 +175,9 @@ struct proc *sc_event_thread; int sc_dying; + u_int32_t sc_quirks; +#define FWOHCI_QUIRK_WAIT_SETTLE 0x00000001 + u_int32_t sc_intmask; u_int32_t sc_iso; @@ -189,6 +193,7 @@ }; int fwohci_init (struct fwohci_softc *, const struct evcnt *); +int fwohci_detach(struct fwohci_softc *); int fwohci_intr (void *); int fwohci_print (void *, const char *); Index: ieee1394/fwscsi.c =================================================================== RCS file: /cvsroot/syssrc/sys/dev/ieee1394/fwscsi.c,v retrieving revision 1.4 diff -w -u -r1.4 fwscsi.c --- fwscsi.c 2001/11/15 09:48:08 1.4 +++ fwscsi.c 2001/12/31 01:43:08 @@ -47,36 +47,285 @@ #include +#include +#include +#include + #include #include +struct fwscsi_softc; + static int fwscsi_match(struct device *, struct cfdata *, void *); static void fwscsi_attach(struct device *, struct device *, void *); static int fwscsi_detach(struct device *, int); +static void sbp2_init(struct fwscsi_softc *); +static void sbp2_login(struct ieee1394_abuf *, int); +static void sbp2_login_resp(struct ieee1394_abuf *, int); + + + +typedef enum { SBP2_ATTACH, + SBP2_LOGIN, + SBP2_RECONNECT, + SBP2_ATTACHED, + SBP2_DETACHED, + SBP2_INVALID_DIR, +} sbp2_state; + struct fwscsi_softc { - struct device sc_dev; + struct fwnode_child_softc sc_node_dev; + + sbp2_state sc_state; + + u_int32_t sc_spec_id; + u_int32_t sc_sw_ver; + + u_int32_t sc_reconnect_timeout; + u_int32_t sc_fw_ver; + u_int32_t sc_cmd_set; + u_int32_t sc_cmd_set_rev; + u_int32_t sc_cmd_set_spec_id; + u_int32_t sc_lun; + u_int32_t sc_uniq_id; + u_int32_t sc_unit_char; + + /* csr */ + u_int32_t sc_mgt_addr; + u_int64_t sc_cmd_addr; }; +#define SC_DEVNAME(sc) (sc->sc_node_dev.sc_device.dv_xname) +#define SC_INREG(sc) (*sc->sc_node_dev.sc_fwnode->sc1394_inreg) +#define SC_WRITE(sc) (*sc->sc_node_dev.sc_fwnode->sc1394_write) + + struct cfattach fwscsi_ca = { sizeof(struct fwscsi_softc), fwscsi_match, fwscsi_attach, fwscsi_detach }; -/* Place holders for the moment. */ - static int fwscsi_match(struct device *parent, struct cfdata *match, void *aux) { + struct fwnode_match_arg *fma = (struct fwnode_match_arg *)aux; + + if ((fma->fwma_valid & (FWMA_SPEC_ID|FWMA_SW_VERSION)) == (FWMA_SPEC_ID|FWMA_SW_VERSION)) + if (fma->fwma_spec_id == SBP2_UNIT_SPEC_ID && + fma->fwma_sw_version == SBP2_UNIT_SW_VERSION) + return 1; + return 0; } static void fwscsi_attach(struct device *parent, struct device *self, void *aux) { + struct fwnode_match_arg *fma = (struct fwnode_match_arg *)aux; + struct fwscsi_softc *sc = (struct fwscsi_softc *) self; + struct configrom_data *data; + + sc->sc_node_dev.sc_fwnode = fma->fwma_fwnode; + + sc->sc_spec_id = fma->fwma_spec_id; + sc->sc_sw_ver = fma->fwma_sw_version; + + sc->sc_state = SBP2_ATTACH; + + sc->sc_reconnect_timeout = 0; + sc->sc_fw_ver = 0; + sc->sc_cmd_set = 0; /* SCSI2 == 0x104d8 */ + sc->sc_uniq_id = 0; + sc->sc_unit_char= 0; + + sc->sc_lun = 0; + sc->sc_mgt_addr = 0; + + sc->sc_cmd_addr = 0; + +#define SBP2_MATCH(d,key,var) \ + case SBP2_KEYVALUE_##key: sc->sc_##var = (d)->val ; break + + TAILQ_FOREACH(data, &fma->fwma_dir->data_root, data) { + switch(data->key_value) { + SBP2_MATCH(data, Reconnect_Timeout, reconnect_timeout); + SBP2_MATCH(data, Firmware_Revision, fw_ver); + SBP2_MATCH(data, Command_Set, cmd_set); + SBP2_MATCH(data, Unit_Unique_Id, uniq_id); + SBP2_MATCH(data, Unit_Characteristics, unit_char); + SBP2_MATCH(data, Command_Set_Revision, cmd_set_rev); + SBP2_MATCH(data, Command_Set_Spec_Id, cmd_set_spec_id); + + case P1212_KEYVALUE_Unit_Dependent_Info: + switch(data->key_type) { + case P1212_KEYTYPE_Immediate: + sc->sc_lun = data->val; + break; + case P1212_KEYTYPE_Offset: + sc->sc_mgt_addr = data->val; + break; + } + } } + printf(": SPB2"); + if (sc->sc_cmd_set == 0x104d8) { + printf(" SCSI2"); + } else { + printf(" %x", sc->sc_cmd_set); + sc->sc_state = SBP2_INVALID_DIR; + } + printf(" device\n"); + + printf("%s:", SC_DEVNAME(sc)); + if (fma->fwma_valid & FWMA_TEXT_DESC) + printf(" %s", fma->fwma_text_desc); + if (sc->sc_fw_ver) + printf(" fw rev: %x", sc->sc_fw_ver); + printf("\n"); + + if (sc->sc_mgt_addr == 0) + sc->sc_state = SBP2_INVALID_DIR; + + if (sc->sc_state == SBP2_INVALID_DIR) + printf("%s: doesn't attach due to invalid rom\n", + SC_DEVNAME(sc)); + else + sbp2_init(sc); +} + static int fwscsi_detach(struct device *self, int flags) { return 0; +} + + +static void +sbp2_init(struct fwscsi_softc *sc) +{ + struct ieee1394_abuf *ab, *ab2; + + sc->sc_state = SBP2_LOGIN; + + ab = malloc(sizeof(struct ieee1394_abuf), M_1394DATA, M_WAITOK); + memset(ab, 0, sizeof(struct ieee1394_abuf)); + ab->ab_data = malloc(8, M_1394DATA, M_WAITOK); + memset(ab->ab_data, 0, 8); + ab2 = malloc(sizeof(struct ieee1394_abuf), M_1394DATA, M_WAITOK); + memset(ab2, 0, sizeof(struct ieee1394_abuf)); + + ab->ab_length = 8; + ab->ab_req = (struct ieee1394_softc *)sc->sc_node_dev.sc_fwnode; + ab->ab_retlen = 0; + ab->ab_cb = NULL; + ab->ab_cbarg = NULL; + ab->ab_csr = CSR_BASE + sc->sc_mgt_addr * 4; + ab->ab_data[0] = htonl(0x4000); + ab->ab_data[1] = 0; + ab->ab_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK; + + ab2->ab_length = 32; + ab2->ab_tcode = IEEE1394_TCODE_READ_REQ_BLOCK; + ab2->ab_retlen = 0; + ab2->ab_data = NULL; + ab2->ab_csr = 0x0000400000000000; + ab2->ab_cb = sbp2_login; + ab2->ab_cbarg = sc; + ab2->ab_req = (struct ieee1394_softc *)sc->sc_node_dev.sc_fwnode; + + SC_INREG(sc)(ab2, 0); + SC_WRITE(sc)(ab); + + return; +} + +static void +sbp2_login(struct ieee1394_abuf *ab, int rcode) +{ + struct fwscsi_softc *sc = ab->ab_cbarg; + struct ieee1394_abuf *statab, *respab; + + /* Got a read so allocate the buffer and write out the response. */ + + if (rcode) { + printf ("%s: sbp2_login: bad return code: %d\n", + SC_DEVNAME(sc), rcode); + sc->sc_state = SBP2_DETACHED; + if (ab->ab_data) + free (ab->ab_data, M_1394DATA); + free(ab, M_1394DATA); + } + + ab->ab_data = malloc(32, M_1394DATA, M_WAITOK); + respab = malloc(sizeof(struct ieee1394_abuf), M_1394DATA, M_WAITOK); + statab = malloc(sizeof(struct ieee1394_abuf), M_1394DATA, M_WAITOK); + memset(respab, 0, sizeof(struct ieee1394_abuf)); + memset(statab, 0, sizeof(struct ieee1394_abuf)); + + statab->ab_length = 32; + statab->ab_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK; + statab->ab_retlen = 0; + statab->ab_data = NULL; + statab->ab_csr = 0x0000400000000030; + statab->ab_cb = sbp2_login_resp; + statab->ab_cbarg = ab->ab_cbarg; + statab->ab_req = ab->ab_req; + + SC_INREG(sc)(statab, 1); + + respab->ab_length = 16; + respab->ab_tcode = IEEE1394_TCODE_WRITE_REQ_BLOCK; + respab->ab_retlen = 0; + respab->ab_data = NULL; + respab->ab_csr = 0x0000400000000020; + respab->ab_cb = sbp2_login_resp; + respab->ab_cbarg = ab->ab_cbarg; + respab->ab_req = ab->ab_req; + + SC_INREG(sc)(respab, 1); + + memset(ab->ab_data, 0, 32); + ab->ab_data[2] = htonl(0x4000); /* login resp hi */ + ab->ab_data[3] = htonl(0x20); /* login resp lo */ + ab->ab_data[4] = htonl(0x90000000); /* Exclusive */ + ab->ab_data[5] = htonl(0x00000010); /* login resp length */ + ab->ab_data[6] = htonl(0x4000); /* status fifo hi */ + ab->ab_data[7] = htonl(0x30); /* status fifo lo */ + ab->ab_retlen = 0; + ab->ab_cb = NULL; + ab->ab_cbarg = NULL; + ab->ab_tcode = IEEE1394_TCODE_READ_RESP_BLOCK; + ab->ab_length = 32; + + SC_WRITE(sc)(ab); +} + +static void +sbp2_login_resp(struct ieee1394_abuf *ab, int rcode) +{ + struct fwscsi_softc *sc = ab->ab_cbarg; + +#ifdef FW_DEBUG + int i; +#endif + + if (rcode) { + printf("%s: bad login response: %d\n", + SC_DEVNAME(sc), rcode); + sc->sc_state = SBP2_DETACHED; + if (ab->ab_data) + free(ab->ab_data, M_1394DATA); + free(ab, M_1394DATA); + } + + printf("csr: 0x%016qx\n", ab->ab_csr); + +#ifdef FW_DEBUG + for (i = 0; i < (ab->ab_retlen / 4); i++) + printf("%d: 0x%08x\n", i, ntohl(ab->ab_data[i])); +#endif + + free(ab->ab_data, M_1394DATA); + free(ab, M_1394DATA); } Index: ieee1394/ieee1394var.h =================================================================== RCS file: /cvsroot/syssrc/sys/dev/ieee1394/ieee1394var.h,v retrieving revision 1.13 diff -w -u -r1.13 ieee1394var.h --- ieee1394var.h 2001/07/18 02:59:54 1.13 +++ ieee1394var.h 2001/12/31 00:31:09 @@ -80,6 +80,7 @@ struct ieee1394_softc { struct device sc1394_dev; struct device *sc1394_if; /* Move to fwohci level. */ + struct device *sc1394_ctl; const struct ieee1394_callbacks sc1394_callback; /* Nuke probably. */ u_int32_t *sc1394_configrom;