/* When an inquiry succeeds the negotiator gets the option to attempt to ** request a better transfer agreement with the target. */ static void negotiator(Symbios *s, SymTarg *targ, uchar *ident, uchar *msg) { if(ident[7] & 0x20){ /* wide supported */ if(targ->flags & tf_ask_wide){ uchar cmd[6] = { 0, 0, 0, 0, 0, 0 }; targ->flags &= (~tf_ask_wide); /* only ask once */ dprintf("symbios%ld: negotiating wide xfer with target %ld\n", s->num,targ->id); msg[1] = 0x01; /* extended message */ msg[2] = 0x02; /* length */ msg[3] = 0x03; /* sync negotiate */ msg[4] = 0x01; /* 16 bit wide */ exec_io(targ, cmd, 6, msg, 5, NULL, 0, 0); } } if(ident[7] & 0x10){ /* sync supported */ if(targ->flags & tf_ask_sync) { uchar cmd[6] = { 0, 0, 0, 0, 0, 0 }; targ->flags &= (~tf_ask_sync); /* only ask once */ dprintf("symbios%ld: negotiating sync xfer with target %ld\n", s->num,targ->id); msg[1] = 0x01; /* extended message */ msg[2] = 0x03; /* length */ msg[3] = 0x01; /* sync negotiate */ msg[4] = s->syncinfo[0].period / 4; /* sync period / 4 */ msg[5] = s->maxoffset; exec_io(targ, cmd, 6, msg, 6, NULL, 0, 0); } } }
/* Convert a CCB_SCSIIO into a BL_CCB32 and (possibly SG array). ** */ static long sim_execute_scsi_io(Symbios *s, CCB_HEADER *ccbh) { CCB_SCSIIO *ccb = (CCB_SCSIIO *) ccbh; uchar *cdb; physical_entry pe[2]; SymTarg *targ; uchar msg[8]; targ = s->targ + ccb->cam_ch.cam_target_id; if(targ->flags & tf_ignore){ ccbh->cam_status = CAM_SEL_TIMEOUT; return B_OK; } if(ccb->cam_ch.cam_flags & CAM_CDB_POINTER) { cdb = ccb->cam_cdb_io.cam_cdb_ptr; } else { cdb = ccb->cam_cdb_io.cam_cdb_bytes; } get_memory_map((void*) (ccb->cam_sim_priv), 1536, pe, 2); /* identify message */ msg[0] = 0xC0 | (ccb->cam_ch.cam_target_lun & 0x07); /* fill out table */ prep_io((SymPriv *) ccb->cam_sim_priv, (uint32) pe[0].address); /* insure only one transaction at a time for any given target */ acquire_sem(targ->sem_targ); targ->priv = (SymPriv *) ccb->cam_sim_priv;; targ->priv_phys = (uint32 ) pe[0].address; targ->inbound = (ccb->cam_ch.cam_flags & CAM_DIR_IN) ? 1 : 0; if(ccb->cam_ch.cam_flags & CAM_SCATTER_VALID){ exec_io(targ, cdb, ccb->cam_cdb_len, msg, 1, ccb->cam_data_ptr, ccb->cam_sglist_cnt, 1); } else { exec_io(targ, cdb, ccb->cam_cdb_len, msg, 1, ccb->cam_data_ptr, ccb->cam_dxfer_len, 0); } /* dprintf("symbios%d: state = 0x%02x, status = 0x%02x\n", s->num,targ->state,targ->priv->status[0]);*/ /* decode status */ switch(targ->status){ case status_complete: if((ccb->cam_scsi_status=targ->priv->_status[0]) != 0) { ccbh->cam_status = CAM_REQ_CMP_ERR; /* nonzero status is an error ... 0x02 = check condition */ if((ccb->cam_scsi_status == 0x02) && !(ccb->cam_ch.cam_flags & CAM_DIS_AUTOSENSE) && ccb->cam_sense_ptr && ccb->cam_sense_len){ uchar command[6]; command[0] = 0x03; /* request_sense */ command[1] = ccb->cam_ch.cam_target_lun << 5; command[2] = 0; command[3] = 0; command[4] = ccb->cam_sense_len; command[5] = 0; targ->inbound = 1; exec_io(targ, command, 6, msg, 1, ccb->cam_sense_ptr, ccb->cam_sense_len, 0); if(targ->priv->_status[0]){ ccb->cam_ch.cam_status |= CAM_AUTOSENSE_FAIL; } else { ccb->cam_ch.cam_status |= CAM_AUTOSNS_VALID; } } } else { ccbh->cam_status = CAM_REQ_CMP; if(cdb[0] == 0x12) { /* inquiry just succeeded ... is it non SG and with enough data to snoop the support bits? */ if(!(ccb->cam_ch.cam_flags & CAM_SCATTER_VALID) && (ccb->cam_dxfer_len>7)){ negotiator(s, targ, ccb->cam_data_ptr, msg); } } } break; case status_timeout: ccbh->cam_status = CAM_SEL_TIMEOUT; break; default: // XXX ccbh->cam_status = CAM_SEL_TIMEOUT; } targ->status = status_inactive; // dprintf("symbios%d: releasing targ @ 0x%08x\n",s->num,targ); release_sem(targ->sem_targ); return B_OK; }
/* * Fetches the resource denoted by |uri|. */ static void fetch_uri(const struct URI *uri) { spdylay_session_callbacks callbacks; int fd; SSL_CTX *ssl_ctx; SSL *ssl; struct Request req; struct Connection connection; int rv; nfds_t npollfds = 1; struct pollfd pollfds[1]; uint16_t spdy_proto_version; request_init(&req, uri); setup_spdylay_callbacks(&callbacks); /* Establish connection and setup SSL */ fd = connect_to(req.host, req.port); ssl_ctx = SSL_CTX_new(SSLv23_client_method()); if(ssl_ctx == NULL) { dief("SSL_CTX_new", ERR_error_string(ERR_get_error(), NULL)); } init_ssl_ctx(ssl_ctx, &spdy_proto_version); ssl = SSL_new(ssl_ctx); if(ssl == NULL) { dief("SSL_new", ERR_error_string(ERR_get_error(), NULL)); } /* To simplify the program, we perform SSL/TLS handshake in blocking I/O. */ ssl_handshake(ssl, fd); connection.ssl = ssl; connection.want_io = IO_NONE; /* Here make file descriptor non-block */ make_non_block(fd); set_tcp_nodelay(fd); printf("[INFO] SPDY protocol version = %d\n", spdy_proto_version); rv = spdylay_session_client_new(&connection.session, spdy_proto_version, &callbacks, &connection); if(rv != 0) { diec("spdylay_session_client_new", rv); } /* Submit the HTTP request to the outbound queue. */ submit_request(&connection, &req); pollfds[0].fd = fd; ctl_poll(pollfds, &connection); /* Event loop */ while(spdylay_session_want_read(connection.session) || spdylay_session_want_write(connection.session)) { int nfds = poll(pollfds, npollfds, -1); if(nfds == -1) { dief("poll", strerror(errno)); } if(pollfds[0].revents & (POLLIN | POLLOUT)) { exec_io(&connection); } if((pollfds[0].revents & POLLHUP) || (pollfds[0].revents & POLLERR)) { die("Connection error"); } ctl_poll(pollfds, &connection); } /* Resource cleanup */ spdylay_session_del(connection.session); SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ssl_ctx); shutdown(fd, SHUT_WR); close(fd); request_free(&req); }
/* * Fetches the resource denoted by |uri|. */ static void fetch_uri(const struct URI *uri) { spdylay_session_callbacks callbacks; int fd; struct Request req; struct Connection connection; int rv; nfds_t npollfds = 1; struct pollfd pollfds[1]; uint16_t spdy_proto_version = 3; request_init(&req, uri); setup_spdylay_callbacks(&callbacks); /* Establish connection and setup SSL */ fd = connect_to(req.host, req.port); if (-1 == fd) abort (); connection.fd = fd; connection.want_io = IO_NONE; /* Here make file descriptor non-block */ make_non_block(fd); set_tcp_nodelay(fd); printf("[INFO] SPDY protocol version = %d\n", spdy_proto_version); rv = spdylay_session_client_new(&connection.session, spdy_proto_version, &callbacks, &connection); if(rv != 0) { diec("spdylay_session_client_new", rv); } /* Submit the HTTP request to the outbound queue. */ submit_request(&connection, &req); pollfds[0].fd = fd; ctl_poll(pollfds, &connection); /* Event loop */ while(spdylay_session_want_read(connection.session) || spdylay_session_want_write(connection.session)) { int nfds = poll(pollfds, npollfds, -1); if(nfds == -1) { dief("poll", strerror(errno)); } if(pollfds[0].revents & (POLLIN | POLLOUT)) { exec_io(&connection); } if((pollfds[0].revents & POLLHUP) || (pollfds[0].revents & POLLERR)) { die("Connection error"); } ctl_poll(pollfds, &connection); } /* Resource cleanup */ spdylay_session_del(connection.session); shutdown(fd, SHUT_WR); MHD_socket_close_(fd); request_free(&req); }