00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00039
00040
00041 #include "globals.h"
00042 #include "fsm.h"
00043 #include "master.h"
00044
00045
00046
00047 void ec_fsm_master_start(ec_fsm_t *);
00048 void ec_fsm_master_broadcast(ec_fsm_t *);
00049 void ec_fsm_master_read_states(ec_fsm_t *);
00050 void ec_fsm_master_validate_vendor(ec_fsm_t *);
00051 void ec_fsm_master_validate_product(ec_fsm_t *);
00052 void ec_fsm_master_rewrite_addresses(ec_fsm_t *);
00053 void ec_fsm_master_configure_slave(ec_fsm_t *);
00054 void ec_fsm_master_scan_slaves(ec_fsm_t *);
00055 void ec_fsm_master_write_eeprom(ec_fsm_t *);
00056
00057 void ec_fsm_slavescan_start(ec_fsm_t *);
00058 void ec_fsm_slavescan_address(ec_fsm_t *);
00059 void ec_fsm_slavescan_state(ec_fsm_t *);
00060 void ec_fsm_slavescan_base(ec_fsm_t *);
00061 void ec_fsm_slavescan_datalink(ec_fsm_t *);
00062 void ec_fsm_slavescan_eeprom_size(ec_fsm_t *);
00063 void ec_fsm_slavescan_eeprom_data(ec_fsm_t *);
00064 void ec_fsm_slavescan_end(ec_fsm_t *);
00065
00066 void ec_fsm_slaveconf_init(ec_fsm_t *);
00067 void ec_fsm_slaveconf_sync(ec_fsm_t *);
00068 void ec_fsm_slaveconf_preop(ec_fsm_t *);
00069 void ec_fsm_slaveconf_fmmu(ec_fsm_t *);
00070 void ec_fsm_slaveconf_saveop(ec_fsm_t *);
00071 void ec_fsm_slaveconf_op(ec_fsm_t *);
00072 void ec_fsm_slaveconf_end(ec_fsm_t *);
00073
00074 void ec_fsm_sii_start_reading(ec_fsm_t *);
00075 void ec_fsm_sii_read_check(ec_fsm_t *);
00076 void ec_fsm_sii_read_fetch(ec_fsm_t *);
00077 void ec_fsm_sii_start_writing(ec_fsm_t *);
00078 void ec_fsm_sii_write_check(ec_fsm_t *);
00079 void ec_fsm_sii_write_check2(ec_fsm_t *);
00080 void ec_fsm_sii_end(ec_fsm_t *);
00081 void ec_fsm_sii_error(ec_fsm_t *);
00082
00083 void ec_fsm_change_start(ec_fsm_t *);
00084 void ec_fsm_change_check(ec_fsm_t *);
00085 void ec_fsm_change_status(ec_fsm_t *);
00086 void ec_fsm_change_code(ec_fsm_t *);
00087 void ec_fsm_change_ack(ec_fsm_t *);
00088 void ec_fsm_change_check_ack(ec_fsm_t *);
00089 void ec_fsm_change_end(ec_fsm_t *);
00090 void ec_fsm_change_error(ec_fsm_t *);
00091
00092
00093
00098 int ec_fsm_init(ec_fsm_t *fsm,
00099 ec_master_t *master
00100 )
00101 {
00102 fsm->master = master;
00103 fsm->master_state = ec_fsm_master_start;
00104 fsm->master_slaves_responding = 0;
00105 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN;
00106 fsm->master_validation = 0;
00107
00108 ec_datagram_init(&fsm->datagram);
00109 if (ec_datagram_prealloc(&fsm->datagram, EC_MAX_DATA_SIZE)) {
00110 EC_ERR("Failed to allocate FSM datagram.\n");
00111 return -1;
00112 }
00113
00114 return 0;
00115 }
00116
00117
00118
00123 void ec_fsm_clear(ec_fsm_t *fsm )
00124 {
00125 ec_datagram_clear(&fsm->datagram);
00126 }
00127
00128
00129
00134 void ec_fsm_reset(ec_fsm_t *fsm )
00135 {
00136 fsm->master_state = ec_fsm_master_start;
00137 fsm->master_slaves_responding = 0;
00138 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN;
00139 }
00140
00141
00142
00147 void ec_fsm_execute(ec_fsm_t *fsm )
00148 {
00149 fsm->master_state(fsm);
00150 }
00151
00152
00153
00154
00155
00161 void ec_fsm_master_start(ec_fsm_t *fsm)
00162 {
00163 ec_datagram_brd(&fsm->datagram, 0x0130, 2);
00164 ec_master_queue_datagram(fsm->master, &fsm->datagram);
00165 fsm->master_state = ec_fsm_master_broadcast;
00166 }
00167
00168
00169
00175 void ec_fsm_master_broadcast(ec_fsm_t *fsm )
00176 {
00177 ec_datagram_t *datagram = &fsm->datagram;
00178 unsigned int topology_change, states_change, i;
00179 ec_slave_t *slave;
00180 ec_master_t *master = fsm->master;
00181
00182 if (datagram->state != EC_CMD_RECEIVED) {
00183 if (!master->device->link_state) {
00184 fsm->master_slaves_responding = 0;
00185 list_for_each_entry(slave, &master->slaves, list) {
00186 slave->online = 0;
00187 }
00188 }
00189 fsm->master_state = ec_fsm_master_start;
00190 fsm->master_state(fsm);
00191 return;
00192 }
00193
00194 topology_change = (datagram->working_counter !=
00195 fsm->master_slaves_responding);
00196 states_change = (EC_READ_U8(datagram->data) != fsm->master_slave_states);
00197
00198 fsm->master_slave_states = EC_READ_U8(datagram->data);
00199 fsm->master_slaves_responding = datagram->working_counter;
00200
00201 if (topology_change) {
00202 EC_INFO("%i slave%s responding.\n",
00203 fsm->master_slaves_responding,
00204 fsm->master_slaves_responding == 1 ? "" : "s");
00205
00206 if (master->mode == EC_MASTER_MODE_RUNNING) {
00207 if (fsm->master_slaves_responding == master->slave_count) {
00208 fsm->master_validation = 1;
00209 }
00210 else {
00211 EC_WARN("Invalid slave count. Bus in tainted state.\n");
00212 }
00213 }
00214 }
00215
00216 if (states_change) {
00217 EC_INFO("Slave states: ");
00218 ec_print_states(fsm->master_slave_states);
00219 printk(".\n");
00220 }
00221
00222
00223 if (topology_change && master->mode == EC_MASTER_MODE_IDLE) {
00224 EC_INFO("Scanning bus.\n");
00225
00226 ec_master_eoe_stop(master);
00227 ec_master_clear_slaves(master);
00228
00229 if (!fsm->master_slaves_responding) {
00230
00231 fsm->master_state = ec_fsm_master_start;
00232 fsm->master_state(fsm);
00233 return;
00234 }
00235
00236
00237 for (i = 0; i < fsm->master_slaves_responding; i++) {
00238 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t),
00239 GFP_ATOMIC))) {
00240 EC_ERR("Failed to allocate slave %i!\n", i);
00241 fsm->master_state = ec_fsm_master_start;
00242 fsm->master_state(fsm);
00243 return;
00244 }
00245
00246 if (ec_slave_init(slave, master, i, i + 1)) {
00247 fsm->master_state = ec_fsm_master_start;
00248 fsm->master_state(fsm);
00249 return;
00250 }
00251
00252 if (kobject_add(&slave->kobj)) {
00253 EC_ERR("Failed to add kobject.\n");
00254 kobject_put(&slave->kobj);
00255 fsm->master_state = ec_fsm_master_start;
00256 fsm->master_state(fsm);
00257 return;
00258 }
00259
00260 list_add_tail(&slave->list, &master->slaves);
00261 }
00262
00263
00264 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
00265 fsm->slave_state = ec_fsm_slavescan_start;
00266 fsm->master_state = ec_fsm_master_scan_slaves;
00267 fsm->master_state(fsm);
00268 return;
00269 }
00270
00271
00272 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
00273 ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address, 0x0130, 2);
00274 ec_master_queue_datagram(master, &fsm->datagram);
00275 fsm->master_state = ec_fsm_master_read_states;
00276 }
00277
00278
00279
00285 void ec_fsm_master_action_process_states(ec_fsm_t *fsm
00287 )
00288 {
00289 ec_master_t *master = fsm->master;
00290 ec_slave_t *slave;
00291
00292
00293 list_for_each_entry(slave, &master->slaves, list) {
00294 if (slave->error_flag ||
00295 !slave->online ||
00296 slave->requested_state == EC_SLAVE_STATE_UNKNOWN ||
00297 slave->current_state == slave->requested_state) continue;
00298
00299 EC_INFO("Changing state of slave %i from ", slave->ring_position);
00300 ec_print_states(slave->current_state);
00301 printk(" to ");
00302 ec_print_states(slave->requested_state);
00303 printk(".\n");
00304
00305 fsm->slave = slave;
00306 fsm->slave_state = ec_fsm_slaveconf_init;
00307 fsm->change_new = EC_SLAVE_STATE_INIT;
00308 fsm->change_state = ec_fsm_change_start;
00309 fsm->master_state = ec_fsm_master_configure_slave;
00310 fsm->master_state(fsm);
00311 return;
00312 }
00313
00314 if (master->mode == EC_MASTER_MODE_IDLE) {
00315
00316 list_for_each_entry(slave, &master->slaves, list) {
00317 if (!slave->new_eeprom_data) continue;
00318
00319 if (!slave->online || slave->error_flag) {
00320 kfree(slave->new_eeprom_data);
00321 slave->new_eeprom_data = NULL;
00322 EC_ERR("Discarding EEPROM data, slave %i not ready.\n",
00323 slave->ring_position);
00324 continue;
00325 }
00326
00327
00328 EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position);
00329 fsm->sii_offset = 0x0000;
00330 memcpy(fsm->sii_value, slave->new_eeprom_data, 2);
00331 fsm->sii_mode = 1;
00332 fsm->sii_state = ec_fsm_sii_start_writing;
00333 fsm->slave = slave;
00334 fsm->master_state = ec_fsm_master_write_eeprom;
00335 fsm->master_state(fsm);
00336 return;
00337 }
00338 }
00339
00340
00341 fsm->master_state = ec_fsm_master_start;
00342 fsm->master_state(fsm);
00343 }
00344
00345
00346
00351 void ec_fsm_master_action_next_slave_state(ec_fsm_t *fsm)
00353 {
00354 ec_master_t *master = fsm->master;
00355 ec_slave_t *slave = fsm->slave;
00356
00357
00358 if (slave->list.next != &master->slaves) {
00359
00360 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00361 ec_datagram_nprd(&fsm->datagram, fsm->slave->station_address,
00362 0x0130, 2);
00363 ec_master_queue_datagram(master, &fsm->datagram);
00364 fsm->master_state = ec_fsm_master_read_states;
00365 return;
00366 }
00367
00368
00369
00370
00371 if (fsm->master_validation) {
00372 fsm->master_validation = 0;
00373 list_for_each_entry(slave, &master->slaves, list) {
00374 if (slave->online) continue;
00375
00376
00377 EC_INFO("Validating bus.\n");
00378 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
00379 fsm->master_state = ec_fsm_master_validate_vendor;
00380 fsm->sii_offset = 0x0008;
00381 fsm->sii_mode = 0;
00382 fsm->sii_state = ec_fsm_sii_start_reading;
00383 fsm->sii_state(fsm);
00384 return;
00385 }
00386 }
00387
00388 ec_fsm_master_action_process_states(fsm);
00389 }
00390
00391
00392
00398 void ec_fsm_master_read_states(ec_fsm_t *fsm )
00399 {
00400 ec_slave_t *slave = fsm->slave;
00401 ec_datagram_t *datagram = &fsm->datagram;
00402 uint8_t new_state;
00403
00404 if (datagram->state != EC_CMD_RECEIVED) {
00405 fsm->master_state = ec_fsm_master_start;
00406 fsm->master_state(fsm);
00407 return;
00408 }
00409
00410
00411 if (datagram->working_counter != 1) {
00412 if (slave->online) {
00413 slave->online = 0;
00414 EC_INFO("Slave %i: offline.\n", slave->ring_position);
00415 }
00416 ec_fsm_master_action_next_slave_state(fsm);
00417 return;
00418 }
00419
00420
00421 new_state = EC_READ_U8(datagram->data);
00422 if (!slave->online) {
00423 slave->online = 1;
00424 slave->error_flag = 0;
00425 slave->current_state = new_state;
00426 EC_INFO("Slave %i: online (", slave->ring_position);
00427 ec_print_states(new_state);
00428 printk(").\n");
00429 }
00430 else if (new_state != slave->current_state) {
00431 EC_INFO("Slave %i: ", slave->ring_position);
00432 ec_print_states(slave->current_state);
00433 printk(" -> ");
00434 ec_print_states(new_state);
00435 printk(".\n");
00436 slave->current_state = new_state;
00437 }
00438
00439 ec_fsm_master_action_next_slave_state(fsm);
00440 }
00441
00442
00443
00449 void ec_fsm_master_validate_vendor(ec_fsm_t *fsm )
00450 {
00451 ec_slave_t *slave = fsm->slave;
00452
00453 fsm->sii_state(fsm);
00454
00455 if (fsm->sii_state == ec_fsm_sii_error) {
00456 fsm->slave->error_flag = 1;
00457 EC_ERR("Failed to validate vendor ID of slave %i.\n",
00458 slave->ring_position);
00459 fsm->master_state = ec_fsm_master_start;
00460 fsm->master_state(fsm);
00461 return;
00462 }
00463
00464 if (fsm->sii_state != ec_fsm_sii_end) return;
00465
00466 if (EC_READ_U32(fsm->sii_value) != slave->sii_vendor_id) {
00467 EC_ERR("Slave %i: invalid vendor ID!\n", slave->ring_position);
00468 fsm->master_state = ec_fsm_master_start;
00469 fsm->master_state(fsm);
00470 return;
00471 }
00472
00473
00474 fsm->master_state = ec_fsm_master_validate_product;
00475 fsm->sii_offset = 0x000A;
00476 fsm->sii_mode = 0;
00477 fsm->sii_state = ec_fsm_sii_start_reading;
00478 fsm->sii_state(fsm);
00479 }
00480
00481
00482
00489 void ec_fsm_master_action_addresses(ec_fsm_t *fsm )
00490 {
00491 ec_datagram_t *datagram = &fsm->datagram;
00492
00493 while (fsm->slave->online) {
00494 if (fsm->slave->list.next == &fsm->master->slaves) {
00495 fsm->master_state = ec_fsm_master_start;
00496 fsm->master_state(fsm);
00497 return;
00498 }
00499
00500 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00501 }
00502
00503 EC_INFO("Reinitializing slave %i.\n", fsm->slave->ring_position);
00504
00505
00506 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2);
00507 EC_WRITE_U16(datagram->data, fsm->slave->station_address);
00508 ec_master_queue_datagram(fsm->master, datagram);
00509 fsm->master_state = ec_fsm_master_rewrite_addresses;
00510 }
00511
00512
00513
00519 void ec_fsm_master_validate_product(ec_fsm_t *fsm )
00520 {
00521 ec_slave_t *slave = fsm->slave;
00522
00523 fsm->sii_state(fsm);
00524
00525 if (fsm->sii_state == ec_fsm_sii_error) {
00526 fsm->slave->error_flag = 1;
00527 EC_ERR("Failed to validate product code of slave %i.\n",
00528 slave->ring_position);
00529 fsm->master_state = ec_fsm_master_start;
00530 fsm->master_state(fsm);
00531 return;
00532 }
00533
00534 if (fsm->sii_state != ec_fsm_sii_end) return;
00535
00536 if (EC_READ_U32(fsm->sii_value) != slave->sii_product_code) {
00537 EC_ERR("Slave %i: invalid product code!\n", slave->ring_position);
00538 EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code,
00539 EC_READ_U32(fsm->sii_value));
00540 fsm->master_state = ec_fsm_master_start;
00541 fsm->master_state(fsm);
00542 return;
00543 }
00544
00545
00546 if (slave->list.next == &fsm->master->slaves) {
00547 fsm->slave = list_entry(fsm->master->slaves.next, ec_slave_t, list);
00548
00549 ec_fsm_master_action_addresses(fsm);
00550 return;
00551 }
00552
00553
00554 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00555 fsm->master_state = ec_fsm_master_validate_vendor;
00556 fsm->sii_offset = 0x0008;
00557 fsm->sii_mode = 0;
00558 fsm->sii_state = ec_fsm_sii_start_reading;
00559 fsm->sii_state(fsm);
00560 }
00561
00562
00563
00569 void ec_fsm_master_rewrite_addresses(ec_fsm_t *fsm
00571 )
00572 {
00573 ec_slave_t *slave = fsm->slave;
00574 ec_datagram_t *datagram = &fsm->datagram;
00575
00576 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
00577 EC_ERR("Failed to write station address on slave %i.\n",
00578 slave->ring_position);
00579 }
00580
00581 if (fsm->slave->list.next == &fsm->master->slaves) {
00582 fsm->master_state = ec_fsm_master_start;
00583 fsm->master_state(fsm);
00584 return;
00585 }
00586
00587
00588 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00589
00590 ec_fsm_master_action_addresses(fsm);
00591 }
00592
00593
00594
00600 void ec_fsm_master_scan_slaves(ec_fsm_t *fsm )
00601 {
00602 ec_master_t *master = fsm->master;
00603 ec_slave_t *slave = fsm->slave;
00604 uint16_t coupler_index, coupler_subindex;
00605 uint16_t reverse_coupler_index, current_coupler_index;
00606 ec_slave_ident_t *ident;
00607
00608 fsm->slave_state(fsm);
00609
00610 if (fsm->slave_state != ec_fsm_slavescan_end) return;
00611
00612
00613 if (slave->list.next == &master->slaves) {
00614 EC_INFO("Bus scanning completed.\n");
00615
00616
00617
00618 coupler_index = 0;
00619 reverse_coupler_index = 0xFFFF;
00620 current_coupler_index = 0x3FFF;
00621 coupler_subindex = 0;
00622
00623 list_for_each_entry(slave, &master->slaves, list)
00624 {
00625
00626 ident = slave_idents;
00627 while (ident->type) {
00628 if (ident->vendor_id == slave->sii_vendor_id
00629 && ident->product_code == slave->sii_product_code) {
00630 slave->type = ident->type;
00631 break;
00632 }
00633 ident++;
00634 }
00635
00636 if (!slave->type) {
00637 EC_WARN("Unknown slave device (vendor 0x%08X,"
00638 " code 0x%08X) at position %i.\n",
00639 slave->sii_vendor_id, slave->sii_product_code,
00640 slave->ring_position);
00641 }
00642 else {
00643
00644 if (slave->type->special == EC_TYPE_BUS_COUPLER) {
00645 if (slave->sii_alias)
00646 current_coupler_index = reverse_coupler_index--;
00647 else
00648 current_coupler_index = coupler_index++;
00649 coupler_subindex = 0;
00650 }
00651 }
00652
00653
00654 if ((slave->type &&
00655 (slave->type->special == EC_TYPE_BUS_COUPLER ||
00656 slave->type->special == EC_TYPE_INFRA))) {
00657 slave->requested_state = EC_SLAVE_STATE_OP;
00658 }
00659 else {
00660 if (master->mode == EC_MASTER_MODE_RUNNING)
00661 slave->requested_state = EC_SLAVE_STATE_PREOP;
00662 else
00663 slave->requested_state = EC_SLAVE_STATE_INIT;
00664 }
00665 slave->error_flag = 0;
00666
00667
00668 slave->coupler_index = current_coupler_index;
00669 slave->coupler_subindex = coupler_subindex;
00670 coupler_subindex++;
00671 }
00672
00673 if (master->mode == EC_MASTER_MODE_IDLE) {
00674
00675 ec_master_eoe_start(master);
00676 }
00677
00678 fsm->master_state = ec_fsm_master_start;
00679 fsm->master_state(fsm);
00680 return;
00681 }
00682
00683
00684 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list);
00685 fsm->slave_state = ec_fsm_slavescan_start;
00686 fsm->slave_state(fsm);
00687 }
00688
00689
00690
00696 void ec_fsm_master_configure_slave(ec_fsm_t *fsm
00698 )
00699 {
00700 fsm->slave_state(fsm);
00701 if (fsm->slave_state != ec_fsm_slaveconf_end) return;
00702
00703 ec_fsm_master_action_process_states(fsm);
00704 }
00705
00706
00707
00712 void ec_fsm_master_write_eeprom(ec_fsm_t *fsm )
00713 {
00714 ec_slave_t *slave = fsm->slave;
00715
00716 fsm->sii_state(fsm);
00717
00718 if (fsm->sii_state == ec_fsm_sii_error) {
00719 fsm->slave->error_flag = 1;
00720 EC_ERR("Failed to write EEPROM contents to slave %i.\n",
00721 slave->ring_position);
00722 kfree(slave->new_eeprom_data);
00723 slave->new_eeprom_data = NULL;
00724 fsm->master_state = ec_fsm_master_start;
00725 fsm->master_state(fsm);
00726 return;
00727 }
00728
00729 if (fsm->sii_state != ec_fsm_sii_end) return;
00730
00731 fsm->sii_offset++;
00732 if (fsm->sii_offset < slave->new_eeprom_size) {
00733 memcpy(fsm->sii_value, slave->new_eeprom_data + fsm->sii_offset, 2);
00734 fsm->sii_state = ec_fsm_sii_start_writing;
00735 fsm->sii_state(fsm);
00736 return;
00737 }
00738
00739
00740 EC_INFO("Finished writing EEPROM of slave %i.\n", slave->ring_position);
00741 kfree(slave->new_eeprom_data);
00742 slave->new_eeprom_data = NULL;
00743
00744
00745 fsm->master_state = ec_fsm_master_start;
00746 fsm->master_state(fsm);
00747 return;
00748 }
00749
00750
00751
00752
00753
00760 void ec_fsm_slavescan_start(ec_fsm_t *fsm )
00761 {
00762 ec_datagram_t *datagram = &fsm->datagram;
00763
00764
00765 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x0010, 2);
00766 EC_WRITE_U16(datagram->data, fsm->slave->station_address);
00767 ec_master_queue_datagram(fsm->master, datagram);
00768 fsm->slave_state = ec_fsm_slavescan_address;
00769 }
00770
00771
00772
00777 void ec_fsm_slavescan_address(ec_fsm_t *fsm )
00778 {
00779 ec_datagram_t *datagram = &fsm->datagram;
00780
00781 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
00782 fsm->slave->error_flag = 1;
00783 fsm->slave_state = ec_fsm_slavescan_end;
00784 EC_ERR("Failed to write station address of slave %i.\n",
00785 fsm->slave->ring_position);
00786 return;
00787 }
00788
00789
00790 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0130, 2);
00791 ec_master_queue_datagram(fsm->master, datagram);
00792 fsm->slave_state = ec_fsm_slavescan_state;
00793 }
00794
00795
00796
00801 void ec_fsm_slavescan_state(ec_fsm_t *fsm )
00802 {
00803 ec_datagram_t *datagram = &fsm->datagram;
00804 ec_slave_t *slave = fsm->slave;
00805
00806 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
00807 fsm->slave->error_flag = 1;
00808 fsm->slave_state = ec_fsm_slavescan_end;
00809 EC_ERR("Failed to read AL state of slave %i.\n",
00810 fsm->slave->ring_position);
00811 return;
00812 }
00813
00814 slave->current_state = EC_READ_U8(datagram->data);
00815 if (slave->current_state & EC_ACK) {
00816 EC_WARN("Slave %i has state error bit set (0x%02X)!\n",
00817 slave->ring_position, slave->current_state);
00818 slave->current_state &= 0x0F;
00819 }
00820
00821
00822 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x0000, 6);
00823 ec_master_queue_datagram(fsm->master, datagram);
00824 fsm->slave_state = ec_fsm_slavescan_base;
00825 }
00826
00827
00828
00833 void ec_fsm_slavescan_base(ec_fsm_t *fsm )
00834 {
00835 ec_datagram_t *datagram = &fsm->datagram;
00836 ec_slave_t *slave = fsm->slave;
00837
00838 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
00839 fsm->slave->error_flag = 1;
00840 fsm->slave_state = ec_fsm_slavescan_end;
00841 EC_ERR("Failed to read base data of slave %i.\n",
00842 slave->ring_position);
00843 return;
00844 }
00845
00846 slave->base_type = EC_READ_U8 (datagram->data);
00847 slave->base_revision = EC_READ_U8 (datagram->data + 1);
00848 slave->base_build = EC_READ_U16(datagram->data + 2);
00849 slave->base_fmmu_count = EC_READ_U8 (datagram->data + 4);
00850 slave->base_sync_count = EC_READ_U8 (datagram->data + 5);
00851
00852 if (slave->base_fmmu_count > EC_MAX_FMMUS)
00853 slave->base_fmmu_count = EC_MAX_FMMUS;
00854
00855
00856 ec_datagram_nprd(datagram, slave->station_address, 0x0110, 2);
00857 ec_master_queue_datagram(slave->master, datagram);
00858 fsm->slave_state = ec_fsm_slavescan_datalink;
00859 }
00860
00861
00862
00867 void ec_fsm_slavescan_datalink(ec_fsm_t *fsm )
00868 {
00869 ec_datagram_t *datagram = &fsm->datagram;
00870 ec_slave_t *slave = fsm->slave;
00871 uint16_t dl_status;
00872 unsigned int i;
00873
00874 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
00875 fsm->slave->error_flag = 1;
00876 fsm->slave_state = ec_fsm_slavescan_end;
00877 EC_ERR("Failed to read DL status of slave %i.\n",
00878 slave->ring_position);
00879 return;
00880 }
00881
00882 dl_status = EC_READ_U16(datagram->data);
00883 for (i = 0; i < 4; i++) {
00884 slave->dl_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0;
00885 slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
00886 slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
00887 }
00888
00889
00890
00891 fsm->sii_offset = 0x0040;
00892 fsm->sii_mode = 1;
00893 fsm->sii_state = ec_fsm_sii_start_reading;
00894 fsm->slave_state = ec_fsm_slavescan_eeprom_size;
00895 fsm->slave_state(fsm);
00896 }
00897
00898
00899
00904 void ec_fsm_slavescan_eeprom_size(ec_fsm_t *fsm )
00905 {
00906 ec_slave_t *slave = fsm->slave;
00907 uint16_t cat_type, cat_size;
00908
00909
00910 fsm->sii_state(fsm);
00911
00912 if (fsm->sii_state == ec_fsm_sii_error) {
00913 fsm->slave->error_flag = 1;
00914 fsm->slave_state = ec_fsm_slavescan_end;
00915 EC_ERR("Failed to read EEPROM size of slave %i.\n",
00916 slave->ring_position);
00917 return;
00918 }
00919
00920 if (fsm->sii_state != ec_fsm_sii_end) return;
00921
00922 cat_type = EC_READ_U16(fsm->sii_value);
00923 cat_size = EC_READ_U16(fsm->sii_value + 2);
00924
00925 if (cat_type != 0xFFFF) {
00926 fsm->sii_offset += cat_size + 2;
00927 fsm->sii_state = ec_fsm_sii_start_reading;
00928 fsm->sii_state(fsm);
00929 return;
00930 }
00931
00932 slave->eeprom_size = (fsm->sii_offset + 1) * 2;
00933
00934 if (slave->eeprom_data) {
00935 EC_INFO("Freeing old EEPROM data on slave %i...\n",
00936 slave->ring_position);
00937 kfree(slave->eeprom_data);
00938 }
00939
00940 if (!(slave->eeprom_data =
00941 (uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) {
00942 fsm->slave->error_flag = 1;
00943 fsm->slave_state = ec_fsm_slavescan_end;
00944 EC_ERR("Failed to allocate EEPROM data on slave %i.\n",
00945 slave->ring_position);
00946 return;
00947 }
00948
00949
00950
00951 fsm->sii_offset = 0x0000;
00952 fsm->sii_mode = 1;
00953 fsm->sii_state = ec_fsm_sii_start_reading;
00954 fsm->slave_state = ec_fsm_slavescan_eeprom_data;
00955 fsm->slave_state(fsm);
00956 }
00957
00958
00959
00964 void ec_fsm_slavescan_eeprom_data(ec_fsm_t *fsm )
00965 {
00966 ec_slave_t *slave = fsm->slave;
00967 uint16_t *cat_word, cat_type, cat_size;
00968
00969
00970 fsm->sii_state(fsm);
00971
00972 if (fsm->sii_state == ec_fsm_sii_error) {
00973 fsm->slave->error_flag = 1;
00974 fsm->slave_state = ec_fsm_slavescan_end;
00975 EC_ERR("Failed to fetch EEPROM contents of slave %i.\n",
00976 slave->ring_position);
00977 return;
00978 }
00979
00980 if (fsm->sii_state != ec_fsm_sii_end) return;
00981
00982
00983
00984 if (fsm->sii_offset + 2 <= slave->eeprom_size / 2) {
00985 memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_value, 4);
00986 }
00987 else {
00988 memcpy(slave->eeprom_data + fsm->sii_offset * 2, fsm->sii_value, 2);
00989 }
00990
00991 if (fsm->sii_offset + 2 < slave->eeprom_size / 2) {
00992
00993 fsm->sii_offset += 2;
00994 fsm->sii_state = ec_fsm_sii_start_reading;
00995 fsm->sii_state(fsm);
00996 return;
00997 }
00998
00999
01000
01001 slave->sii_alias =
01002 EC_READ_U16(slave->eeprom_data + 2 * 0x0004);
01003 slave->sii_vendor_id =
01004 EC_READ_U32(slave->eeprom_data + 2 * 0x0008);
01005 slave->sii_product_code =
01006 EC_READ_U32(slave->eeprom_data + 2 * 0x000A);
01007 slave->sii_revision_number =
01008 EC_READ_U32(slave->eeprom_data + 2 * 0x000C);
01009 slave->sii_serial_number =
01010 EC_READ_U32(slave->eeprom_data + 2 * 0x000E);
01011 slave->sii_rx_mailbox_offset =
01012 EC_READ_U16(slave->eeprom_data + 2 * 0x0018);
01013 slave->sii_rx_mailbox_size =
01014 EC_READ_U16(slave->eeprom_data + 2 * 0x0019);
01015 slave->sii_tx_mailbox_offset =
01016 EC_READ_U16(slave->eeprom_data + 2 * 0x001A);
01017 slave->sii_tx_mailbox_size =
01018 EC_READ_U16(slave->eeprom_data + 2 * 0x001B);
01019 slave->sii_mailbox_protocols =
01020 EC_READ_U16(slave->eeprom_data + 2 * 0x001C);
01021
01022
01023 cat_word = (uint16_t *) slave->eeprom_data + 0x0040;
01024 while (EC_READ_U16(cat_word) != 0xFFFF) {
01025 cat_type = EC_READ_U16(cat_word) & 0x7FFF;
01026 cat_size = EC_READ_U16(cat_word + 1);
01027
01028 switch (cat_type) {
01029 case 0x000A:
01030 if (ec_slave_fetch_strings(slave, (uint8_t *) (cat_word + 2)))
01031 goto end;
01032 break;
01033 case 0x001E:
01034 if (ec_slave_fetch_general(slave, (uint8_t *) (cat_word + 2)))
01035 goto end;
01036 break;
01037 case 0x0028:
01038 break;
01039 case 0x0029:
01040 if (ec_slave_fetch_sync(slave, (uint8_t *) (cat_word + 2),
01041 cat_size))
01042 goto end;
01043 break;
01044 case 0x0032:
01045 if (ec_slave_fetch_pdo(slave, (uint8_t *) (cat_word + 2),
01046 cat_size, EC_TX_PDO))
01047 goto end;
01048 break;
01049 case 0x0033:
01050 if (ec_slave_fetch_pdo(slave, (uint8_t *) (cat_word + 2),
01051 cat_size, EC_RX_PDO))
01052 goto end;
01053 break;
01054 default:
01055 EC_WARN("Unknown category type 0x%04X in slave %i.\n",
01056 cat_type, slave->ring_position);
01057 }
01058
01059 cat_word += cat_size + 2;
01060 }
01061
01062 fsm->slave_state = ec_fsm_slavescan_end;
01063
01064 end:
01065 fsm->slave->error_flag = 1;
01066 fsm->slave_state = ec_fsm_slavescan_end;
01067 }
01068
01069
01070
01076 void ec_fsm_slavescan_end(ec_fsm_t *fsm )
01077 {
01078 }
01079
01080
01081
01082
01083
01088 void ec_fsm_slaveconf_init(ec_fsm_t *fsm )
01089 {
01090 ec_slave_t *slave = fsm->slave;
01091 ec_datagram_t *datagram = &fsm->datagram;
01092 const ec_sync_t *sync;
01093 ec_eeprom_sync_t *eeprom_sync, mbox_sync;
01094 unsigned int j;
01095
01096 fsm->change_state(fsm);
01097
01098 if (fsm->change_state == ec_fsm_change_error) {
01099 slave->error_flag = 1;
01100 fsm->slave_state = ec_fsm_slaveconf_end;
01101 return;
01102 }
01103
01104 if (fsm->change_state != ec_fsm_change_end) return;
01105
01106
01107 if (slave->current_state == slave->requested_state) {
01108 fsm->slave_state = ec_fsm_slaveconf_end;
01109 return;
01110 }
01111
01112
01113 if (!slave->type) {
01114 EC_WARN("Slave %i has unknown type!\n", slave->ring_position);
01115 }
01116
01117
01118
01119
01120
01121 if (!slave->base_sync_count) {
01122 fsm->slave_state = ec_fsm_slaveconf_preop;
01123 fsm->change_new = EC_SLAVE_STATE_PREOP;
01124 fsm->change_state = ec_fsm_change_start;
01125 fsm->change_state(fsm);
01126 return;
01127 }
01128
01129
01130 ec_datagram_npwr(datagram, slave->station_address, 0x0800,
01131 EC_SYNC_SIZE * slave->base_sync_count);
01132 memset(datagram->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count);
01133
01134
01135 if (!list_empty(&slave->eeprom_syncs)) {
01136 list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) {
01137 if (eeprom_sync->index >= slave->base_sync_count) {
01138 fsm->slave->error_flag = 1;
01139 fsm->slave_state = ec_fsm_slaveconf_end;
01140 EC_ERR("Invalid sync manager configuration found!");
01141 return;
01142 }
01143 ec_eeprom_sync_config(eeprom_sync, slave,
01144 datagram->data + EC_SYNC_SIZE
01145 * eeprom_sync->index);
01146 }
01147 }
01148
01149
01150 else if (slave->type) {
01151 for (j = 0; slave->type->sync_managers[j] && j < EC_MAX_SYNC; j++) {
01152 sync = slave->type->sync_managers[j];
01153 ec_sync_config(sync, slave, datagram->data + EC_SYNC_SIZE * j);
01154 }
01155 }
01156
01157
01158 else if (slave->sii_mailbox_protocols)
01159 {
01160
01161 mbox_sync.physical_start_address =
01162 slave->sii_rx_mailbox_offset;
01163 mbox_sync.length = slave->sii_rx_mailbox_size;
01164 mbox_sync.control_register = 0x26;
01165 mbox_sync.enable = 1;
01166 ec_eeprom_sync_config(&mbox_sync, slave, datagram->data);
01167
01168 mbox_sync.physical_start_address =
01169 slave->sii_tx_mailbox_offset;
01170 mbox_sync.length = slave->sii_tx_mailbox_size;
01171 mbox_sync.control_register = 0x22;
01172 mbox_sync.enable = 1;
01173 ec_eeprom_sync_config(&mbox_sync, slave,
01174 datagram->data + EC_SYNC_SIZE);
01175
01176 EC_INFO("Mailbox configured for unknown slave %i\n",
01177 slave->ring_position);
01178 }
01179
01180 ec_master_queue_datagram(fsm->master, datagram);
01181 fsm->slave_state = ec_fsm_slaveconf_sync;
01182 }
01183
01184
01185
01190 void ec_fsm_slaveconf_sync(ec_fsm_t *fsm )
01191 {
01192 ec_datagram_t *datagram = &fsm->datagram;
01193 ec_slave_t *slave = fsm->slave;
01194
01195 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
01196 slave->error_flag = 1;
01197 fsm->slave_state = ec_fsm_slaveconf_end;
01198 EC_ERR("Failed to set sync managers on slave %i.\n",
01199 slave->ring_position);
01200 return;
01201 }
01202
01203 fsm->slave_state = ec_fsm_slaveconf_preop;
01204 fsm->change_new = EC_SLAVE_STATE_PREOP;
01205 fsm->change_state = ec_fsm_change_start;
01206 fsm->change_state(fsm);
01207 }
01208
01209
01210
01215 void ec_fsm_slaveconf_preop(ec_fsm_t *fsm )
01216 {
01217 ec_slave_t *slave = fsm->slave;
01218 ec_master_t *master = fsm->master;
01219 ec_datagram_t *datagram = &fsm->datagram;
01220 unsigned int j;
01221
01222 fsm->change_state(fsm);
01223
01224 if (fsm->change_state == ec_fsm_change_error) {
01225 slave->error_flag = 1;
01226 fsm->slave_state = ec_fsm_slaveconf_end;
01227 return;
01228 }
01229
01230 if (fsm->change_state != ec_fsm_change_end) return;
01231
01232
01233 if (slave->current_state == slave->requested_state) {
01234 fsm->slave_state = ec_fsm_slaveconf_end;
01235 return;
01236 }
01237
01238
01239 if (!slave->type) {
01240 fsm->slave_state = ec_fsm_slaveconf_end;
01241 return;
01242 }
01243
01244 if (!slave->base_fmmu_count) {
01245 fsm->slave_state = ec_fsm_slaveconf_saveop;
01246 fsm->change_new = EC_SLAVE_STATE_SAVEOP;
01247 fsm->change_state = ec_fsm_change_start;
01248 fsm->change_state(fsm);
01249 return;
01250 }
01251
01252
01253 ec_datagram_npwr(datagram, slave->station_address,
01254 0x0600, EC_FMMU_SIZE * slave->base_fmmu_count);
01255 memset(datagram->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
01256 for (j = 0; j < slave->fmmu_count; j++) {
01257 ec_fmmu_config(&slave->fmmus[j], slave,
01258 datagram->data + EC_FMMU_SIZE * j);
01259 }
01260
01261 ec_master_queue_datagram(master, datagram);
01262 fsm->slave_state = ec_fsm_slaveconf_fmmu;
01263 }
01264
01265
01266
01271 void ec_fsm_slaveconf_fmmu(ec_fsm_t *fsm )
01272 {
01273 ec_datagram_t *datagram = &fsm->datagram;
01274
01275 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
01276 fsm->slave->error_flag = 1;
01277 fsm->slave_state = ec_fsm_slaveconf_end;
01278 EC_ERR("Failed to set FMMUs on slave %i.\n",
01279 fsm->slave->ring_position);
01280 return;
01281 }
01282
01283
01284 fsm->slave_state = ec_fsm_slaveconf_saveop;
01285 fsm->change_new = EC_SLAVE_STATE_SAVEOP;
01286 fsm->change_state = ec_fsm_change_start;
01287 fsm->change_state(fsm);
01288 }
01289
01290
01291
01296 void ec_fsm_slaveconf_saveop(ec_fsm_t *fsm )
01297 {
01298 fsm->change_state(fsm);
01299
01300 if (fsm->change_state == ec_fsm_change_error) {
01301 fsm->slave->error_flag = 1;
01302 fsm->slave_state = ec_fsm_slaveconf_end;
01303 return;
01304 }
01305
01306 if (fsm->change_state != ec_fsm_change_end) return;
01307
01308
01309 if (fsm->slave->current_state == fsm->slave->requested_state) {
01310 fsm->slave_state = ec_fsm_slaveconf_end;
01311 return;
01312 }
01313
01314
01315 fsm->slave_state = ec_fsm_slaveconf_op;
01316 fsm->change_new = EC_SLAVE_STATE_OP;
01317 fsm->change_state = ec_fsm_change_start;
01318 fsm->change_state(fsm);
01319 }
01320
01321
01322
01327 void ec_fsm_slaveconf_op(ec_fsm_t *fsm )
01328 {
01329 fsm->change_state(fsm);
01330
01331 if (fsm->change_state == ec_fsm_change_error) {
01332 fsm->slave->error_flag = 1;
01333 fsm->slave_state = ec_fsm_slaveconf_end;
01334 return;
01335 }
01336
01337 if (fsm->change_state != ec_fsm_change_end) return;
01338
01339
01340 fsm->slave_state = ec_fsm_slaveconf_end;
01341 }
01342
01343
01344
01350 void ec_fsm_slaveconf_end(ec_fsm_t *fsm )
01351 {
01352 }
01353
01354
01355
01356
01357
01363 void ec_fsm_sii_start_reading(ec_fsm_t *fsm )
01364 {
01365 ec_datagram_t *datagram = &fsm->datagram;
01366
01367
01368 if (fsm->sii_mode) {
01369 ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 4);
01370 }
01371 else {
01372 ec_datagram_apwr(datagram, fsm->slave->ring_position, 0x502, 4);
01373 }
01374
01375 EC_WRITE_U8 (datagram->data, 0x00);
01376 EC_WRITE_U8 (datagram->data + 1, 0x01);
01377 EC_WRITE_U16(datagram->data + 2, fsm->sii_offset);
01378 ec_master_queue_datagram(fsm->master, datagram);
01379 fsm->sii_state = ec_fsm_sii_read_check;
01380 }
01381
01382
01383
01389 void ec_fsm_sii_read_check(ec_fsm_t *fsm )
01390 {
01391 ec_datagram_t *datagram = &fsm->datagram;
01392
01393 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
01394 EC_ERR("SII: Reception of read datagram failed.\n");
01395 fsm->sii_state = ec_fsm_sii_error;
01396 return;
01397 }
01398
01399 fsm->sii_start = get_cycles();
01400
01401
01402 if (fsm->sii_mode) {
01403 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10);
01404 }
01405 else {
01406 ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10);
01407 }
01408
01409 ec_master_queue_datagram(fsm->master, datagram);
01410 fsm->sii_state = ec_fsm_sii_read_fetch;
01411 }
01412
01413
01414
01420 void ec_fsm_sii_read_fetch(ec_fsm_t *fsm )
01421 {
01422 ec_datagram_t *datagram = &fsm->datagram;
01423
01424 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
01425 EC_ERR("SII: Reception of check/fetch datagram failed.\n");
01426 fsm->sii_state = ec_fsm_sii_error;
01427 return;
01428 }
01429
01430
01431 if (EC_READ_U8(datagram->data + 1) & 0x81) {
01432
01433 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) {
01434 EC_ERR("SII: Timeout.\n");
01435 fsm->sii_state = ec_fsm_sii_error;
01436 #if 0
01437 EC_DBG("SII busy: %02X %02X %02X %02X\n",
01438 EC_READ_U8(datagram->data + 0),
01439 EC_READ_U8(datagram->data + 1),
01440 EC_READ_U8(datagram->data + 2),
01441 EC_READ_U8(datagram->data + 3));
01442 #endif
01443 }
01444
01445
01446 if (fsm->sii_mode) {
01447 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 10);
01448 }
01449 else {
01450 ec_datagram_aprd(datagram, fsm->slave->ring_position, 0x502, 10);
01451 }
01452 ec_master_queue_datagram(fsm->master, datagram);
01453 return;
01454 }
01455
01456 #if 0
01457 EC_DBG("SII rec: %02X %02X %02X %02X - %02X %02X %02X %02X\n",
01458 EC_READ_U8(datagram->data + 0), EC_READ_U8(datagram->data + 1),
01459 EC_READ_U8(datagram->data + 2), EC_READ_U8(datagram->data + 3),
01460 EC_READ_U8(datagram->data + 6), EC_READ_U8(datagram->data + 7),
01461 EC_READ_U8(datagram->data + 8), EC_READ_U8(datagram->data + 9));
01462 #endif
01463
01464
01465 memcpy(fsm->sii_value, datagram->data + 6, 4);
01466 fsm->sii_state = ec_fsm_sii_end;
01467 }
01468
01469
01470
01476 void ec_fsm_sii_start_writing(ec_fsm_t *fsm )
01477 {
01478 ec_datagram_t *datagram = &fsm->datagram;
01479
01480
01481 ec_datagram_npwr(datagram, fsm->slave->station_address, 0x502, 8);
01482 EC_WRITE_U8 (datagram->data, 0x01);
01483 EC_WRITE_U8 (datagram->data + 1, 0x02);
01484 EC_WRITE_U32(datagram->data + 2, fsm->sii_offset);
01485 memcpy(datagram->data + 6, fsm->sii_value, 2);
01486 ec_master_queue_datagram(fsm->master, datagram);
01487 fsm->sii_state = ec_fsm_sii_write_check;
01488 }
01489
01490
01491
01496 void ec_fsm_sii_write_check(ec_fsm_t *fsm )
01497 {
01498 ec_datagram_t *datagram = &fsm->datagram;
01499
01500 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
01501 EC_ERR("SII: Reception of write datagram failed.\n");
01502 fsm->sii_state = ec_fsm_sii_error;
01503 return;
01504 }
01505
01506 fsm->sii_start = get_cycles();
01507
01508
01509 ec_datagram_nprd(datagram, fsm->slave->station_address, 0x502, 2);
01510 ec_master_queue_datagram(fsm->master, datagram);
01511 fsm->sii_state = ec_fsm_sii_write_check2;
01512 }
01513
01514
01515
01520 void ec_fsm_sii_write_check2(ec_fsm_t *fsm )
01521 {
01522 ec_datagram_t *datagram = &fsm->datagram;
01523
01524 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
01525 EC_ERR("SII: Reception of write check datagram failed.\n");
01526 fsm->sii_state = ec_fsm_sii_error;
01527 return;
01528 }
01529
01530 if (EC_READ_U8(datagram->data + 1) & 0x82) {
01531
01532 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) {
01533 EC_ERR("SII: Write timeout.\n");
01534 fsm->sii_state = ec_fsm_sii_error;
01535 }
01536
01537
01538 ec_master_queue_datagram(fsm->master, datagram);
01539 }
01540 else if (EC_READ_U8(datagram->data + 1) & 0x40) {
01541 EC_ERR("SII: Write operation failed!\n");
01542 fsm->sii_state = ec_fsm_sii_error;
01543 }
01544 else {
01545 fsm->sii_state = ec_fsm_sii_end;
01546 }
01547 }
01548
01549
01550
01556 void ec_fsm_sii_end(ec_fsm_t *fsm )
01557 {
01558 }
01559
01560
01561
01567 void ec_fsm_sii_error(ec_fsm_t *fsm )
01568 {
01569 }
01570
01571
01572
01573
01574
01579 void ec_fsm_change_start(ec_fsm_t *fsm )
01580 {
01581 ec_datagram_t *datagram = &fsm->datagram;
01582 ec_slave_t *slave = fsm->slave;
01583
01584
01585 ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2);
01586 EC_WRITE_U16(datagram->data, fsm->change_new);
01587 ec_master_queue_datagram(fsm->master, datagram);
01588 fsm->change_state = ec_fsm_change_check;
01589 }
01590
01591
01592
01597 void ec_fsm_change_check(ec_fsm_t *fsm )
01598 {
01599 ec_datagram_t *datagram = &fsm->datagram;
01600 ec_slave_t *slave = fsm->slave;
01601
01602 if (datagram->state != EC_CMD_RECEIVED) {
01603 fsm->change_state = ec_fsm_change_error;
01604 EC_ERR("Failed to send state datagram to slave %i!\n",
01605 fsm->slave->ring_position);
01606 return;
01607 }
01608
01609 if (datagram->working_counter != 1) {
01610 fsm->change_state = ec_fsm_change_error;
01611 EC_ERR("Failed to set state 0x%02X on slave %i: Slave did not"
01612 " respond.\n", fsm->change_new, fsm->slave->ring_position);
01613 return;
01614 }
01615
01616 fsm->change_start = get_cycles();
01617
01618
01619 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
01620 ec_master_queue_datagram(fsm->master, datagram);
01621 fsm->change_state = ec_fsm_change_status;
01622 }
01623
01624
01625
01630 void ec_fsm_change_status(ec_fsm_t *fsm )
01631 {
01632 ec_datagram_t *datagram = &fsm->datagram;
01633 ec_slave_t *slave = fsm->slave;
01634
01635 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
01636 fsm->change_state = ec_fsm_change_error;
01637 EC_ERR("Failed to check state 0x%02X on slave %i.\n",
01638 fsm->change_new, slave->ring_position);
01639 return;
01640 }
01641
01642 slave->current_state = EC_READ_U8(datagram->data);
01643
01644 if (slave->current_state == fsm->change_new) {
01645
01646 fsm->change_state = ec_fsm_change_end;
01647 return;
01648 }
01649
01650 if (slave->current_state & 0x10) {
01651
01652 fsm->change_new = slave->current_state & 0x0F;
01653 EC_ERR("Failed to set state 0x%02X - Slave %i refused state change"
01654 " (code 0x%02X)!\n", fsm->change_new, slave->ring_position,
01655 slave->current_state);
01656
01657 ec_datagram_nprd(datagram, slave->station_address, 0x0134, 2);
01658 ec_master_queue_datagram(fsm->master, datagram);
01659 fsm->change_state = ec_fsm_change_code;
01660 return;
01661 }
01662
01663 if (get_cycles() - fsm->change_start >= (cycles_t) 10 * cpu_khz) {
01664
01665 fsm->change_state = ec_fsm_change_error;
01666 EC_ERR("Timeout while setting state 0x%02X on slave %i.\n",
01667 fsm->change_new, slave->ring_position);
01668 return;
01669 }
01670
01671
01672 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
01673 ec_master_queue_datagram(fsm->master, datagram);
01674 }
01675
01676
01677
01682 const ec_code_msg_t al_status_messages[] = {
01683 {0x0001, "Unspecified error"},
01684 {0x0011, "Invalud requested state change"},
01685 {0x0012, "Unknown requested state"},
01686 {0x0013, "Bootstrap not supported"},
01687 {0x0014, "No valid firmware"},
01688 {0x0015, "Invalid mailbox configuration"},
01689 {0x0016, "Invalid mailbox configuration"},
01690 {0x0017, "Invalid sync manager configuration"},
01691 {0x0018, "No valid inputs available"},
01692 {0x0019, "No valid outputs"},
01693 {0x001A, "Synchronisation error"},
01694 {0x001B, "Sync manager watchdog"},
01695 {0x001C, "Invalid sync manager types"},
01696 {0x001D, "Invalid output configuration"},
01697 {0x001E, "Invalid input configuration"},
01698 {0x001F, "Invalid watchdog configuration"},
01699 {0x0020, "Slave needs cold start"},
01700 {0x0021, "Slave needs INIT"},
01701 {0x0022, "Slave needs PREOP"},
01702 {0x0023, "Slave needs SAVEOP"},
01703 {0x0030, "Invalid DC SYNCH configuration"},
01704 {0x0031, "Invalid DC latch configuration"},
01705 {0x0032, "PLL error"},
01706 {0x0033, "Invalid DC IO error"},
01707 {0x0034, "Invalid DC timeout error"},
01708 {0x0042, "MBOX EOE"},
01709 {0x0043, "MBOX COE"},
01710 {0x0044, "MBOX FOE"},
01711 {0x0045, "MBOX SOE"},
01712 {0x004F, "MBOX VOE"},
01713 {}
01714 };
01715
01716
01717
01722 void ec_fsm_change_code(ec_fsm_t *fsm )
01723 {
01724 ec_datagram_t *datagram = &fsm->datagram;
01725 ec_slave_t *slave = fsm->slave;
01726 uint32_t code;
01727 const ec_code_msg_t *al_msg;
01728
01729 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
01730 fsm->change_state = ec_fsm_change_error;
01731 EC_ERR("Reception of AL status code datagram failed.\n");
01732 return;
01733 }
01734
01735 if ((code = EC_READ_U16(datagram->data))) {
01736 for (al_msg = al_status_messages; al_msg->code; al_msg++) {
01737 if (al_msg->code != code) continue;
01738 EC_ERR("AL status message 0x%04X: \"%s\".\n",
01739 al_msg->code, al_msg->message);
01740 break;
01741 }
01742 if (!al_msg->code)
01743 EC_ERR("Unknown AL status code 0x%04X.\n", code);
01744 }
01745
01746
01747 ec_datagram_npwr(datagram, slave->station_address, 0x0120, 2);
01748 EC_WRITE_U16(datagram->data, slave->current_state);
01749 ec_master_queue_datagram(fsm->master, datagram);
01750 fsm->change_state = ec_fsm_change_ack;
01751 }
01752
01753
01754
01759 void ec_fsm_change_ack(ec_fsm_t *fsm )
01760 {
01761 ec_datagram_t *datagram = &fsm->datagram;
01762 ec_slave_t *slave = fsm->slave;
01763
01764 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
01765 fsm->change_state = ec_fsm_change_error;
01766 EC_ERR("Reception of state ack datagram failed.\n");
01767 return;
01768 }
01769
01770 fsm->change_start = get_cycles();
01771
01772
01773 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
01774 ec_master_queue_datagram(fsm->master, datagram);
01775 fsm->change_state = ec_fsm_change_check_ack;
01776 }
01777
01778
01779
01784 void ec_fsm_change_check_ack(ec_fsm_t *fsm )
01785 {
01786 ec_datagram_t *datagram = &fsm->datagram;
01787 ec_slave_t *slave = fsm->slave;
01788 ec_slave_state_t ack_state;
01789
01790 if (datagram->state != EC_CMD_RECEIVED || datagram->working_counter != 1) {
01791 fsm->change_state = ec_fsm_change_error;
01792 EC_ERR("Reception of state ack check datagram failed.\n");
01793 return;
01794 }
01795
01796 ack_state = EC_READ_U8(datagram->data);
01797
01798 if (ack_state == slave->current_state) {
01799 fsm->change_state = ec_fsm_change_error;
01800 EC_INFO("Acknowleged state 0x%02X on slave %i.\n",
01801 slave->current_state, slave->ring_position);
01802 return;
01803 }
01804
01805 if (get_cycles() - fsm->change_start >= (cycles_t) 100 * cpu_khz) {
01806
01807 slave->current_state = EC_SLAVE_STATE_UNKNOWN;
01808 fsm->change_state = ec_fsm_change_error;
01809 EC_ERR("Timeout while acknowleging state 0x%02X on slave %i.\n",
01810 fsm->change_new, slave->ring_position);
01811 return;
01812 }
01813
01814
01815 ec_datagram_nprd(datagram, slave->station_address, 0x0130, 2);
01816 ec_master_queue_datagram(fsm->master, datagram);
01817 }
01818
01819
01820
01825 void ec_fsm_change_end(ec_fsm_t *fsm )
01826 {
01827 }
01828
01829
01830
01835 void ec_fsm_change_error(ec_fsm_t *fsm )
01836 {
01837 }
01838
01839