static int sff_8431_open(struct nfp_phymod *phy) { struct nfp_phymod_priv *priv = phy->priv; struct sff_8431 *sff; int err; sff = kzalloc(sizeof(*sff), GFP_KERNEL); if (!sff) return -ENOMEM; sff->selected = 0; err = _phymod_get_attr_pin(phy, "pin.present", &sff->in.present); if (err < 0) goto exit; err = _phymod_get_attr_pin(phy, "pin.tx_fault", &sff->in.tx_fault); if (err < 0) goto exit; err = _phymod_get_attr_pin(phy, "pin.rx_los", &sff->in.rx_los); if (err < 0) goto exit; err = _phymod_get_attr_pin(phy, "pin.tx_disable", &sff->out.tx_disable); if (err < 0) goto exit; err = pin_direction(priv->nfp, &sff->in.present, 0); if (err < 0) goto exit; err = pin_direction(priv->nfp, &sff->in.tx_fault, 0); if (err < 0) goto exit; err = pin_direction(priv->nfp, &sff->in.rx_los, 0); if (err < 0) goto exit; err = pin_direction(priv->nfp, &sff->out.tx_disable, 1); if (err < 0) goto exit; err = _phymod_get_attr_bus(phy, "SFF-8431", &sff->bus[0]); if (err < 0) goto exit; err = _phymod_get_attr_bus(phy, "SFF-8472", &sff->bus[1]); /* Optional, so err is not checked */ if (err < 0) { err = 0; sff->bus[1].op = NULL; } phy->sff.priv = sff; return 0; exit: kfree(sff); return err; }
/* * Generate all moves that evade check in the given position. This is purely * legal move generation; no pseudo-legal moves. */ int generate_evasions(const position_t* pos, move_t* moves) { assert(pos->is_check && pos->board[pos->check_square]); move_t* moves_head = moves; color_t side = pos->side_to_move, other_side = side^1; square_t king_sq = pos->pieces[side][0]; square_t check_sq = pos->check_square; piece_t king = create_piece(side, KING); piece_t checker = pos->board[check_sq]; // Generate king moves. // Don't let the king mask its possible destination squares in calls // to is_square_attacked. square_t from = king_sq, to = INVALID_SQUARE; ((position_t*)pos)->board[king_sq] = EMPTY; for (const direction_t* delta = piece_deltas[king]; *delta; ++delta) { to = from + *delta; piece_t capture = pos->board[to]; if (capture != EMPTY && !can_capture(king, capture)) continue; if (is_square_attacked((position_t*)pos,to,other_side)) continue; ((position_t*)pos)->board[king_sq] = king; moves = add_move(pos, create_move(from, to, king, capture), moves); ((position_t*)pos)->board[king_sq] = EMPTY; } ((position_t*)pos)->board[king_sq] = king; // If there are multiple checkers, only king moves are possible. if (pos->is_check > 1) { *moves = 0; return moves-moves_head; } // First, the most common case: a check that can be evaded via an // en passant capture. Note that if we're in check and an en passant // capture is available, the only way the en passant capture would evade // the check is if it's the newly moved pawn that's checking us. direction_t pin_dir; if (pos->ep_square != EMPTY && check_sq+pawn_push[side] == pos->ep_square && pos->board[pos->ep_square] == EMPTY) { piece_t our_pawn = create_piece(side, PAWN); to = pos->ep_square; for (int i=0; i<2; ++i) { from = to-piece_deltas[our_pawn][i]; if (pos->board[from] && pos->board[from] == our_pawn) { pin_dir = pin_direction(pos, from, king_sq); if (pin_dir) continue; moves = add_move(pos, create_move_enpassant(from, to, our_pawn, checker), moves); } } } // Generate captures of the checker. for (int i = 0; i < pos->num_pawns[side]; ++i) { from = pos->pawns[side][i]; piece_t piece = create_piece(side, PAWN); pin_dir = pin_direction(pos, from, king_sq); if (pin_dir) continue; if (!possible_attack(from, check_sq, piece)) continue; if (relative_rank[side][square_rank(from)] == RANK_7) { // Capture and promote. for (piece_t promoted=QUEEN; promoted > PAWN; --promoted) { moves = add_move(pos, create_move_promote(from, check_sq, piece, checker, promoted), moves); } } else { moves = add_move(pos, create_move(from, check_sq, piece, checker), moves); } } for (int i = 1; i < pos->num_pieces[side]; ++i) { from = pos->pieces[side][i]; piece_t piece = pos->board[from]; pin_dir = pin_direction(pos, from, king_sq); if (pin_dir) continue; if (!possible_attack(from, check_sq, piece)) continue; if (piece_slide_type(piece) == NONE) { moves = add_move(pos, create_move(from, check_sq, piece, checker), moves); } else { // A sliding piece, keep going until we hit something. direction_t check_dir = direction(from, check_sq); for (to=from+check_dir; pos->board[to] == EMPTY; to+=check_dir) {} if (to == check_sq) { moves = add_move(pos, create_move(from, to, piece, checker), moves); continue; } } } if (piece_slide_type(checker) == NONE) { *moves = 0; return moves-moves_head; } // A slider is doing the checking; generate blocking moves. direction_t block_dir = direction(check_sq, king_sq); for (int i = 0; i < pos->num_pawns[side]; ++i) { from = pos->pawns[side][i]; piece_t piece = create_piece(side, PAWN); direction_t k_dir; pin_dir = pin_direction(pos, from, king_sq); if (pin_dir) continue; to = from + pawn_push[side]; if (pos->board[to] != EMPTY) continue; rank_t rank = relative_rank[side][square_rank(from)]; k_dir = direction(to, king_sq); if (k_dir == block_dir && ((king_sq < to && check_sq > to) || (king_sq > to && check_sq < to))) { if (rank == RANK_7) { // Block and promote. for (piece_t promoted=QUEEN; promoted > PAWN; --promoted) { moves = add_move(pos, create_move_promote(from, to, piece, EMPTY, promoted), moves); } } else { moves = add_move(pos, create_move(from, to, piece, EMPTY), moves); } } if (rank != RANK_2) continue; to += pawn_push[side]; if (pos->board[to]) continue; k_dir = direction(to, king_sq); if (k_dir == block_dir && ((king_sq < to && check_sq > to) || (king_sq > to && check_sq < to))) { moves = add_move(pos, create_move(from, to, piece, EMPTY), moves); } } for (int i=1; i<pos->num_pieces[side]; ++i) { from = pos->pieces[side][i]; piece_t piece = pos->board[from]; direction_t k_dir; pin_dir = pin_direction(pos, from, king_sq); if (pin_dir) continue; if (piece_is_type(piece, KNIGHT)) { for (const direction_t* delta=piece_deltas[piece]; *delta; ++delta) { to = from + *delta; if (pos->board[to] != EMPTY) continue; k_dir = direction(to, king_sq); if (k_dir == block_dir && ((king_sq < to && check_sq > to) || (king_sq > to && check_sq < to))) { moves = add_move(pos, create_move(from, to, piece, EMPTY), moves); } } } else { for (const direction_t* delta=piece_deltas[piece]; *delta; ++delta) { for (to = from+*delta; pos->board[to] == EMPTY; to+=*delta) { k_dir = direction(to, king_sq); if (k_dir == block_dir && ((king_sq < to && check_sq > to) || (king_sq > to && check_sq < to))) { moves = add_move(pos, create_move(from, to, piece, EMPTY), moves); break; } } } } } *moves = 0; return moves-moves_head; }